1/** 2 * TASK-0125 — RAG workspace search DTO (zod; validated by `ZodValidate`). 3 * 4 * Body: `{ query, context? }` (the spec's query-path contract). `query` is 5 * the question (1–1000 chars); `context.types` is the search page's type 6 * chips (optional metadata filter — see the recorded chunk-vs-types conflict 7 * in the task file: the kNN leg cannot filter chunk docs by their parent's 8 * public type, so `types` narrows the keyword leg + the de-dup only). 9 */ 10import { z } from "zod"; 11import { SEARCH_TYPES } from "@factory/search"; 12 13const isSearchType = (v: string): boolean => (SEARCH_TYPES as readonly string[]).includes(v); 14 15export const RagSearchDto = z.object({ 16 /** The question (the answer is streamed; the query is embedded + BM25'd). */ 17 query: z.string().trim().min(1, "query is required").max(1000), 18 /** Optional metadata filters from the search page's chips. */ 19 context: z 20 .object({ 21 /** Restrict to these content types (the public SearchType set). */ 22 types: z.array(z.string().refine(isSearchType, { message: "unknown content type" })).min(1).optional(), 23 }) 24 .optional(), 25}); 26export type RagSearchInput = z.infer<typeof RagSearchDto>; 27