1/** 2 * TASK-0123 — AI writing tools DTOs (zod; validated by `ZodValidate`). 3 * 4 * Limits (spec §Limits): ≤50 blocks (422 — also re-checked in the service, 5 * where it is the 422-with-details path), selected text ≤100k chars (413 — 6 * the assembler's check, since the server assembles the content), language 7 * ≤64 chars (trim + cap; the UI constrains it too), action = the spec's 8 * four tools. 9 */ 10import { z } from "zod"; 11 12import { WRITING_ACTIONS } from "./prompts.js"; 13 14// NOTE: the >50 cap is intentionally NOT a zod refine (that would be a 400 15// VALIDATION_ERROR); the service returns the spec's 422 with details. 16export const AiWritingDto = z.object({ 17 /** The selected block IDs (duplicates are de-duped server-side; the >50 18 * cap is the service's 422 `too_many_blocks` check, per spec §Limits). */ 19 blockIds: z.array(z.string().min(1)).min(1), 20 /** The anchor page the selection is rendered on (UI provenance; the 21 * blocks' own pages carry the permission checks). */ 22 pageId: z.string().min(1), 23 /** The writing action (the spec's four tools). */ 24 action: z.enum(WRITING_ACTIONS), 25 /** Target language for `translate` (trim + cap 64; ignored otherwise). */ 26 language: z.string().trim().max(64).optional(), 27}); 28export type AiWritingInput = z.infer<typeof AiWritingDto>; 29 30export const ApplyWritingDto = z.object({ 31 /** The assistant message id from the stream's `done.assistantMessageId`. */ 32 suggestionId: z.string().min(1), 33 /** Subset of the suggestion's blockIds ("accept one"); omitted = all. 34 * Must be a subset — unknown ids are a 422 (no smuggling). */ 35 blockIds: z.array(z.string().min(1)).min(1).optional(), 36}); 37export type ApplyWritingInput = z.infer<typeof ApplyWritingDto>; 38