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