/** * @factory/shared — AI DTOs (PRODUCT-SPEC §21). */ import { z } from "zod"; export const chatRoleSchema = z.enum(["system", "user", "assistant", "tool"]); export type ChatRole = z.infer; /** A tool call requested by the model (structured tool calls, never raw SQL). */ export const chatToolCallSchema = z .object({ id: z.string().min(1), name: z.string().min(1), arguments: z.record(z.unknown()), }) .strict(); export type ChatToolCall = z.infer; export const chatMessageSchema = z .object({ role: chatRoleSchema, content: z.string(), toolCalls: z.array(chatToolCallSchema).optional(), /** Result fed back for a tool call (role=tool). */ toolResults: z .array( z .object({ toolCallId: z.string().min(1), content: z.string(), }) .strict(), ) .optional(), }) .strict(); export type ChatMessage = z.infer; export const chatContextSchema = z .object({ /** Page or database ids whose content is retrieved (RAG). */ pageIds: z.array(z.string().min(1)).max(10).optional(), databaseIds: z.array(z.string().min(1)).max(10).optional(), /** Pre-retrieved context chunks: {id, title, text}. */ chunks: z .array( z .object({ id: z.string().min(1), title: z.string().max(200).default(""), text: z.string().min(1), }) .strict(), ) .max(25) .optional(), }) .strict(); export type ChatContext = z.infer; export const chatRequestSchema = z .object({ messages: z.array(chatMessageSchema).min(1, "At least one message is required").max(200), context: chatContextSchema.optional(), /** Model override; defaults to the workspace/platform model. */ model: z.string().min(1).max(128).optional(), temperature: z.number().min(0).max(2).optional(), maxTokens: z.number().int().min(1).max(32_000).optional(), stream: z.boolean().default(false), }) .strict(); export type ChatRequest = z.infer;