@miraiclip/assistant 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/index.cjs +727 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +350 -23
- package/dist/index.d.ts +350 -23
- package/dist/index.js +727 -62
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/openai.ts","../src/http.ts","../src/limits.ts","../src/state.ts","../src/strict.ts","../src/tools.ts","../src/fork.ts","../src/run.ts","../src/testing.ts"],"sourcesContent":["/**\n * The vendor-neutral model contract. An adapter turns these neutral messages\n * and tools into one vendor's API and back; nothing else in the package knows\n * which vendor is on the other end.\n */\n\n/** A tool call the model made. `arguments` is already parsed JSON. */\nexport interface ToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}\n\nexport type ChatMessage =\n | { role: \"system\"; content: string }\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string; toolCalls?: ToolCall[] }\n | { role: \"tool\"; toolCallId: string; name: string; content: string };\n\n/** A tool as the model sees it: name, description and a JSON Schema for its input. */\nexport interface ToolSpec {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ChatRequest {\n messages: ChatMessage[];\n tools?: ToolSpec[];\n /** Model id, when the adapter serves several. */\n model?: string;\n maxOutputTokens?: number;\n /** Vendor-specific request fields, passed through untouched (e.g. `{ reasoning_effort: \"low\" }`). */\n params?: Record<string, unknown>;\n}\n\nexport interface ChatUsage {\n inputTokens?: number;\n outputTokens?: number;\n}\n\nexport interface ChatResponse {\n content: string;\n toolCalls: ToolCall[];\n /** Why the model stopped. */\n finish: \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"other\";\n model?: string;\n usage?: ChatUsage;\n}\n\nexport interface ChatOptions {\n signal?: AbortSignal;\n /** Streaming text, as it arrives (adapters that can't stream call it once). */\n onText?: (delta: string) => void;\n}\n\nexport interface ChatModelInfo {\n /** Adapter id, e.g. \"openai\". Alphanumeric with - or _. */\n id: string;\n label: string;\n /** Models this adapter serves; the first is the default. */\n models?: { id: string; label?: string }[];\n}\n\nexport interface ChatModel extends ChatModelInfo {\n complete(request: ChatRequest, options?: ChatOptions): Promise<ChatResponse>;\n}\n\n/** An error from a model vendor, carrying its HTTP status when there was one. */\nexport class ChatModelError extends Error {\n constructor(\n readonly provider: string,\n message: string,\n readonly status?: number,\n ) {\n super(`${provider}: ${message}`);\n this.name = \"ChatModelError\";\n }\n}\n\nexport type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;\n\nexport function defaultFetch(): FetchLike {\n if (typeof fetch !== \"function\") throw new Error(\"No global fetch: pass `fetch` explicitly\");\n return (url, init) => fetch(url, init);\n}\n\n/** Check an adapter's shape once, at registration. */\nexport function defineChatModel<M extends ChatModel>(model: M): M {\n if (!model.id || !/^[a-z0-9][a-z0-9_-]*$/i.test(model.id)) {\n throw new Error(`Chat model id must be alphanumeric with - or _ (got \"${model.id}\")`);\n }\n if (typeof model.complete !== \"function\") throw new Error(`Chat model \"${model.id}\" has no complete()`);\n return model;\n}\n","/**\n * OpenAI adapter, over the Chat Completions API with function calling.\n *\n * Chat Completions is also what most other servers speak (Azure OpenAI,\n * OpenRouter, Groq, Together, vLLM, Ollama, LM Studio…), so `baseUrl` points\n * this one adapter at any of them.\n */\nimport {\n ChatModelError,\n defaultFetch,\n defineChatModel,\n type ChatMessage,\n type ChatModel,\n type ChatRequest,\n type ChatResponse,\n type FetchLike,\n type ToolCall,\n} from \"./types.js\";\n\nexport interface OpenAIChatModelOptions {\n /** Model id, e.g. \"gpt-5.4-mini\". Required: model names change faster than this package. */\n model: string;\n /** Other models the app may pick per request (`ChatRequest.model`). */\n models?: { id: string; label?: string }[];\n /** API key. Omit for local servers that don't need one. Keep it server-side (see `createChatHandler`). */\n apiKey?: string;\n /** Default https://api.openai.com/v1. Any OpenAI-compatible base URL works. */\n baseUrl?: string;\n organization?: string;\n project?: string;\n headers?: Record<string, string>;\n /** Default request fields merged into every call (e.g. `{ reasoning_effort: \"low\" }`). */\n params?: Record<string, unknown>;\n /** Stream responses (default true). */\n stream?: boolean;\n /**\n * Retries on rate limits (429) and server errors (500/502/503/504), waiting\n * as long as the server asks (Retry-After, or \"try again in 1.2s\"), else\n * backing off 1 s, 2 s, 4 s… (capped at 30 s). Default 4; 0 disables.\n */\n maxRetries?: number;\n /** Adapter id / label (default \"openai\" / \"OpenAI\"), e.g. \"ollama\" when pointing elsewhere. */\n id?: string;\n label?: string;\n fetch?: FetchLike;\n}\n\ntype OpenAIMessage =\n | { role: \"system\" | \"user\"; content: string }\n | { role: \"assistant\"; content: string | null; tool_calls?: { id: string; type: \"function\"; function: { name: string; arguments: string } }[] }\n | { role: \"tool\"; tool_call_id: string; content: string };\n\n/** Neutral messages → Chat Completions messages. */\nexport function toOpenAIMessages(messages: readonly ChatMessage[]): OpenAIMessage[] {\n return messages.map((m): OpenAIMessage => {\n if (m.role === \"assistant\") {\n const out: OpenAIMessage = { role: \"assistant\", content: m.content || null };\n if (m.toolCalls?.length) {\n out.tool_calls = m.toolCalls.map((c) => ({ id: c.id, type: \"function\", function: { name: c.name, arguments: JSON.stringify(c.arguments) } }));\n }\n return out;\n }\n if (m.role === \"tool\") return { role: \"tool\", tool_call_id: m.toolCallId, content: m.content };\n return { role: m.role, content: m.content };\n });\n}\n\n/** Parse a tool call's JSON arguments; unparseable JSON is reported to the model as a tool error. */\nexport function parseToolArguments(raw: string): Record<string, unknown> {\n if (!raw.trim()) return {};\n try {\n const value = JSON.parse(raw) as unknown;\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : { __invalidArguments: raw };\n } catch {\n return { __invalidArguments: raw };\n }\n}\n\nconst RETRYABLE = new Set([429, 500, 502, 503, 504]);\n\n/** How long the server asked us to wait (Retry-After header, or \"try again in 1.2s / 350ms\"), else exponential backoff. */\nexport function retryDelayMs(res: Pick<Response, \"headers\">, message: string, attempt: number): number {\n const header = Number(res.headers.get(\"retry-after-ms\") ?? NaN) || Number(res.headers.get(\"retry-after\") ?? NaN) * 1000;\n const m = /try again in ([\\d.]+)\\s*(ms|s)/i.exec(message);\n const asked = header || (m ? Number(m[1]) * (m[2]!.toLowerCase() === \"ms\" ? 1 : 1000) : 0);\n const backoff = Math.min(30_000, 1000 * 2 ** attempt);\n // A little extra and some jitter, so parallel callers don't all retry at the same instant.\n return Math.round(Math.min(60_000, Math.max(asked + 250, asked ? 0 : backoff)) * (1 + Math.random() * 0.25));\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason ?? new Error(\"aborted\"));\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\"abort\", () => (clearTimeout(t), reject(signal.reason ?? new Error(\"aborted\"))), { once: true });\n });\n}\n\nconst FINISH: Record<string, ChatResponse[\"finish\"]> = {\n stop: \"stop\",\n tool_calls: \"tool_calls\",\n function_call: \"tool_calls\",\n length: \"length\",\n content_filter: \"content_filter\",\n};\n\nexport function openAIChatModel(options: OpenAIChatModelOptions): ChatModel {\n const base = (options.baseUrl ?? \"https://api.openai.com/v1\").replace(/\\/+$/, \"\");\n const id = options.id ?? \"openai\";\n const doFetch = options.fetch ?? defaultFetch();\n const stream = options.stream ?? true;\n const models = [{ id: options.model }, ...(options.models ?? []).filter((m) => m.id !== options.model)];\n\n return defineChatModel({\n id,\n label: options.label ?? \"OpenAI\",\n models,\n async complete(request: ChatRequest, opts = {}): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n model: request.model ?? options.model,\n messages: toOpenAIMessages(request.messages),\n ...(request.tools?.length\n ? { tools: request.tools.map((t) => ({ type: \"function\", function: { name: t.name, description: t.description, parameters: t.inputSchema } })) }\n : {}),\n ...(request.maxOutputTokens ? { max_completion_tokens: request.maxOutputTokens } : {}),\n ...(stream ? { stream: true, stream_options: { include_usage: true } } : {}),\n ...options.params,\n ...request.params,\n };\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\", ...options.headers };\n if (options.apiKey) headers[\"Authorization\"] = `Bearer ${options.apiKey}`;\n if (options.organization) headers[\"OpenAI-Organization\"] = options.organization;\n if (options.project) headers[\"OpenAI-Project\"] = options.project;\n\n const maxRetries = options.maxRetries ?? 4;\n let res: Response;\n for (let attempt = 0; ; attempt++) {\n res = await doFetch(`${base}/chat/completions`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n if (res.ok) break;\n const err = (await res.json().catch(() => null)) as { error?: { message?: string } } | null;\n const message = err?.error?.message ?? `HTTP ${res.status}`;\n // A 429 for an exhausted quota or no credits won't clear by waiting.\n const permanent = /quota|credits|billing/i.test(message);\n if (attempt >= maxRetries || !RETRYABLE.has(res.status) || permanent) throw new ChatModelError(id, message, res.status);\n await sleep(retryDelayMs(res, message, attempt), opts.signal);\n }\n if (!stream || !res.body || !(res.headers.get(\"content-type\") ?? \"\").includes(\"event-stream\")) {\n return fromCompletion(await res!.json(), opts.onText);\n }\n return readStream(res!.body!, opts.onText);\n },\n });\n}\n\ninterface CompletionJson {\n model?: string;\n choices?: { message?: { content?: string | null; tool_calls?: { id: string; function: { name: string; arguments: string } }[] }; finish_reason?: string }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number };\n}\n\nfunction fromCompletion(json: CompletionJson, onText?: (delta: string) => void): ChatResponse {\n const choice = json.choices?.[0];\n const content = choice?.message?.content ?? \"\";\n if (content) onText?.(content);\n const out: ChatResponse = {\n content,\n toolCalls: (choice?.message?.tool_calls ?? []).map((c) => ({ id: c.id, name: c.function.name, arguments: parseToolArguments(c.function.arguments) })),\n finish: FINISH[choice?.finish_reason ?? \"\"] ?? \"other\",\n };\n if (json.model) out.model = json.model;\n if (json.usage) out.usage = usage(json.usage);\n return out;\n}\n\nconst usage = (u: { prompt_tokens?: number; completion_tokens?: number }) => ({\n ...(u.prompt_tokens !== undefined ? { inputTokens: u.prompt_tokens } : {}),\n ...(u.completion_tokens !== undefined ? { outputTokens: u.completion_tokens } : {}),\n});\n\ninterface ChunkJson {\n model?: string;\n choices?: {\n delta?: { content?: string | null; tool_calls?: { index: number; id?: string; function?: { name?: string; arguments?: string } }[] };\n finish_reason?: string | null;\n }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number } | null;\n}\n\n/** Server-sent events → one response; text deltas stream to `onText`, tool-call fragments are joined by index. */\nasync function readStream(body: ReadableStream<Uint8Array>, onText?: (delta: string) => void): Promise<ChatResponse> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let content = \"\";\n let finish: ChatResponse[\"finish\"] = \"other\";\n let model: string | undefined;\n let use: ChatResponse[\"usage\"];\n const calls = new Map<number, { id: string; name: string; args: string }>();\n\n const handle = (data: string) => {\n if (data === \"[DONE]\") return;\n let chunk: ChunkJson;\n try {\n chunk = JSON.parse(data) as ChunkJson;\n } catch {\n return;\n }\n if (chunk.model) model = chunk.model;\n if (chunk.usage) use = usage(chunk.usage);\n for (const choice of chunk.choices ?? []) {\n const delta = choice.delta;\n if (delta?.content) {\n content += delta.content;\n onText?.(delta.content);\n }\n for (const tc of delta?.tool_calls ?? []) {\n const call = calls.get(tc.index) ?? { id: \"\", name: \"\", args: \"\" };\n if (tc.id) call.id = tc.id;\n if (tc.function?.name) call.name += tc.function.name;\n if (tc.function?.arguments) call.args += tc.function.arguments;\n calls.set(tc.index, call);\n }\n if (choice.finish_reason) finish = FINISH[choice.finish_reason] ?? \"other\";\n }\n };\n\n for (;;) {\n const { done, value } = await reader.read();\n if (value) buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n const line = buffer.slice(0, nl).replace(/\\r$/, \"\");\n buffer = buffer.slice(nl + 1);\n if (line.startsWith(\"data:\")) handle(line.slice(5).trim());\n }\n if (done) break;\n }\n if (buffer.startsWith(\"data:\")) handle(buffer.slice(5).trim());\n\n const toolCalls: ToolCall[] = [...calls.entries()]\n .sort(([a], [b]) => a - b)\n .map(([index, c]) => ({ id: c.id || `call_${index}`, name: c.name, arguments: parseToolArguments(c.args) }));\n const out: ChatResponse = { content, toolCalls, finish };\n if (model) out.model = model;\n if (use) out.usage = use;\n return out;\n}\n","/**\n * Keys stay on the server: run the real model adapter in your backend behind\n * `createChatHandler`, and give the browser `remoteChatModel(endpoint)` — a\n * proxy with the same `ChatModel` shape. The agent loop and the tools run in\n * the browser, next to the project; only model calls cross the network.\n *\n * GET {base}/ → { id, label, models }\n * POST {base}/chat { request: ChatRequest } →\n * application/x-ndjson, one JSON object per line:\n * { \"type\": \"text\", \"delta\": \"…\" } (as it streams)\n * { \"type\": \"done\", \"response\": ChatResponse }\n * { \"type\": \"error\", \"error\": \"…\", \"status\": 401 }\n * errors before streaming → { error } with 400 / 404 / 413, or the vendor's status\n *\n * Fetch-API handler (`Request` → `Response`): mounts in Node 18+, edge\n * runtimes, Next, Hono, Express (via an adapter).\n */\nimport { ChatModelError, defaultFetch, type ChatModel, type ChatRequest, type ChatResponse, type FetchLike } from \"./types.js\";\n\nexport interface ChatHandlerOptions {\n /** Path prefix the handler is mounted at, e.g. \"/api/assistant\". */\n basePath?: string;\n /** Reject request bodies larger than this (default 2 MB). */\n maxBodyBytes?: number;\n /** Return a Response to refuse a request (auth, rate limits); undefined to allow. */\n authorize?: (request: Request) => Promise<Response | undefined> | Response | undefined;\n /** Adjust each request server-side (pin a model, cap tokens, add instructions). */\n prepare?: (request: ChatRequest) => ChatRequest;\n}\n\nexport function createChatHandler(model: ChatModel, options: ChatHandlerOptions = {}) {\n const base = (options.basePath ?? \"\").replace(/\\/+$/, \"\");\n const maxBody = options.maxBodyBytes ?? 2_000_000;\n\n return async function handle(request: Request): Promise<Response | null> {\n const path = new URL(request.url).pathname;\n if (base && path !== base && !path.startsWith(`${base}/`)) return null;\n const rest = path.slice(base.length).replace(/\\/+$/, \"\");\n\n const refused = await options.authorize?.(request);\n if (refused) return refused;\n\n if (rest === \"\" && request.method === \"GET\") {\n return json(200, { id: model.id, label: model.label, models: model.models ?? [] });\n }\n if (rest !== \"/chat\" || request.method !== \"POST\") return json(404, { error: \"not found\" });\n\n const text = await request.text();\n if (text.length > maxBody) return json(413, { error: \"request too large\" });\n let chat: ChatRequest;\n try {\n chat = (JSON.parse(text) as { request: ChatRequest }).request;\n } catch {\n return json(400, { error: \"body must be JSON { request }\" });\n }\n if (!chat || !Array.isArray(chat.messages)) return json(400, { error: \"request.messages is required\" });\n if (options.prepare) chat = options.prepare(chat);\n\n const encoder = new TextEncoder();\n const body = new ReadableStream<Uint8Array>({\n async start(controller) {\n const send = (value: unknown) => controller.enqueue(encoder.encode(`${JSON.stringify(value)}\\n`));\n try {\n const response = await model.complete(chat, { signal: request.signal, onText: (delta) => send({ type: \"text\", delta }) });\n send({ type: \"done\", response });\n } catch (err) {\n const status = (err as { status?: number })?.status;\n send({ type: \"error\", error: (err as Error)?.message ?? String(err), ...(status ? { status } : {}) });\n } finally {\n controller.close();\n }\n },\n });\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/x-ndjson\", \"cache-control\": \"no-store\" } });\n };\n}\n\nconst json = (status: number, body: unknown) => new Response(JSON.stringify(body), { status, headers: { \"content-type\": \"application/json\" } });\n\nexport interface RemoteChatModelOptions {\n fetch?: FetchLike;\n headers?: Record<string, string>;\n /** Skip the GET for model info (id/label/models default to \"remote\"). */\n info?: { id: string; label: string; models?: { id: string; label?: string }[] };\n}\n\n/** The model a backend serves, as a browser-side `ChatModel`. */\nexport async function remoteChatModel(endpoint: string, options: RemoteChatModelOptions = {}): Promise<ChatModel> {\n const doFetch = options.fetch ?? defaultFetch();\n const root = endpoint.replace(/\\/+$/, \"\");\n let info = options.info;\n if (!info) {\n const res = await doFetch(`${root}/`, { headers: { Accept: \"application/json\", ...options.headers } });\n if (!res.ok) throw new ChatModelError(\"remote\", `HTTP ${res.status}`, res.status);\n info = (await res.json()) as NonNullable<RemoteChatModelOptions[\"info\"]>;\n }\n const { id, label, models } = info;\n\n return {\n id,\n label,\n ...(models ? { models } : {}),\n async complete(request, opts = {}): Promise<ChatResponse> {\n const res = await doFetch(`${root}/chat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Accept: \"application/x-ndjson\", ...options.headers },\n body: JSON.stringify({ request }),\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n if (!res.ok || !res.body) {\n const err = (await res.json().catch(() => null)) as { error?: string } | null;\n throw new ChatModelError(id, err?.error ?? `HTTP ${res.status}`, res.status);\n }\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let final: ChatResponse | undefined;\n const handle = (line: string) => {\n if (!line.trim()) return;\n const event = JSON.parse(line) as { type: string; delta?: string; response?: ChatResponse; error?: string; status?: number };\n if (event.type === \"text\" && event.delta) opts.onText?.(event.delta);\n else if (event.type === \"done\") final = event.response;\n else if (event.type === \"error\") throw new ChatModelError(id, event.error ?? \"failed\", event.status);\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (value) buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n handle(buffer.slice(0, nl));\n buffer = buffer.slice(nl + 1);\n }\n if (done) break;\n }\n handle(buffer);\n if (!final) throw new ChatModelError(id, \"the server closed the stream without a response\");\n return final;\n },\n };\n}\n","import type { ChatModel, ChatRequest } from \"./types.js\";\n\nexport interface RateLimitOptions {\n /** Tokens per rolling minute across every caller of this model (input + output). */\n tokensPerMinute?: number;\n /** Requests per rolling minute. */\n requestsPerMinute?: number;\n /** Token estimate for a request before it's sent (default: JSON length ÷ 4, plus room for the reply). */\n estimate?: (request: ChatRequest) => number;\n}\n\n/**\n * Wrap a model so calls wait for room under your provider's per-minute\n * limits instead of failing with 429s — for batch jobs (evals, bulk edits)\n * and for a server sharing one key. Each call reserves an estimate, which is\n * replaced by the real usage when the response reports it.\n */\nexport function rateLimitedChatModel(model: ChatModel, options: RateLimitOptions): ChatModel {\n const tpm = options.tokensPerMinute ?? Infinity;\n const rpm = options.requestsPerMinute ?? Infinity;\n const estimate = options.estimate ?? ((r: ChatRequest) => Math.ceil(JSON.stringify(r).length / 4) + (r.maxOutputTokens ?? 1000));\n const window: { at: number; tokens: number }[] = [];\n let gate: Promise<void> = Promise.resolve();\n\n const prune = (now: number) => {\n while (window.length && now - window[0]!.at >= 60_000) window.shift();\n };\n const used = () => window.reduce((n, e) => n + e.tokens, 0);\n\n /** Wait (in arrival order) until this request fits, then reserve it. */\n const reserve = (tokens: number, signal?: AbortSignal) => {\n const want = Math.min(tokens, tpm); // a single request bigger than the limit still goes, alone\n const turn = gate.then(async () => {\n for (;;) {\n if (signal?.aborted) throw signal.reason ?? new Error(\"aborted\");\n const now = Date.now();\n prune(now);\n if (window.length < rpm && used() + want <= tpm) break;\n const oldest = window[0];\n await new Promise((r) => setTimeout(r, oldest ? Math.max(50, 60_000 - (now - oldest.at)) : 50));\n }\n const entry = { at: Date.now(), tokens: want };\n window.push(entry);\n return entry;\n });\n gate = turn.then(\n () => undefined,\n () => undefined,\n );\n return turn;\n };\n\n return {\n ...model,\n async complete(request, opts = {}) {\n const entry = await reserve(estimate(request), opts.signal);\n const response = await model.complete(request, opts);\n const real = (response.usage?.inputTokens ?? 0) + (response.usage?.outputTokens ?? 0);\n if (real > 0) entry.tokens = real;\n return response;\n },\n };\n}\n","import { animationPreset, describeAnimation, describeProject, findCuts, keyframeTimeUs, readAnimation, type AnimationRecipe, type Clip, type ProjectDocument } from \"@miraiclip/core\";\n\n/**\n * The project as the model sees it: core's `describeProject`, plus what a\n * model needs to make RELATIVE edits (\"bigger\", \"louder\", \"keep the\n * entrance\") — track names, every clip's position, size and opacity, text\n * styling, volume, effects and its animation recipe.\n */\nexport function describeForAssistant(doc: ProjectDocument): string {\n const lines = [\n describeProject(doc),\n \"\",\n \"track names: \" +\n doc.trackOrder\n .map((id) => {\n const t = doc.tracks[id] as { name?: string; hidden?: boolean; muted?: boolean; solo?: boolean; locked?: boolean } | undefined;\n const flags = [t?.hidden && \"hidden\", t?.muted && \"muted\", t?.solo && \"solo\", t?.locked && \"locked\"].filter(Boolean);\n return `${id} = \"${t?.name ?? id}\"${flags.length ? ` (${flags.join(\", \")})` : \"\"}`;\n })\n .join(\", \") +\n \" (track flags muted / solo / locked / hidden: track/set-property)\",\n ];\n const cuts = findCuts(doc);\n lines.push(\n cuts.length\n ? `cuts (where one clip ends and the next starts on the same track; transitions go here): ${cuts.map((c) => `${n(c.atUs / 1e6)}s ${c.fromClipId}→${c.toClipId}${c.transition ? ` (${c.transition.kind})` : \"\"}`).join(\", \")}`\n : \"cuts: none\",\n );\n const clips = Object.values(doc.clips).sort((a, b) => a.trackId.localeCompare(b.trackId) || a.startUs - b.startUs);\n if (clips.length) {\n lines.push(\"clip details (transform x/y: 0.5 = center; scale 1 = full size; times in seconds):\");\n for (const clip of clips) lines.push(`- ${clip.id}: ${details(clip)}`);\n }\n return lines.join(\"\\n\");\n}\n\nconst n = (v: number) => Number(v.toFixed(3));\n\nfunction details(clip: Clip): string {\n const parts: string[] = [`${clip.kind} on ${clip.trackId}`, `${n(clip.startUs / 1e6)}–${n((clip.startUs + clip.durationUs) / 1e6)}s`];\n if (clip.kind !== \"audio\") {\n const t = clip.transform;\n parts.push(`x ${n(t.x)} y ${n(t.y)} scale ${n(t.scale)}${t.rotation ? ` rotation ${n(t.rotation)}°` : \"\"} opacity ${n(t.opacity)}`);\n }\n if (clip.kind === \"text\") {\n const c = clip as Clip & { fontSizePx: number; color: string; fontFamily: string; fontWeight?: number; textAlign?: string };\n parts.push(`font ${c.fontFamily} ${c.fontSizePx}px${c.fontWeight ? ` weight ${c.fontWeight}` : \"\"} color ${c.color}${c.textAlign ? ` align ${c.textAlign}` : \"\"}`);\n }\n if (clip.kind === \"caption\") {\n const c = clip as Clip & { words: { text: string }[]; style: { preset: string; color: string; highlightColor: string; backgroundColor?: string } };\n parts.push(\n `words \"${c.words.map((w) => w.text).join(\" \").slice(0, 80)}\" · style preset ${c.style.preset} color ${c.style.color} highlight ${c.style.highlightColor} box ${c.style.backgroundColor ?? \"none\"} (style.backgroundColor)`,\n );\n }\n if (clip.kind === \"html\") {\n const c = clip as Clip & { template: string; params: Record<string, unknown> };\n parts.push(`params ${JSON.stringify(c.params)} (template placeholders: ${htmlPlaceholders(c.template).join(\", \") || \"none\"})`);\n }\n if (\"volume\" in clip) {\n const c = clip as Clip & { volume: number; fadeInUs?: number; fadeOutUs?: number; trimStartUs: number };\n parts.push(`volume ${n(c.volume)}${c.fadeInUs ? ` fade-in ${n(c.fadeInUs / 1e6)}s` : \"\"}${c.fadeOutUs ? ` fade-out ${n(c.fadeOutUs / 1e6)}s` : \"\"}`);\n parts.push(`source from ${n(c.trimStartUs / 1e6)}s`);\n }\n if (clip.effects?.length) parts.push(`effects ${clip.effects.map((e) => `${e.kind}#${e.id}${e.enabled ? \"\" : \" (off)\"}`).join(\", \")}`);\n const volumeKeys = clip.animations?.volume ?? [];\n if (volumeKeys.length) parts.push(`volume keyframes ${volumeKeys.map((k) => `${n((clip.startUs + keyframeTimeUs(k, clip.durationUs)) / 1e6)}s=${n(k.value)}`).join(\", \")}`);\n const visual = Object.entries(clip.animations ?? {}).some(([prop, list]) => prop !== \"volume\" && list && list.length);\n if (visual) {\n const read = readClipAnimation(clip);\n parts.push(read.custom ? `custom keyframes (not presets): ${describeKeyframes(clip)}` : `animation ${describeAnimation(read.recipe)}`);\n }\n return parts.join(\" · \");\n}\n\n/** The `{{name}}` placeholders an html clip's template substitutes from its params. */\nexport function htmlPlaceholders(template: string): string[] {\n return [...new Set([...template.matchAll(/\\{\\{\\s*([\\w.-]+)\\s*\\}\\}/g)].map((m) => m[1]!))];\n}\n\n/**\n * core's `readAnimation`, stricter: a \"stale\" reading (In / Out plus a loop\n * whose spacing a trim broke) is only trusted when the loop's properties have\n * enough keyframes to be a loop. Two keyframes are someone's own animation,\n * and rewriting them as presets would destroy it.\n */\nexport function readClipAnimation(clip: Clip): { recipe: AnimationRecipe; custom: boolean } {\n const read = readAnimation(clip);\n if (read.custom) return { recipe: {}, custom: true };\n if (read.stale && read.recipe.loop) {\n const preset = animationPreset(read.recipe.loop.preset);\n const props = Object.keys(preset?.build(clip.transform, 1_000_000, \"linear\") ?? {}) as (keyof NonNullable<Clip[\"animations\"]>)[];\n const count = props.reduce((sum, prop) => sum + (clip.animations?.[prop]?.length ?? 0), 0);\n if (count < 4) return { recipe: {}, custom: true };\n }\n return { recipe: read.recipe, custom: false };\n}\n\n/** Visual keyframes per property, at timeline seconds: \"opacity 0.5s 0 → 1s 1; scale …\". */\nexport function describeKeyframes(clip: Clip): string {\n return Object.entries(clip.animations ?? {})\n .filter(([prop, list]) => prop !== \"volume\" && list?.length)\n .map(([prop, list]) => `${prop} ${list!.map((k) => `${n((clip.startUs + keyframeTimeUs(k, clip.durationUs)) / 1e6)}s ${n(k.value)}`).join(\" → \")}`)\n .join(\"; \");\n}\n","/**\n * Catch fields a command would silently ignore. Core's schemas strip unknown\n * keys, so `clip/move { at: … }` or `track/set-property { property, value }`\n * validate fine and change nothing — and a model then reports an edit that\n * never happened. Checking payload keys against the command's JSON Schema\n * turns those into errors the model can fix.\n */\ntype Schema = {\n type?: string;\n properties?: Record<string, Schema>;\n required?: string[];\n anyOf?: Schema[];\n oneOf?: Schema[];\n const?: unknown;\n additionalProperties?: boolean | Schema;\n};\n\n/** Object schemas a value may match (unions flattened). */\nfunction branches(schema: Schema): Schema[] {\n const alts = schema.anyOf ?? schema.oneOf;\n return alts ? alts.flatMap(branches) : [schema];\n}\n\n/** `path` entries for keys the schema doesn't declare (one level into nested objects). */\nfunction unknownIn(schema: Schema, value: Record<string, unknown>, prefix = \"\"): string[] {\n const props = schema.properties;\n if (!props || (schema.additionalProperties !== undefined && schema.additionalProperties !== false)) return [];\n const out: string[] = [];\n for (const [key, v] of Object.entries(value)) {\n const sub = props[key];\n if (!sub) out.push(prefix + key);\n else if (!prefix && v && typeof v === \"object\" && !Array.isArray(v)) {\n const objectBranch = branches(sub).find((b) => b.properties);\n if (objectBranch) out.push(...unknownIn(objectBranch, v as Record<string, unknown>, `${key}.`));\n }\n }\n return out;\n}\n\nexport interface UnknownFields {\n unknown: string[];\n /** The fields the command does take (for the error message). */\n allowed: string[];\n}\n\n/** Unknown payload fields for a command, judged against the best-matching schema branch. */\nexport function unknownFields(schema: unknown, payload: unknown): UnknownFields | null {\n if (!schema || !payload || typeof payload !== \"object\" || Array.isArray(payload)) return null;\n const value = payload as Record<string, unknown>;\n let candidates = branches(schema as Schema).filter((b) => b.properties);\n if (candidates.length === 0) return null;\n // A discriminated union: prefer the branch whose `kind` constant matches.\n const byKind = candidates.filter((b) => b.properties!.kind?.const !== undefined && b.properties!.kind.const === value.kind);\n if (byKind.length) candidates = byKind;\n let best: UnknownFields | null = null;\n for (const b of candidates) {\n const unknown = unknownIn(b, value);\n if (!best || unknown.length < best.unknown.length) best = { unknown, allowed: Object.keys(b.properties!) };\n }\n return best && best.unknown.length ? best : null;\n}\n","import {\n ANIMATION_EASINGS,\n ANIMATION_PRESETS,\n animationCommands,\n applyCommands,\n commandCatalog,\n builtinTransitionParamSchemas,\n describeAnimation,\n EFFECT_CATALOG,\n findCuts,\n fitAnimation,\n toToolDefinitions,\n tryDispatch,\n type AnimationEasing,\n type AnimationRecipe,\n type AnimationSlot,\n type Command,\n type Cut,\n type Project,\n} from \"@miraiclip/core\";\nimport { describeForAssistant, describeKeyframes, htmlPlaceholders, readClipAnimation } from \"./state.js\";\nimport { unknownFields } from \"./strict.js\";\nimport type { ToolSpec } from \"./types.js\";\n\n/** What a tool's `run` gets. `project` is the turn's working copy. */\nexport interface ToolContext {\n project: Project;\n signal?: AbortSignal;\n}\n\n/** A tool's answer. `changes` are human-readable lines for the app's \"what changed\" list. */\nexport type ToolOutput =\n | { ok: true; result?: unknown; changes?: string[] }\n | { ok: false; error: unknown };\n\nexport interface AssistantTool extends ToolSpec {\n run(input: Record<string, unknown>, ctx: ToolContext): Promise<ToolOutput> | ToolOutput;\n}\n\nexport function defineTool(tool: AssistantTool): AssistantTool {\n if (!/^[a-zA-Z0-9_-]{1,64}$/.test(tool.name)) throw new Error(`Tool name must match ^[a-zA-Z0-9_-]{1,64}$ (got \"${tool.name}\")`);\n return tool;\n}\n\n/**\n * Adopt tools that come as definitions plus one runner — e.g.\n * `@miraiclip/audio-sources`' `audioToolDefinitions` + `runAudioTool`.\n * Accepts `{ name, description, input_schema }` or OpenAI function tools.\n */\nexport function toolsFromDefinitions(\n definitions: readonly unknown[],\n run: (name: string, input: Record<string, unknown>, ctx: ToolContext) => Promise<{ ok: boolean; result?: unknown; error?: unknown }>,\n options: { changes?: (name: string, input: Record<string, unknown>, result: unknown) => string[] | undefined } = {},\n): AssistantTool[] {\n return definitions.map((d) => {\n const def = d as { name?: string; description?: string; input_schema?: Record<string, unknown>; function?: { name: string; description?: string; parameters?: Record<string, unknown> } };\n const name = def.function?.name ?? def.name!;\n return defineTool({\n name,\n description: def.function?.description ?? def.description ?? \"\",\n inputSchema: def.function?.parameters ?? def.input_schema ?? { type: \"object\", properties: {} },\n async run(input, ctx) {\n const out = await run(name, input, ctx);\n if (!out.ok) return { ok: false, error: out.error ?? \"failed\" };\n const changes = options.changes?.(name, input, out.result);\n return { ok: true, result: out.result, ...(changes?.length ? { changes } : {}) };\n },\n });\n });\n}\n\nconst S = 1_000_000;\n/** Slide presets are named by motion; models do better naming the edge, so these map edges to presets. */\nconst SLIDE_IN: Record<string, string> = { \"from-right\": \"left\", \"from-left\": \"right\", \"from-bottom\": \"up\", \"from-top\": \"down\" };\nconst SLIDE_OUT: Record<string, string> = { \"to-left\": \"left\", \"to-right\": \"right\", \"to-top\": \"up\", \"to-bottom\": \"down\" };\nfunction slideAliases(input: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (typeof input.in === \"string\" && SLIDE_IN[input.in]) out.in = SLIDE_IN[input.in];\n if (typeof input.out === \"string\" && SLIDE_OUT[input.out]) out.out = SLIDE_OUT[input.out];\n return out;\n}\n/** The html template set_background uses: one `{{color}}` fill. */\nexport const BACKGROUND_TEMPLATE = '<div style=\"width:100%;height:100%;background:{{color}}\"></div>';\nconst seconds = (us: number) => `${Math.round(us / 100_000) / 10}s`;\nconst n3 = (v: number) => Number(v.toFixed(3));\nconst toUs = (s: unknown) => (typeof s === \"number\" && Number.isFinite(s) ? Math.round(s * S) : undefined);\n\n/* ---------- describing commands for people ---------- */\n\nconst PHRASES: Record<string, (p: Record<string, unknown>) => string> = {\n \"clip/add\": (p) =>\n p.kind === \"text\" ? `Added text \"${String(p.text ?? \"\").slice(0, 40)}\" at ${seconds(Number(p.startUs))}` : `Added a ${p.kind} clip at ${seconds(Number(p.startUs))}`,\n \"clip/remove\": (p) => `Removed clip ${p.clipId}`,\n \"clip/move\": (p) => `Moved clip ${p.clipId}${p.startUs !== undefined ? ` to ${seconds(Number(p.startUs))}` : \"\"}`,\n \"clip/trim\": (p) => `Trimmed clip ${p.clipId}`,\n \"clip/split\": (p) => `Split clip ${p.clipId} at ${seconds(Number(p.atUs))}`,\n \"clip/duplicate\": (p) => `Duplicated clip ${p.clipId}`,\n \"clip/set-property\": (p) => `Changed ${Object.keys(p).filter((k) => k !== \"clipId\").join(\", \")} of clip ${p.clipId}`,\n \"track/add\": (p) => `Added a ${p.kind} track`,\n \"track/remove\": (p) => `Removed track ${p.id}`,\n \"track/set-property\": (p) => `Changed track ${p.trackId}: ${Object.keys(p).filter((k) => k !== \"trackId\").join(\", \")}`,\n \"effect/add\": (p) => `Added ${p.kind} to clip ${p.clipId}`,\n \"effect/update\": (p) => `Adjusted an effect on clip ${p.clipId}`,\n \"effect/remove\": (p) => `Removed an effect from clip ${p.clipId}`,\n \"transition/add\": (p) => `Added a ${p.kind} transition`,\n \"transition/remove\": () => \"Removed a transition\",\n \"project/set-settings\": () => \"Changed the project settings\",\n};\n\n/** One line per command, for a \"what changed\" list (keyframe edits fold into one line per clip). */\nexport function describeCommands(commands: readonly Command[]): string[] {\n const lines: string[] = [];\n const keyframed = new Set<string>();\n for (const c of commands) {\n const p = (c.payload ?? {}) as Record<string, unknown>;\n if (c.type.startsWith(\"keyframe/\")) {\n const id = String(p.clipId);\n if (!keyframed.has(id)) lines.push(`Changed the animation of clip ${id}`);\n keyframed.add(id);\n continue;\n }\n const phrase = PHRASES[c.type];\n lines.push(phrase ? phrase(p) : `${c.type}`);\n }\n return lines;\n}\n\n/* ---------- the editor tools ---------- */\n\nconst US_NOTE = \"Times in commands are integer MICROSECONDS (1 s = 1000000).\";\n\nexport interface EditorToolsOptions {\n /** Transition kinds to offer (default: the built-ins). Add your registered custom kinds. */\n transitionKinds?: string[];\n /** The command catalog to offer in apply_commands (default: the built-ins). Pass `project.commandCatalog()` when you register custom commands. */\n commandCatalog?: Record<string, unknown>;\n}\n\n/**\n * The tools that edit a Miraiclip project: read state, look up a command's\n * schema, apply command batches, and two high-level tools (transitions,\n * animation presets) that use the same logic as the editor's panels.\n */\nexport function editorTools(options: EditorToolsOptions = {}): AssistantTool[] {\n const transitionKinds = options.transitionKinds ?? Object.keys(builtinTransitionParamSchemas);\n const presetIds = (slot: AnimationSlot) => ANIMATION_PRESETS.filter((p) => p.slot === slot).map((p) => p.id.split(\":\")[1]!);\n\n return [\n defineTool({\n name: \"get_state\",\n description: `The project as it is now (after your edits so far): settings, assets, tracks with clips (ids, kinds, time ranges), transitions, and each clip's position, size, opacity, text style, volume, effects and animation. ${US_NOTE}`,\n inputSchema: {\n type: \"object\",\n properties: { includeJson: { type: \"boolean\", description: \"Also return the full document JSON (verbose; only for exact field values).\" } },\n additionalProperties: false,\n },\n run(input, { project }) {\n const summary = describeForAssistant(project.toJSON());\n return { ok: true, result: input.includeJson ? { summary, document: project.toJSON() } : summary };\n },\n }),\n\n defineTool({\n name: \"get_command_schema\",\n description: \"The JSON Schema of one editing command's payload. Look it up before using a command in apply_commands for the first time.\",\n inputSchema: {\n type: \"object\",\n properties: { type: { type: \"string\", description: 'Command type, e.g. \"clip/add\".' } },\n required: [\"type\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const catalog = project.commandCatalog();\n const schema = catalog[String(input.type)];\n return schema ? { ok: true, result: schema } : { ok: false, error: { error: `unknown command \"${input.type}\"`, validTypes: Object.keys(catalog).sort() } };\n },\n }),\n\n defineTool({\n name: \"apply_commands\",\n description:\n \"Apply editing commands as one all-or-nothing batch. On failure nothing changes and the error names the failing index and why (invalid payload issues, or the engine's rejection reason) — fix it and retry. \" +\n `Give new clips, tracks and assets your own readable ids. ${US_NOTE}`,\n inputSchema: applyCommandsSchema(options.commandCatalog ?? commandCatalog()),\n run(input, { project }) {\n const commands = input.commands as Command[] | undefined;\n if (!Array.isArray(commands) || commands.length === 0) return { ok: false, error: \"commands must be a non-empty array of { type, payload }\" };\n return applyChecked(project, commands);\n },\n }),\n\n defineTool({\n name: \"add_transition\",\n description:\n \"Add (or replace, or remove) a transition on cuts — where one clip ends exactly where the next starts on the same video track. Pick the cut by its two clip ids, by a time near it, or all cuts. \" +\n \"A transition overlaps both clips around the cut, so its length is capped by the spare footage there; cuts with none are skipped and reported. \" +\n 'When a video clip directly follows another on its track, \"fade into / dissolve to / slide in / wipe to\" that clip means a transition on the cut before it, not an animation. ' +\n 'Slide / wipe direction is the direction of motion: \"from the left\" = right.',\n inputSchema: {\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...transitionKinds, \"none\"], description: '\"none\" removes the transition.' },\n fromClipId: { type: \"string\", description: \"The clip ending at the cut.\" },\n toClipId: { type: \"string\", description: \"The clip starting at the cut.\" },\n nearSeconds: { type: \"number\", description: \"Pick the cut closest to this time instead.\" },\n allCuts: { type: \"boolean\", description: \"Apply to every cut.\" },\n durationSeconds: { type: \"number\", minimum: 0.1, maximum: 3, description: \"Default 0.6.\" },\n direction: { type: \"string\", enum: [\"left\", \"right\", \"up\", \"down\"], description: \"wipe / slide only.\" },\n },\n required: [\"kind\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const cuts = findCuts(project.getState().doc);\n if (cuts.length === 0) return { ok: false, error: \"There are no cuts: transitions need two clips touching on the same video track.\" };\n let targets: Cut[];\n if (input.allCuts === true) targets = cuts;\n else if (typeof input.fromClipId === \"string\" || typeof input.toClipId === \"string\") {\n targets = cuts.filter((c) => (!input.fromClipId || c.fromClipId === input.fromClipId) && (!input.toClipId || c.toClipId === input.toClipId));\n if (targets.length === 0) return { ok: false, error: { error: noCutReason(project, input.fromClipId, input.toClipId), cuts: cuts.map(cutInfo) } };\n } else {\n const at = toUs(input.nearSeconds) ?? project.getState().playheadUs;\n const nearest = cuts.reduce((a, b) => (Math.abs(b.atUs - at) < Math.abs(a.atUs - at) ? b : a));\n if (input.nearSeconds !== undefined && Math.abs(nearest.atUs - at) > 1.5 * S) {\n return {\n ok: false,\n error: { error: `There is no cut near ${seconds(at)} (the nearest is at ${seconds(nearest.atUs)}). Transitions only go on cuts; nothing was added. Use one of these cuts, or tell the user there isn't one there.`, cuts: cuts.map(cutInfo) },\n };\n }\n targets = [nearest];\n }\n if (targets.length === 0) return { ok: false, error: { error: \"no cut matches\", cuts: cuts.map(cutInfo) } };\n const kind = String(input.kind);\n const wanted = toUs(input.durationSeconds) ?? 600_000;\n const commands: Command[] = [];\n const changes: string[] = [];\n const skipped: unknown[] = [];\n for (const cut of targets) {\n if (cut.transition) commands.push({ type: \"transition/remove\", payload: { transitionId: cut.transition.id } });\n if (kind === \"none\") {\n if (cut.transition) changes.push(`Removed the transition at ${seconds(cut.atUs)}`);\n continue;\n }\n const durationUs = Math.min(wanted, cut.maxTransitionUs);\n if (durationUs < 100_000) {\n skipped.push({ ...cutInfo(cut), reason: `no spare footage (${cut.short === \"from\" ? \"the first clip ends where its media ends\" : cut.short === \"to\" ? \"the second clip starts at its media's start\" : \"both clips use all their media\"})` });\n if (cut.transition) commands.pop();\n continue;\n }\n const params = input.direction && (kind === \"wipe\" || kind === \"slide\") ? { direction: input.direction } : undefined;\n commands.push({ type: \"transition/add\", payload: { kind, fromClipId: cut.fromClipId, toClipId: cut.toClipId, durationUs, ...(params ? { params } : {}) } });\n changes.push(`${cut.transition ? \"Replaced the transition with\" : \"Added\"} ${kind} at ${seconds(cut.atUs)} (${seconds(durationUs)})`);\n }\n if (commands.length) {\n const result = applyCommands(project, commands);\n if (!result.ok) return { ok: false, error: result };\n }\n return { ok: true, result: { changed: changes.length, skipped }, changes };\n },\n }),\n\n defineTool({\n name: \"animate_clip\",\n description:\n \"Give a visual clip (video, image, text) an entrance (in), a loop while on screen, and/or an exit (out), as keyframes. Slots you leave out keep their current animation; \\\"none\\\" removes one; reset:true removes all. \" +\n `In/out presets: ${presetIds(\"in\").join(\", \")}. Loops: ${presetIds(\"loop\").join(\", \")}. Exits stay on the clip's end through trims. ` +\n 'Slides: give the edge, in: \"from-right\" (enters from the right edge, moving left), \"from-left\", \"from-top\", \"from-bottom\"; out: \"to-left\", \"to-right\", \"to-top\", \"to-bottom\". ' +\n \"For text, logos and overlays; between two video clips prefer add_transition. The clip's current animation is in get_state; pass only the slots to change. \" +\n \"Fading the whole VIDEO in at the start and out at the end is two calls: in on the FIRST clip of the main video track, out on the LAST one (an out on the first clip would fade to black at its cut).\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n in: { type: \"string\", enum: [...presetIds(\"in\"), ...Object.keys(SLIDE_IN), \"none\"], description: 'For slides, prefer \"from-left\" / \"from-right\" / \"from-top\" / \"from-bottom\": the edge the clip enters from.' },\n loop: { type: \"string\", enum: [...presetIds(\"loop\"), \"none\"] },\n out: { type: \"string\", enum: [...presetIds(\"out\"), ...Object.keys(SLIDE_OUT), \"none\"], description: 'For slides, prefer \"to-left\" / \"to-right\" / \"to-top\" / \"to-bottom\": the edge the clip leaves by.' },\n inSeconds: { type: \"number\", minimum: 0.2, maximum: 3, description: \"Default 0.6.\" },\n outSeconds: { type: \"number\", minimum: 0.2, maximum: 3, description: \"Default 0.6.\" },\n easing: { type: \"string\", enum: ANIMATION_EASINGS.map((e) => e.id), description: \"Default smooth.\" },\n reset: { type: \"boolean\" },\n },\n required: [\"clipId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n input = { ...input, ...slideAliases(input) };\n const clip = project.getState().doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n if (clip.kind === \"audio\") return { ok: false, error: \"audio clips have no picture to animate (use volume or fades)\" };\n const reading = readClipAnimation(clip);\n if (reading.custom && input.reset !== true) {\n return {\n ok: false,\n error: `${clip.id} has its own keyframes (${describeKeyframes(clip)}), not presets; presets would overwrite them. To remove one property's animation, apply_commands keyframe/clear { clipId, property }. To edit them, use set_keyframes. To replace them all with presets, pass reset: true. Nothing was changed.`,\n };\n }\n const current = input.reset === true ? {} : reading.recipe;\n const next: AnimationRecipe = { ...current };\n const easing = (typeof input.easing === \"string\" ? input.easing : \"smooth\") as AnimationEasing;\n for (const slot of [\"in\", \"loop\", \"out\"] as const) {\n const name = input[slot];\n if (name === undefined) continue;\n if (name === \"none\") {\n delete next[slot];\n continue;\n }\n const durationUs = slot === \"loop\" ? 0 : toUs(input[slot === \"in\" ? \"inSeconds\" : \"outSeconds\"]) ?? current[slot]?.durationUs ?? 600_000;\n next[slot] = { preset: `${slot}:${name}`, durationUs, easing: slot === \"loop\" ? \"linear\" : easing };\n }\n const recipe = fitAnimation(next, clip.durationUs);\n const result = applyCommands(project, animationCommands(clip, recipe));\n if (!result.ok) return { ok: false, error: result };\n const summary = describeAnimation(recipe) || \"no animation\";\n const atCut = input.in && input.in !== \"none\" && clip.kind === \"video\" ? findCuts(project.getState().doc).find((c) => c.toClipId === clip.id) : undefined;\n return {\n ok: true,\n result: {\n clipId: clip.id,\n animation: summary,\n ...(atCut ? { note: `${clip.id} starts at a cut right after ${atCut.fromClipId}. If the user meant going from ${atCut.fromClipId} into ${clip.id} (\"fade into\", \"slide in\", \"dissolve to\"), that is add_transition on this cut: undo this entrance with in:\"none\" and add the transition.` } : {}),\n },\n changes: [`${clip.id}: ${summary}`],\n };\n },\n }),\n\n defineTool({\n name: \"add_effect\",\n description:\n \"Add a visual effect to one or more clips (video, image, text). Kinds, with their params (min–max, default): \" +\n EFFECT_CATALOG.map((e) => `${e.kind} (${e.label}${e.params.length ? `: ${e.params.map((p) => (p.type === \"number\" ? `${p.key} ${p.min}–${p.max}, ${p.default}` : `${p.key} color`)).join(\"; \")}` : \"\"})`).join(\", \") +\n \". Omitted params take their defaults. Black & white is mono; brightness, contrast, saturation and hue are colorAdjust params (-1–1, 0 = unchanged).\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", enum: EFFECT_CATALOG.map((e) => e.kind) },\n params: { type: \"object\", description: \"Effect params by key; see the list above.\" },\n },\n required: [\"clipIds\", \"kind\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const ids = (input.clipIds as string[]) ?? [];\n const doc = project.getState().doc;\n const missing = ids.filter((id) => !doc.clips[id]);\n if (missing.length) return { ok: false, error: `no clip ${missing.map((m) => `\"${m}\"`).join(\", \")}` };\n const audio = ids.filter((id) => doc.clips[id]!.kind === \"audio\");\n if (audio.length) return { ok: false, error: `audio clips have no picture: ${audio.join(\", \")}` };\n const params = input.params && typeof input.params === \"object\" ? (input.params as Record<string, unknown>) : undefined;\n const out = applyChecked(project, ids.map((clipId) => ({ type: \"effect/add\", payload: { clipId, kind: input.kind, ...(params ? { params } : {}) } })));\n if (!out.ok) return out;\n const label = EFFECT_CATALOG.find((e) => e.kind === input.kind)?.label ?? String(input.kind);\n return { ...out, changes: [`Added ${label} to ${ids.join(\", \")}`] };\n },\n }),\n\n defineTool({\n name: \"remove_effects\",\n description: \"Delete effects from clips: one kind, or every effect when kind is omitted. To turn effects off but keep them, use set_effects_enabled.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", description: \"Only effects of this kind (default: all).\" },\n },\n required: [\"clipIds\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const commands: Command[] = [];\n for (const id of (input.clipIds as string[]) ?? []) {\n const clip = doc.clips[id];\n if (!clip) return { ok: false, error: `no clip \"${id}\"` };\n for (const e of clip.effects ?? []) if (!input.kind || e.kind === input.kind) commands.push({ type: \"effect/remove\", payload: { clipId: id, effectId: e.id } });\n }\n if (!commands.length) return { ok: true, result: { removed: 0, note: \"those clips had no matching effects\" } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, result: { removed: commands.length }, changes: [`Removed ${commands.length} effect${commands.length > 1 ? \"s\" : \"\"}`] } : out;\n },\n }),\n\n defineTool({\n name: \"trim_clip\",\n description:\n \"Trim a clip like an editor's edge drag, in seconds. removeFromStart cuts that much off the beginning (the clip's end stays put; for video/audio the source moves on too). \" +\n \"removeFromEnd cuts off the end. setDuration sets the length, keeping the start. startSeconds / endSeconds put the clip's edges at those timeline times (e.g. 0 and the composition length to cover the whole video; a video/audio clip's source shifts with its start edge). \" +\n \"ripple:true shifts later clips on the same track to close (or open) the gap.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n removeFromStart: { type: \"number\", exclusiveMinimum: 0 },\n removeFromEnd: { type: \"number\", exclusiveMinimum: 0 },\n setDuration: { type: \"number\", exclusiveMinimum: 0 },\n startSeconds: { type: \"number\", minimum: 0, description: \"Timeline time for the clip's start edge.\" },\n endSeconds: { type: \"number\", exclusiveMinimum: 0, description: \"Timeline time for the clip's end edge.\" },\n ripple: { type: \"boolean\" },\n },\n required: [\"clipId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const clip = doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n const head = toUs(input.removeFromStart) ?? 0;\n const tail = toUs(input.removeFromEnd) ?? 0;\n const ripple = input.ripple === true;\n const startAt = toUs(input.startSeconds);\n const endAt = toUs(input.endSeconds);\n if ((startAt !== undefined || endAt !== undefined) && (head || tail)) return { ok: false, error: \"use either startSeconds / endSeconds or removeFromStart / removeFromEnd, not both\" };\n let duration = clip.durationUs - head - tail;\n const set = toUs(input.setDuration);\n if (set) duration = set;\n // Without ripple, cutting the head keeps the clip's end in place; with ripple the clip keeps its start and later clips move up.\n let start = ripple ? clip.startUs : clip.startUs + head;\n let sourceShift = head;\n if (startAt !== undefined) {\n start = startAt;\n sourceShift = startAt - clip.startUs;\n if (endAt === undefined && !set) duration = clip.startUs + clip.durationUs - startAt;\n }\n if (endAt !== undefined) duration = endAt - start;\n if (duration <= 0) return { ok: false, error: `that leaves the clip ${seconds(duration)} long; it is ${seconds(clip.durationUs)} (${seconds(clip.startUs)}–${seconds(clip.startUs + clip.durationUs)})` };\n const trimmable = \"trimStartUs\" in clip;\n if (trimmable && (clip as { trimStartUs: number }).trimStartUs + sourceShift < 0) {\n return { ok: false, error: `${clip.id}'s media has only ${seconds((clip as { trimStartUs: number }).trimStartUs)} before its current start, so its start edge can move back at most that far` };\n }\n const commands: Command[] = [\n {\n type: \"clip/trim\",\n payload: {\n clipId: clip.id,\n startUs: start,\n durationUs: duration,\n ...(trimmable && sourceShift ? { trimStartUs: (clip as { trimStartUs: number }).trimStartUs + sourceShift } : {}),\n },\n },\n ];\n if (ripple) {\n const oldEnd = clip.startUs + clip.durationUs;\n const delta = start + duration - oldEnd;\n const later = Object.values(doc.clips)\n .filter((c) => c.trackId === clip.trackId && c.id !== clip.id && c.startUs >= oldEnd)\n .sort((x, y) => (delta < 0 ? x.startUs - y.startUs : y.startUs - x.startUs));\n for (const c of later) commands.push({ type: \"clip/move\", payload: { clipId: c.id, startUs: Math.max(0, c.startUs + delta) } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n const after = project.getState().doc.clips[clip.id]!;\n return { ...out, changes: [`Trimmed ${clip.id} to ${seconds(after.startUs)}–${seconds(after.startUs + after.durationUs)}`] };\n },\n }),\n\n defineTool({\n name: \"set_effects_enabled\",\n description: \"Turn effects off (or back on) without deleting them, keeping their settings: one kind, or every effect when kind is omitted. To delete effects use remove_effects.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", description: \"Only effects of this kind (default: all).\" },\n enabled: { type: \"boolean\" },\n },\n required: [\"clipIds\", \"enabled\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const enabled = input.enabled === true;\n const commands: Command[] = [];\n for (const id of (input.clipIds as string[]) ?? []) {\n const clip = doc.clips[id];\n if (!clip) return { ok: false, error: `no clip \"${id}\"` };\n for (const e of clip.effects ?? []) {\n if ((!input.kind || e.kind === input.kind) && e.enabled !== enabled) commands.push({ type: \"effect/update\", payload: { clipId: id, effectId: e.id, enabled } });\n }\n }\n if (!commands.length) return { ok: true, result: { changed: 0, note: `no matching effects that are ${enabled ? \"off\" : \"on\"}` } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, result: { changed: commands.length }, changes: [`Turned ${enabled ? \"on\" : \"off\"} ${commands.length} effect${commands.length > 1 ? \"s\" : \"\"}`] } : out;\n },\n }),\n\n defineTool({\n name: \"set_keyframes\",\n description:\n \"Animate one property of a clip so it CHANGES over time, with keyframes at TIMELINE seconds (the same times as get_state). Replaces that property's existing keyframes (including a preset's) unless keep:true. Between points the value moves smoothly; before the first and after the last it holds. \" +\n \"Properties: x, y (0–1, 0.5 = center), scale (1 = full size), rotation (degrees; 360 = one full turn, so a static 360 looks like 0), opacity (0–1), volume (0–1, audio/video). \" +\n \"Not for constant values (\\\"rotate 45°\\\", \\\"music at 30%\\\", \\\"louder\\\": set those with clip/set-property) or for removing an animation (keyframe/clear). Use it for motion and timed changes the presets don't cover: a spin (rotation 0 → 360 over the clip), a pan, ducking music (volume: normal → low just before a range, low → normal just after), or fading audio between two times.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n property: { type: \"string\", enum: [\"x\", \"y\", \"scale\", \"rotation\", \"opacity\", \"volume\"] },\n points: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n properties: { atSeconds: { type: \"number\", minimum: 0 }, value: { type: \"number\" } },\n required: [\"atSeconds\", \"value\"],\n additionalProperties: false,\n },\n },\n easing: { type: \"string\", enum: [\"linear\", \"easeIn\", \"easeOut\", \"easeInOut\", \"hold\"], description: \"Curve between points (default linear).\" },\n keep: { type: \"boolean\", description: \"Keep the property's other keyframes (default false: replace them).\" },\n },\n required: [\"clipId\", \"property\", \"points\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const clip = project.getState().doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n const property = String(input.property);\n if (property === \"volume\" && !(\"volume\" in clip)) return { ok: false, error: `${clip.id} is a ${clip.kind} clip and has no volume` };\n if (property !== \"volume\" && clip.kind === \"audio\") return { ok: false, error: \"audio clips only animate volume\" };\n const end = clip.startUs + clip.durationUs;\n const points = (input.points as { atSeconds: number; value: number }[]).map((p) => ({ atUs: toUs(p.atSeconds)!, value: p.value }));\n const outside = points.filter((p) => p.atUs < clip.startUs - 1000 || p.atUs > end + 1000);\n if (outside.length) return { ok: false, error: `${clip.id} runs ${seconds(clip.startUs)}–${seconds(end)}; points must be inside that range (got ${outside.map((p) => seconds(p.atUs)).join(\", \")})` };\n if (input.keep !== true && new Set(points.map((p) => p.value)).size < 2) {\n const how = property === \"volume\" ? \"clip/set-property { volume }\" : `clip/set-property { transform: { ${property} } }`;\n return {\n ok: false,\n error: `Keyframes are for a value that CHANGES over time; ${points.length === 1 ? \"one point\" : \"these points\"} hold${points.length === 1 ? \"s\" : \"\"} a single value. For a constant ${property}, set it directly with apply_commands ${how}. To remove an animation, apply keyframe/clear { clipId, property }. Nothing was changed.`,\n };\n }\n const commands: Command[] = [];\n if (input.keep !== true && (clip.animations?.[property as \"x\"]?.length ?? 0) > 0) commands.push({ type: \"keyframe/clear\", payload: { clipId: clip.id, property } });\n const easing = typeof input.easing === \"string\" ? input.easing : \"linear\";\n for (const p of points) {\n commands.push({ type: \"keyframe/set\", payload: { clipId: clip.id, property, timeUs: Math.min(clip.durationUs, Math.max(0, p.atUs - clip.startUs)), value: p.value, easing } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n const list = points.map((p) => `${seconds(p.atUs)} ${n3(p.value)}`).join(\" → \");\n return { ...out, changes: [`${clip.id}: ${property} ${list}`] };\n },\n }),\n\n defineTool({\n name: \"set_background\",\n description:\n \"A solid color background behind everything (an html clip on a Background track at the very bottom). Adds one, recolors or re-times the existing one, or removes it with color \\\"none\\\". \" +\n \"Covers the whole video unless fromSeconds / toSeconds say otherwise. Only visible where nothing opaque is on top (behind scaled-down, faded or transparent clips, or where there's no footage).\",\n inputSchema: {\n type: \"object\",\n properties: {\n color: { type: \"string\", description: 'CSS color, e.g. \"#1E3A8A\", or \"none\" to remove the background.' },\n fromSeconds: { type: \"number\", minimum: 0 },\n toSeconds: { type: \"number\", exclusiveMinimum: 0 },\n },\n required: [\"color\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const color = String(input.color).trim();\n const existing = Object.values(doc.clips).find(\n (c) => c.kind === \"html\" && ((c as { template?: string }).template === BACKGROUND_TEMPLATE || doc.tracks[c.trackId]?.name === \"Background\"),\n );\n if (color.toLowerCase() === \"none\") {\n if (!existing) return { ok: true, result: { note: \"there is no background to remove\" } };\n const commands: Command[] = [{ type: \"clip/remove\", payload: { clipId: existing.id } }];\n if (!Object.values(doc.clips).some((c) => c.trackId === existing.trackId && c.id !== existing.id)) commands.push({ type: \"track/remove\", payload: { id: existing.trackId } });\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, changes: [\"Removed the background\"] } : out;\n }\n let endUs = 0;\n for (const c of Object.values(doc.clips)) if (c.id !== existing?.id) endUs = Math.max(endUs, c.startUs + c.durationUs);\n const startUs = toUs(input.fromSeconds) ?? (existing && input.toSeconds === undefined ? existing.startUs : 0);\n const stopUs = toUs(input.toSeconds) ?? (existing && input.fromSeconds === undefined ? existing.startUs + existing.durationUs : endUs || 10 * S);\n if (stopUs <= startUs) return { ok: false, error: `toSeconds must be after fromSeconds (got ${seconds(startUs)}–${seconds(stopUs)})` };\n const commands: Command[] = [];\n if (existing) {\n const params = existing as { template: string; params: Record<string, unknown> };\n const key = htmlPlaceholders(params.template).find((k) => /colou?r|background|bg/i.test(k)) ?? \"color\";\n if (params.params[key] !== color) commands.push({ type: \"clip/set-property\", payload: { clipId: existing.id, params: { [key]: color } } });\n if (existing.startUs !== startUs || existing.durationUs !== stopUs - startUs) commands.push({ type: \"clip/trim\", payload: { clipId: existing.id, startUs, durationUs: stopUs - startUs } });\n if (!commands.length) return { ok: true, result: { note: \"the background already looks like that\" } };\n } else {\n const trackId = doc.tracks.background ? `background-${Object.keys(doc.tracks).length}` : \"background\";\n commands.push({ type: \"track/add\", payload: { id: trackId, kind: \"video\", name: \"Background\", index: 0 } });\n commands.push({ type: \"clip/add\", payload: { kind: \"html\", id: `${trackId}-clip`, trackId, startUs, durationUs: stopUs - startUs, template: BACKGROUND_TEMPLATE, params: { color } } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n return { ...out, changes: [`${existing ? \"Changed the background to\" : \"Added a background:\"} ${color}, ${seconds(startUs)}–${seconds(stopUs)}`] };\n },\n }),\n\n defineTool({\n name: \"close_gaps\",\n description: \"Close the empty gaps on a track so its clips run back to back, keeping their order (the first clip stays where it is, or starts at 0 with fromZero).\",\n inputSchema: {\n type: \"object\",\n properties: { trackId: { type: \"string\" }, fromZero: { type: \"boolean\" } },\n required: [\"trackId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n if (!doc.tracks[String(input.trackId)]) return { ok: false, error: `no track \"${input.trackId}\"` };\n const clips = Object.values(doc.clips)\n .filter((c) => c.trackId === input.trackId)\n .sort((a, b) => a.startUs - b.startUs);\n let cursor = input.fromZero === true ? 0 : clips[0]?.startUs ?? 0;\n const commands: Command[] = [];\n for (const c of clips) {\n if (c.startUs !== cursor) commands.push({ type: \"clip/move\", payload: { clipId: c.id, startUs: cursor } });\n cursor += c.durationUs;\n }\n if (!commands.length) return { ok: true, result: { moved: 0, note: \"no gaps on that track\" } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, changes: [`Closed ${commands.length} gap${commands.length > 1 ? \"s\" : \"\"} on ${input.trackId}`] } : out;\n },\n }),\n ];\n}\n\n/* ---------- apply_commands, checked ---------- */\n\nclass Abort extends Error {}\n\n/**\n * Apply a batch as one all-or-nothing step, with two checks core doesn't do:\n * fields a command would silently ignore are errors, and commands that\n * changed nothing are reported, so the model never claims an edit that didn't\n * happen.\n */\nexport function applyChecked(project: Project, commands: Command[]): ToolOutput {\n const catalog = project.commandCatalog();\n const nothing = commands.length > 1 ? \"Nothing in this batch was applied (not even the commands before it): resend the whole corrected batch.\" : \"Nothing was applied.\";\n const templates = new Map<string, string>();\n for (const [index, command] of commands.entries()) {\n if (!catalog[command?.type]) {\n const looksLikeTool = /^[a-z]+(_[a-z]+)+$/.test(String(command?.type));\n return {\n ok: false,\n error: {\n failedIndex: index,\n kind: \"unknown-command\",\n commandType: command?.type,\n error: `\"${command?.type}\" is not a command${looksLikeTool ? \": it is a tool. Call it as its own tool call, not inside apply_commands\" : \"\"}. ${nothing}`,\n validTypes: Object.keys(catalog).sort(),\n },\n };\n }\n const htmlError = checkHtmlParams(project, command, templates);\n if (htmlError) return { ok: false, error: { failedIndex: index, commandType: command.type, error: `${htmlError} ${nothing}` } };\n const extra = unknownFields(catalog[command?.type], command?.payload);\n if (extra) {\n return {\n ok: false,\n error: {\n failedIndex: index,\n commandType: command.type,\n error: `unknown field${extra.unknown.length > 1 ? \"s\" : \"\"} ${extra.unknown.map((f) => `\"${f}\"`).join(\", \")}: ${command.type} would ignore ${extra.unknown.length > 1 ? \"them\" : \"it\"}. Its fields are: ${extra.allowed.join(\", \")}. ${nothing}`,\n },\n };\n }\n }\n const unchanged: number[] = [];\n let failure: unknown;\n try {\n project.transaction(() => {\n commands.forEach((command, index) => {\n const before = project.getState().doc;\n const result = tryDispatch(project, command);\n if (!result.ok) {\n const hint = rejectionHint(result.error as { code?: string; commandType?: string }, command);\n const skipped = commands.length > 1 ? { notApplied: describeCommands(commands.filter((_, i) => i !== index)) } : {};\n failure = { failedIndex: index, ...result.error, ...(hint ? { hint } : {}), note: nothing, ...skipped };\n throw new Abort();\n }\n if (project.getState().doc === before) unchanged.push(index);\n });\n });\n } catch (err) {\n if (err instanceof Abort) return { ok: false, error: failure };\n throw err;\n }\n const changed = commands.filter((_, i) => !unchanged.includes(i));\n return {\n ok: true,\n result: {\n applied: changed.length,\n ...(unchanged.length\n ? { unchanged: unchanged.map((i) => ({ index: i, type: commands[i]!.type, note: \"changed nothing: the project already had these values. Check the field names and values.\" })) }\n : {}),\n },\n ...(changed.length ? { changes: describeCommands(changed) } : {}),\n };\n}\n\n/** html clips substitute `{{name}}` placeholders: params with any other name change nothing on screen. */\nfunction checkHtmlParams(project: Project, command: Command, templates: Map<string, string>): string | undefined {\n const p = (command.payload ?? {}) as Record<string, unknown>;\n let template: string | undefined;\n if (command.type === \"clip/add\" && p.kind === \"html\" && typeof p.template === \"string\") {\n template = p.template;\n if (typeof p.id === \"string\") templates.set(p.id, template);\n } else if (command.type === \"clip/set-property\" && p.params && typeof p.params === \"object\") {\n const clip = project.getState().doc.clips[String(p.clipId)] as { kind?: string; template?: string } | undefined;\n template = templates.get(String(p.clipId)) ?? (clip?.kind === \"html\" ? clip.template : undefined);\n }\n if (template === undefined || !p.params || typeof p.params !== \"object\") return undefined;\n const names = htmlPlaceholders(template);\n const unknown = Object.keys(p.params).filter((k) => !names.includes(k));\n if (!unknown.length) return undefined;\n return `html params ${unknown.map((k) => `\"${k}\"`).join(\", \")} match no {{placeholder}} in the template, so they would change nothing. Its placeholders: ${names.join(\", \") || \"none\"}.`;\n}\n\n/** What to do instead, for rejections models commonly hit. */\nfunction rejectionHint(error: { code?: string }, _command: Command): string | undefined {\n switch (error.code) {\n case \"no-audio\":\n return \"fadeInUs / fadeOutUs fade audio only. To fade a text, image or video picture in or out, call animate_clip (in / out: fade).\";\n case \"asset-not-found\":\n return \"Clips can only use assets already in the project (see get_state). Audio found with search_audio is added with add_audio, which imports it.\";\n case \"not-caption\":\n case \"not-html\":\n case \"not-text\":\n return \"That field belongs to another clip kind: text clips take color / font fields, caption clips take style, html clips take params (named by the template's {{placeholders}}, shown in get_state).\";\n default:\n return undefined;\n }\n}\n\n/** Why two clips have no cut between them, so the model reports it instead of picking another cut. */\nfunction noCutReason(project: Project, fromId: unknown, toId: unknown): string {\n const doc = project.getState().doc;\n const a = typeof fromId === \"string\" ? doc.clips[fromId] : undefined;\n const b = typeof toId === \"string\" ? doc.clips[toId] : undefined;\n const tail = \"Nothing was added. Don't substitute a different cut: tell the user, and offer an animation (animate_clip) instead if that fits.\";\n for (const [given, clip] of [[fromId, a], [toId, b]] as const) if (typeof given === \"string\" && !clip) return `There is no clip \"${given}\". ${tail}`;\n if (a && b && a.trackId !== b.trackId) return `${a.id} is on track ${a.trackId} and ${b.id} on track ${b.trackId}: a transition joins two clips that touch on the SAME track, so these two have no cut between them. ${tail}`;\n if (a && b) return `${a.id} and ${b.id} don't touch (${a.id} ends at ${seconds(a.startUs + a.durationUs)}, ${b.id} starts at ${seconds(b.startUs)}). ${tail}`;\n return `No cut ${a ? `starts after ${a.id}` : `leads into ${b!.id}`} (it isn't directly after/before another clip on its track). ${tail}`;\n}\n\nfunction cutInfo(c: Cut) {\n return { fromClipId: c.fromClipId, toClipId: c.toClipId, atSeconds: c.atUs / S, maxSeconds: c.maxTransitionUs / S, ...(c.transition ? { transition: c.transition.kind } : {}) };\n}\n\n/** apply_commands' input schema: `type` is an enum of the catalog's commands. */\nexport function applyCommandsSchema(catalog: Record<string, unknown>): Record<string, unknown> {\n const [dispatch] = toToolDefinitions(catalog, { mode: \"dispatch\" }) as { input_schema: Record<string, unknown> }[];\n return {\n type: \"object\",\n properties: {\n commands: { type: \"array\", minItems: 1, items: dispatch!.input_schema, description: \"Commands applied in order, as one batch.\" },\n },\n required: [\"commands\"],\n additionalProperties: false,\n };\n}\n","import { createProject, type Command, type Project } from \"@miraiclip/core\";\n\n/**\n * A working copy of a project that records every command that sticks.\n *\n * The assistant edits the copy while the model thinks (async, many steps);\n * the real project only changes when the turn commits, by replaying the\n * recorded commands in one transaction — one undo step, and nothing half-done\n * if the request fails. Commands inside a transaction that rolls back are\n * dropped, exactly as the copy drops their effects.\n *\n * Replay must produce the same ids the model saw, so commands whose ids are\n * optional get explicit ones before they run.\n */\nexport interface RecordingProject extends Project {\n /** Commands that changed the copy, in order. */\n readonly recorded: readonly Command[];\n}\n\nexport interface ForkOptions {\n /** Build the copy (default: `createProject(doc)`). Register custom commands here. */\n createFork?: (doc: ReturnType<Project[\"toJSON\"]>) => Project;\n /** Give commands explicit ids (default handles the built-ins with optional ids). */\n ensureIds?: (command: Command) => Command;\n}\n\nlet seq = 0;\nconst genId = (prefix: string) => `${prefix}-${Date.now().toString(36)}${(++seq).toString(36)}${Math.random().toString(36).slice(2, 6)}`;\n\n/** Built-in commands that would otherwise get a random id inside the engine. */\nexport function withExplicitIds(command: Command): Command {\n const p = (command.payload ?? {}) as Record<string, unknown>;\n const set = (field: string, prefix: string) =>\n p[field] === undefined ? { ...command, payload: { ...p, [field]: genId(prefix) } } : command;\n switch (command.type) {\n case \"clip/split\":\n case \"clip/duplicate\":\n return set(\"newClipId\", \"clip\");\n case \"effect/add\":\n return set(\"effectId\", \"fx\");\n case \"transition/add\":\n return set(\"id\", \"tr\");\n default:\n return command;\n }\n}\n\nexport function forkProject(project: Project, options: ForkOptions = {}): RecordingProject {\n const fork = (options.createFork ?? ((doc) => createProject(doc)))(project.toJSON());\n const state = project.getState();\n fork.setPlayhead(state.playheadUs);\n fork.setSelection([...state.selection]);\n const ensure = options.ensureIds ?? withExplicitIds;\n const recorded: Command[] = [];\n let depth = 0;\n let buffer: Command[] = [];\n\n return {\n ...fork,\n get recorded() {\n return recorded;\n },\n dispatch(command) {\n const explicit = ensure(command as Command);\n const before = fork.getState().doc;\n fork.dispatch(explicit);\n if (fork.getState().doc === before) return; // no-op: nothing to replay\n if (depth > 0) buffer.push(explicit);\n else recorded.push(explicit);\n },\n transaction(fn, label) {\n if (depth > 0) {\n fn();\n return;\n }\n depth = 1;\n buffer = [];\n try {\n fork.transaction(fn, label);\n recorded.push(...buffer);\n } finally {\n depth = 0;\n buffer = [];\n }\n },\n };\n}\n\nexport type CommitResult = { ok: true; applied: number } | { ok: false; error: string };\n\n/** Replay a fork's commands onto the real project as one undoable step. */\nexport function commitFork(project: Project, fork: RecordingProject, label?: string): CommitResult {\n if (fork.recorded.length === 0) return { ok: true, applied: 0 };\n try {\n project.transaction(() => {\n for (const command of fork.recorded) project.dispatch(command);\n }, label);\n return { ok: true, applied: fork.recorded.length };\n } catch (err) {\n return {\n ok: false,\n error: `The project changed while the assistant was working, so its edit no longer applies (${(err as Error)?.message ?? err}). Ask again.`,\n };\n }\n}\n","import type { Command, Project, ProjectDocument } from \"@miraiclip/core\";\nimport { describeForAssistant } from \"./state.js\";\nimport { commitFork, forkProject, type CommitResult, type ForkOptions } from \"./fork.js\";\nimport { editorTools, type AssistantTool } from \"./tools.js\";\nimport type { ChatMessage, ChatModel, ChatUsage, ToolCall } from \"./types.js\";\n\nexport interface AssistantOptions {\n model: ChatModel;\n /** Default `editorTools()`. Add your own (audio, captions, stock media…). */\n tools?: AssistantTool[];\n /** Extra system instructions (brand voice, house rules). */\n instructions?: string;\n /** Model round-trips per request (default 12). */\n maxSteps?: number;\n /** Model id when the adapter serves several. */\n modelId?: string;\n maxOutputTokens?: number;\n /** Vendor request fields, passed through. */\n params?: Record<string, unknown>;\n fork?: ForkOptions;\n}\n\nexport type AssistantEvent =\n | { type: \"text\"; delta: string }\n | { type: \"tool-start\"; call: ToolCall }\n | { type: \"tool-end\"; call: ToolCall; ok: boolean; changes?: string[]; error?: string }\n | { type: \"step\"; index: number };\n\nexport interface TurnOptions {\n /** Earlier messages of this conversation (`turn.messages` from the last turn). */\n history?: readonly ChatMessage[];\n /** What the user is looking at, e.g. \"Selected: clip t-1. Playhead: 4.2s.\" */\n context?: string;\n /** \"auto\" (default) commits when the request finishes; \"review\" waits for `turn.apply()`. */\n apply?: \"auto\" | \"review\";\n signal?: AbortSignal;\n onEvent?: (event: AssistantEvent) => void;\n /** History label for the undo step (default \"Assistant: <request>\"). */\n label?: string;\n}\n\nexport interface AssistantTurn {\n /** The model's final answer to the user. */\n reply: string;\n /** Human-readable list of what the turn changed (empty when nothing). */\n changes: string[];\n /** The commands the turn makes, in order (replayed onto the project on apply). */\n commands: readonly Command[];\n /**\n * applied: committed as one undo step. review: waiting for apply()/discard().\n * no-changes: nothing to apply. failed / canceled: the project wasn't touched.\n */\n status: \"applied\" | \"review\" | \"no-changes\" | \"failed\" | \"canceled\";\n error?: string;\n /** The project as the turn left it (for previews in review mode). */\n preview: ProjectDocument;\n /** The conversation so far, without the system prompt: pass back as `history`. */\n messages: ChatMessage[];\n usage: Required<ChatUsage>;\n /** Commit a reviewed turn (no-op once applied). */\n apply(): CommitResult;\n discard(): void;\n}\n\nexport interface Assistant {\n readonly tools: readonly AssistantTool[];\n run(project: Project, request: string, options?: TurnOptions): Promise<AssistantTurn>;\n}\n\nconst MAX_TOOL_RESULT = 20_000;\nconst MAX_OLD_TOOL_RESULT = 2_000;\n\nexport const DEFAULT_INSTRUCTIONS = `You are the editing assistant inside a video editor. You change the user's project by calling tools; every change you make lands as ONE undo step when you finish, so act confidently.\n\nHow to work:\n- The current project is summarized below. Clip, track and asset ids there are what tools expect. Call get_state to re-read it after big changes.\n- Prefer the high-level tools when they fit (add_transition, animate_clip, add_effect, set_effects_enabled, set_background, trim_clip, set_keyframes, close_gaps, and any audio or media tools). Call tools directly; apply_commands takes only editing commands like \"clip/add\", never tool names. Use apply_commands for everything else, batching related commands; look up a command's payload with get_command_schema the first time you use it, and use only the fields it lists.\n- Fading a picture (text, image, logo, video) in or out is animate_clip (in / out: fade). fadeInUs / fadeOutUs are audio fades. \"Fade the video in at the start / out at the end\" means the first clip's entrance and the last clip's exit.\n- Constant values are set directly with clip/set-property: rotation (\"rotate 45°\", \"tilt\"), volume (\"lower to 30%\", \"louder\"), position, size, opacity. Only values that CHANGE over a time range (\"duck the music between 10 and 15 s\", \"fade to silence between 18 and 20 s\", \"spin one full turn\", \"pan across\") are keyframes: set_keyframes, with times in timeline seconds. Remove an animation with keyframe/clear.\n- \"Cuts\" are the ones listed in the project summary; use their times (e.g. one sound per cut).\n- \"Add N more seconds of footage\" adds a new clip (clip/add with trimStartUs for the source point) after the last one; it does not stretch an existing clip.\n- Caption looks (box behind the text, outline, shadow, colors, word preset) are the caption clip's style (clip/set-property { style }).\n- \"The whole video\" means from 0 to the composition length (trim_clip startSeconds / endSeconds).\n- A solid color background behind everything is set_background (add, recolor, remove). Other html clips are recolored through the params their template uses (shown in the clip details). A new track goes on top unless track/add gets index 0 (the bottom).\n- \"Replace X with Y\" removes X and adds Y in the same turn, whichever tool adds Y (audio tools take replaceClipId, which does both).\n- Solo / mute / lock / hide a track with track/set-property (solo, muted, locked, hidden). \"Solo X\" is solo: true on X, not muting the others.\n- Relative requests (\"bigger\", \"louder\", \"a bit brighter\", \"twice as big\") start from the current values in the clip details below: make a visible change in the asked direction (about 25% for \"bigger\"/\"smaller\", ×2 for \"twice\").\n- When something is selected, \"this\", \"it\", \"the clip\" and any request that names no target mean ONLY the selection, even with words like \"at the end\" (the end of that clip). Edit nothing else. \"Here\" / \"now\" / \"this point\" mean the playhead. \"Clips\" without a kind mean the video clips on the main video track.\n- \"Again\" / \"also\" / \"another\" mean keep the original and add a copy (clip/duplicate, or clip/add with the same asset); never move the original. \"Instead\" means move or replace.\n- Removing a clip leaves a gap; when asked to close it, also run close_gaps (or trim_clip with ripple).\n- Commands use integer microseconds (1 second = 1000000). High-level tools take seconds.\n- Positions (transform x, y) are fractions of the frame: 0.5, 0.5 is the center.\n- Only reference media that exists in the project or that a tool returned. Never invent file URLs.\n- If a tool fails, read the error, fix the input and retry. A failed apply_commands batch applied NONE of its commands: resend all of them, corrected. If something can't be done, say why.\n- If the request is ambiguous in a way that matters, ask one short question instead of guessing.\n\nWhen you're done, reply in one to three short sentences: what you changed, in plain words (times in seconds, names over ids). Describe only edits your tools reported as applied; if a tool says something changed nothing or failed, fix it or say so. No markdown headings.`;\n\nexport function createAssistant(options: AssistantOptions): Assistant {\n const tools = options.tools ?? editorTools();\n const byName = new Map(tools.map((t) => [t.name, t]));\n const specs = tools.map(({ name, description, inputSchema }) => ({ name, description, inputSchema }));\n const maxSteps = options.maxSteps ?? 12;\n\n return {\n tools,\n async run(project, request, turn = {}) {\n const fork = forkProject(project, options.fork);\n const emit = turn.onEvent ?? (() => {});\n const usage = { inputTokens: 0, outputTokens: 0 };\n const changes: string[] = [];\n const history = trimHistory(turn.history ?? []);\n const added: ChatMessage[] = [{ role: \"user\", content: request }];\n const system = [\n DEFAULT_INSTRUCTIONS,\n options.instructions?.trim(),\n `Current project:\\n${describeForAssistant(fork.toJSON())}`,\n turn.context?.trim() ? `What the user is looking at: ${turn.context.trim()}` : undefined,\n selectionNote(fork.toJSON(), fork.getState().selection),\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n let reply = \"\";\n let status: AssistantTurn[\"status\"] = \"no-changes\";\n let error: string | undefined;\n\n try {\n for (let step = 0; ; step++) {\n if (step >= maxSteps) {\n reply = (reply ? `${reply}\\n\\n` : \"\") + `I stopped after ${maxSteps} steps; what I finished is applied. Ask me to continue if there's more.`;\n break;\n }\n emit({ type: \"step\", index: step });\n const response = await options.model.complete(\n {\n messages: [{ role: \"system\", content: system }, ...history, ...added],\n tools: specs,\n ...(options.modelId ? { model: options.modelId } : {}),\n ...(options.maxOutputTokens ? { maxOutputTokens: options.maxOutputTokens } : {}),\n ...(options.params ? { params: options.params } : {}),\n },\n { ...(turn.signal ? { signal: turn.signal } : {}), onText: (delta) => emit({ type: \"text\", delta }) },\n );\n usage.inputTokens += response.usage?.inputTokens ?? 0;\n usage.outputTokens += response.usage?.outputTokens ?? 0;\n added.push({ role: \"assistant\", content: response.content, ...(response.toolCalls.length ? { toolCalls: response.toolCalls } : {}) });\n if (response.toolCalls.length === 0) {\n reply = response.content.trim();\n break;\n }\n for (const call of response.toolCalls) {\n if (turn.signal?.aborted) throw abortError();\n emit({ type: \"tool-start\", call });\n const out = await runTool(byName.get(call.name), call, fork, turn.signal);\n if (out.ok && out.changes?.length) changes.push(...out.changes);\n emit({\n type: \"tool-end\",\n call,\n ok: out.ok,\n ...(out.ok && out.changes?.length ? { changes: out.changes } : {}),\n ...(!out.ok ? { error: short(out.error) } : {}),\n });\n added.push({ role: \"tool\", toolCallId: call.id, name: call.name, content: cap(out.ok ? out.result ?? { ok: true } : { ok: false, error: out.error }, MAX_TOOL_RESULT) });\n }\n }\n status = fork.recorded.length === 0 ? \"no-changes\" : turn.apply === \"review\" ? \"review\" : \"applied\";\n } catch (err) {\n status = turn.signal?.aborted || (err as Error)?.name === \"AbortError\" ? \"canceled\" : \"failed\";\n error = (err as Error)?.message ?? String(err);\n }\n\n let committed = false;\n let discarded = false;\n const label = turn.label ?? `Assistant: ${request.length > 40 ? `${request.slice(0, 39)}…` : request}`;\n const apply = (): CommitResult => {\n if (committed) return { ok: true, applied: 0 };\n if (discarded) return { ok: false, error: \"This edit was discarded.\" };\n if (status === \"failed\" || status === \"canceled\") return { ok: false, error: error ?? status };\n const result = commitFork(project, fork, label);\n if (result.ok) committed = true;\n return result;\n };\n if (status === \"applied\") {\n const result = apply();\n if (!result.ok) {\n status = \"failed\";\n error = result.error;\n }\n }\n\n return {\n reply,\n changes,\n commands: fork.recorded,\n status,\n ...(error !== undefined ? { error } : {}),\n preview: fork.toJSON(),\n messages: [...history, ...added],\n usage,\n apply,\n discard() {\n if (!committed) discarded = true;\n },\n };\n },\n };\n}\n\nasync function runTool(tool: AssistantTool | undefined, call: ToolCall, project: Project, signal?: AbortSignal) {\n if (!tool) return { ok: false as const, error: `unknown tool \"${call.name}\"` };\n if (\"__invalidArguments\" in call.arguments) return { ok: false as const, error: \"the tool arguments weren't valid JSON; send a JSON object\" };\n try {\n return await tool.run(call.arguments, { project, ...(signal ? { signal } : {}) });\n } catch (err) {\n if ((err as Error)?.name === \"AbortError\") throw err;\n return { ok: false as const, error: (err as Error)?.message ?? String(err) };\n }\n}\n\nfunction cap(value: unknown, max: number): string {\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return text.length > max ? `${text.slice(0, max)}… [truncated ${text.length - max} chars]` : text;\n}\n\nconst short = (e: unknown) => {\n const text = typeof e === \"string\" ? e : JSON.stringify(e);\n return text.length > 300 ? `${text.slice(0, 299)}…` : text;\n};\n\n/**\n * Earlier turns keep their shape but not their bulky tool output. A turn cut\n * short (canceled, failed) can leave tool calls without results, which\n * vendors reject: those get a \"not run\" result.\n */\nfunction trimHistory(history: readonly ChatMessage[]): ChatMessage[] {\n const answered = new Set(history.flatMap((m) => (m.role === \"tool\" ? [m.toolCallId] : [])));\n const out: ChatMessage[] = [];\n for (const m of history) {\n if (m.role === \"system\") continue;\n if (m.role === \"tool\") {\n out.push(m.content.length > MAX_OLD_TOOL_RESULT ? { ...m, content: `${m.content.slice(0, MAX_OLD_TOOL_RESULT)}… [truncated]` } : m);\n continue;\n }\n out.push(m);\n if (m.role === \"assistant\") {\n for (const call of m.toolCalls ?? []) {\n if (!answered.has(call.id)) out.push({ role: \"tool\", toolCallId: call.id, name: call.name, content: '{\"ok\":false,\"error\":\"not run: the request was interrupted\"}' });\n }\n }\n }\n return out;\n}\n\nfunction abortError() {\n const err = new Error(\"canceled\");\n err.name = \"AbortError\";\n return err;\n}\n\n/** The selection, stated as a scope rule right before the request (models drift to \"all clips\" otherwise). */\nfunction selectionNote(doc: ProjectDocument, selection: readonly string[]): string | undefined {\n const clips = selection.map((id) => doc.clips[id]).filter((c): c is NonNullable<typeof c> => !!c);\n if (!clips.length) return undefined;\n const list = clips.map((c) => `${c.id} (${c.kind}, ${Number((c.startUs / 1e6).toFixed(2))}–${Number(((c.startUs + c.durationUs) / 1e6).toFixed(2))}s)`).join(\", \");\n return `Selected: ${list}. In this request, \"this\", \"it\", \"the clip\" and anything that names no target mean ONLY ${clips.map((c) => c.id).join(\", \")}. Leave every other clip alone.`;\n}\n","import { defineChatModel, type ChatModel, type ChatRequest, type ChatResponse, type ToolCall } from \"./types.js\";\n\nexport type ScriptStep =\n | string\n | { text?: string; toolCalls?: (Omit<ToolCall, \"id\"> & { id?: string })[] }\n | ((request: ChatRequest, index: number) => ScriptStep);\n\n/**\n * A model that answers from a script: for tests, demos and offline\n * development. Each `complete` call takes the next step; a string is a final\n * text answer, an object can call tools. Requests are kept in `requests`.\n */\nexport function scriptedChatModel(steps: ScriptStep[], options: { id?: string } = {}): ChatModel & { requests: ChatRequest[] } {\n const requests: ChatRequest[] = [];\n let i = 0;\n const model = defineChatModel({\n id: options.id ?? \"scripted\",\n label: \"Scripted model\",\n async complete(request: ChatRequest, opts: { onText?: (delta: string) => void } = {}): Promise<ChatResponse> {\n requests.push(structuredClone(request));\n let step: ScriptStep = steps[Math.min(i, steps.length - 1)] ?? \"Done.\";\n while (typeof step === \"function\") step = step(request, i);\n i++;\n const s = typeof step === \"string\" ? { text: step } : step;\n if (s.text) opts.onText?.(s.text);\n const toolCalls = (s.toolCalls ?? []).map((c, n) => ({ id: c.id ?? `call_${i}_${n}`, name: c.name, arguments: c.arguments }));\n return { content: s.text ?? \"\", toolCalls, finish: toolCalls.length ? \"tool_calls\" : \"stop\", usage: { inputTokens: 10, outputTokens: 5 } };\n },\n });\n return Object.assign(model, { requests });\n}\n"],"mappings":"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","names":["json","n","describeAnimation","findCuts","findCuts","describeAnimation","commands","out","usage","n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/wire.ts","../src/openai.ts","../src/anthropic.ts","../src/gemini.ts","../src/providers.ts","../src/http.ts","../src/limits.ts","../src/state.ts","../src/strict.ts","../src/tools.ts","../src/fork.ts","../src/run.ts","../src/testing.ts"],"sourcesContent":["/**\n * The vendor-neutral model contract. An adapter turns these neutral messages\n * and tools into one vendor's API and back; nothing else in the package knows\n * which vendor is on the other end.\n */\n\n/** A tool call the model made. `arguments` is already parsed JSON. */\nexport interface ToolCall {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n /**\n * Opaque data the adapter that produced the call needs back when the\n * conversation is replayed (Gemini thought signatures, Anthropic thinking\n * blocks). Keep it with the call; other adapters ignore it.\n */\n meta?: Record<string, unknown>;\n}\n\nexport type ChatMessage =\n | { role: \"system\"; content: string }\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string; toolCalls?: ToolCall[] }\n | { role: \"tool\"; toolCallId: string; name: string; content: string };\n\n/** A tool as the model sees it: name, description and a JSON Schema for its input. */\nexport interface ToolSpec {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n}\n\nexport interface ChatRequest {\n messages: ChatMessage[];\n tools?: ToolSpec[];\n /** Model id, when the adapter serves several. */\n model?: string;\n maxOutputTokens?: number;\n /** Vendor-specific request fields, passed through untouched (e.g. `{ reasoning_effort: \"low\" }`). */\n params?: Record<string, unknown>;\n}\n\nexport interface ChatUsage {\n inputTokens?: number;\n outputTokens?: number;\n}\n\nexport interface ChatResponse {\n content: string;\n toolCalls: ToolCall[];\n /** Why the model stopped. */\n finish: \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"other\";\n model?: string;\n usage?: ChatUsage;\n}\n\nexport interface ChatOptions {\n signal?: AbortSignal;\n /** Streaming text, as it arrives (adapters that can't stream call it once). */\n onText?: (delta: string) => void;\n}\n\nexport interface ModelEntry {\n id: string;\n label?: string;\n}\n\nexport interface ChatModelInfo {\n /** Adapter id, e.g. \"openai\". Alphanumeric with - or _. */\n id: string;\n label: string;\n /** Models this adapter serves; the first is the default. */\n models?: ModelEntry[];\n /** For a model that routes to several providers (`routedChatModel`): which ones. */\n providers?: { id: string; label: string }[];\n}\n\nexport interface ChatModel extends ChatModelInfo {\n complete(request: ChatRequest, options?: ChatOptions): Promise<ChatResponse>;\n /** Every model the account behind this adapter can use, live from the vendor (for model pickers). */\n listModels?(options?: { signal?: AbortSignal }): Promise<ModelEntry[]>;\n}\n\n/** An error from a model vendor, carrying its HTTP status when there was one. */\nexport class ChatModelError extends Error {\n constructor(\n readonly provider: string,\n message: string,\n readonly status?: number,\n ) {\n super(`${provider}: ${message}`);\n this.name = \"ChatModelError\";\n }\n}\n\nexport type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;\n\nexport function defaultFetch(): FetchLike {\n if (typeof fetch !== \"function\") throw new Error(\"No global fetch: pass `fetch` explicitly\");\n return (url, init) => fetch(url, init);\n}\n\n/** Check an adapter's shape once, at registration. */\nexport function defineChatModel<M extends ChatModel>(model: M): M {\n if (!model.id || !/^[a-z0-9][a-z0-9_-]*$/i.test(model.id)) {\n throw new Error(`Chat model id must be alphanumeric with - or _ (got \"${model.id}\")`);\n }\n if (typeof model.complete !== \"function\") throw new Error(`Chat model \"${model.id}\" has no complete()`);\n return model;\n}\n","/**\n * Plumbing the vendor adapters share: POST with retries on rate limits and\n * server errors, server-sent-event reading, and tool-argument parsing.\n */\nimport { ChatModelError, type FetchLike } from \"./types.js\";\n\n/** Parse a tool call's JSON arguments; unparseable JSON is reported to the model as a tool error. */\nexport function parseToolArguments(raw: string): Record<string, unknown> {\n if (!raw.trim()) return {};\n try {\n const value = JSON.parse(raw) as unknown;\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : { __invalidArguments: raw };\n } catch {\n return { __invalidArguments: raw };\n }\n}\n\n/** How long the server asked us to wait (Retry-After header, or \"try again in 1.2s / 350ms\"), else exponential backoff. */\nexport function retryDelayMs(res: Pick<Response, \"headers\">, message: string, attempt: number): number {\n const header = Number(res.headers.get(\"retry-after-ms\") ?? NaN) || Number(res.headers.get(\"retry-after\") ?? NaN) * 1000;\n const m = /try again in ([\\d.]+)\\s*(ms|s)/i.exec(message);\n const asked = header || (m ? Number(m[1]) * (m[2]!.toLowerCase() === \"ms\" ? 1 : 1000) : 0);\n const backoff = Math.min(30_000, 1000 * 2 ** attempt);\n // A little extra and some jitter, so parallel callers don't all retry at the same instant.\n return Math.round(Math.min(60_000, Math.max(asked + 250, asked ? 0 : backoff)) * (1 + Math.random() * 0.25));\n}\n\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason ?? new Error(\"aborted\"));\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\"abort\", () => (clearTimeout(t), reject(signal.reason ?? new Error(\"aborted\"))), { once: true });\n });\n}\n\n/** 529 is Anthropic's \"overloaded\". */\nconst RETRYABLE = new Set([429, 500, 502, 503, 504, 529]);\n\n/** The message out of the error bodies vendors send ({ error: { message } }, { error: \"…\" }, { message }). */\nexport function errorMessage(body: unknown, status: number): string {\n const b = body as { error?: { message?: string } | string; message?: string } | null;\n const msg = typeof b?.error === \"string\" ? b.error : (b?.error?.message ?? b?.message);\n return msg || `HTTP ${status}`;\n}\n\n/**\n * Send a request, retrying 429s and 5xx (waiting as long as the server asks,\n * else 1 s, 2 s, 4 s… capped at 30 s). A 429 for an exhausted quota, missing\n * credits or billing won't clear by waiting, so it fails at once.\n */\nexport async function sendWithRetry(\n provider: string,\n doFetch: FetchLike,\n url: string,\n init: RequestInit,\n options: { maxRetries?: number; signal?: AbortSignal } = {},\n): Promise<Response> {\n const maxRetries = options.maxRetries ?? 4;\n for (let attempt = 0; ; attempt++) {\n let res: Response;\n try {\n res = await doFetch(url, { ...init, ...(options.signal ? { signal: options.signal } : {}) });\n } catch (err) {\n if ((err as Error)?.name === \"AbortError\" || options.signal?.aborted) throw err;\n throw new ChatModelError(provider, `request failed: ${(err as Error)?.message ?? err}`);\n }\n if (res.ok) return res;\n const message = errorMessage(await res.json().catch(() => null), res.status);\n const permanent = /quota|credit|billing/i.test(message);\n if (attempt >= maxRetries || !RETRYABLE.has(res.status) || permanent) throw new ChatModelError(provider, message, res.status);\n await sleep(retryDelayMs(res, message, attempt), options.signal);\n }\n}\n\n/** GET a JSON document, as a ChatModelError on failure. */\nexport async function getJson(provider: string, doFetch: FetchLike, url: string, headers: Record<string, string>, signal?: AbortSignal): Promise<unknown> {\n const res = await sendWithRetry(provider, doFetch, url, { method: \"GET\", headers }, { maxRetries: 1, ...(signal ? { signal } : {}) });\n return res.json();\n}\n\n/**\n * Server-sent events: calls `onData` with each `data:` line's payload. Every\n * vendor here sends one JSON object per data line, and handling lines one by\n * one also copes with servers that skip the blank line between events.\n */\nexport async function readSse(body: ReadableStream<Uint8Array>, onData: (data: string) => void): Promise<void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n const line = (raw: string) => {\n const l = raw.replace(/\\r$/, \"\");\n if (l.startsWith(\"data:\")) onData(l.slice(5).trim());\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (value) buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n line(buffer.slice(0, nl));\n buffer = buffer.slice(nl + 1);\n }\n if (done) break;\n }\n if (buffer) line(buffer);\n}\n\n/** True when a response is an event stream we should read incrementally. */\nexport const isEventStream = (res: Response) => !!res.body && (res.headers.get(\"content-type\") ?? \"\").includes(\"event-stream\");\n\nexport const trimSlash = (url: string) => url.replace(/\\/+$/, \"\");\n\n/** The adapter's model list: the default first (keeping its label if `others` has one), then the rest. */\nexport function modelList(model: string, others: readonly { id: string; label?: string }[] = []): { id: string; label?: string }[] {\n return [others.find((m) => m.id === model) ?? { id: model }, ...others.filter((m) => m.id !== model)];\n}\n","/**\n * OpenAI adapter, over the Chat Completions API with function calling.\n *\n * Chat Completions is also what most other servers speak (Azure OpenAI,\n * OpenRouter, Groq, Together, vLLM, Ollama, LM Studio…), so `baseUrl` points\n * this one adapter at any of them.\n */\nimport {\n defaultFetch,\n defineChatModel,\n type ChatMessage,\n type ChatModel,\n type ChatRequest,\n type ChatResponse,\n type FetchLike,\n type ToolCall,\n} from \"./types.js\";\nimport { getJson, isEventStream, modelList, parseToolArguments, readSse, sendWithRetry, trimSlash } from \"./wire.js\";\n\nexport { parseToolArguments, retryDelayMs } from \"./wire.js\";\n\nexport interface OpenAIChatModelOptions {\n /** Model id, e.g. \"gpt-5.4-mini\". Required: model names change faster than this package. */\n model: string;\n /** Other models the app may pick per request (`ChatRequest.model`). */\n models?: { id: string; label?: string }[];\n /** API key. Omit for local servers that don't need one. Keep it server-side (see `createChatHandler`). */\n apiKey?: string | undefined;\n /** Default https://api.openai.com/v1. Any OpenAI-compatible base URL works. */\n baseUrl?: string;\n organization?: string;\n project?: string;\n headers?: Record<string, string>;\n /** Default request fields merged into every call (e.g. `{ reasoning_effort: \"low\" }`). */\n params?: Record<string, unknown>;\n /** Stream responses (default true). */\n stream?: boolean;\n /**\n * Retries on rate limits (429) and server errors (500/502/503/504), waiting\n * as long as the server asks (Retry-After, or \"try again in 1.2s\"), else\n * backing off 1 s, 2 s, 4 s… (capped at 30 s). Default 4; 0 disables.\n */\n maxRetries?: number;\n /**\n * The request field for the output cap: \"max_completion_tokens\" (default;\n * OpenAI) or \"max_tokens\" (what most other compatible servers read).\n */\n maxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n /** Ask for token usage at the end of a stream (default true; turn off for servers that reject `stream_options`). */\n streamUsage?: boolean;\n /** Adapter id / label (default \"openai\" / \"OpenAI\"), e.g. \"ollama\" when pointing elsewhere. */\n id?: string;\n label?: string;\n fetch?: FetchLike;\n}\n\ntype OpenAIMessage =\n | { role: \"system\" | \"user\"; content: string }\n | { role: \"assistant\"; content: string | null; tool_calls?: { id: string; type: \"function\"; function: { name: string; arguments: string } }[] }\n | { role: \"tool\"; tool_call_id: string; content: string };\n\n/** Neutral messages → Chat Completions messages. */\nexport function toOpenAIMessages(messages: readonly ChatMessage[]): OpenAIMessage[] {\n return messages.map((m): OpenAIMessage => {\n if (m.role === \"assistant\") {\n const out: OpenAIMessage = { role: \"assistant\", content: m.content || null };\n if (m.toolCalls?.length) {\n out.tool_calls = m.toolCalls.map((c) => ({ id: c.id, type: \"function\", function: { name: c.name, arguments: JSON.stringify(c.arguments) } }));\n }\n return out;\n }\n if (m.role === \"tool\") return { role: \"tool\", tool_call_id: m.toolCallId, content: m.content };\n return { role: m.role, content: m.content };\n });\n}\n\nconst FINISH: Record<string, ChatResponse[\"finish\"]> = {\n stop: \"stop\",\n tool_calls: \"tool_calls\",\n function_call: \"tool_calls\",\n length: \"length\",\n content_filter: \"content_filter\",\n};\n\nexport function openAIChatModel(options: OpenAIChatModelOptions): ChatModel {\n const base = trimSlash(options.baseUrl ?? \"https://api.openai.com/v1\");\n const id = options.id ?? \"openai\";\n const doFetch = options.fetch ?? defaultFetch();\n const stream = options.stream ?? true;\n const models = modelList(options.model, options.models);\n const maxTokensField = options.maxTokensField ?? \"max_completion_tokens\";\n\n const headers = (): Record<string, string> => {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\", ...options.headers };\n if (options.apiKey) h[\"Authorization\"] = `Bearer ${options.apiKey}`;\n if (options.organization) h[\"OpenAI-Organization\"] = options.organization;\n if (options.project) h[\"OpenAI-Project\"] = options.project;\n return h;\n };\n\n return defineChatModel({\n id,\n label: options.label ?? \"OpenAI\",\n models,\n async listModels(opts = {}) {\n const json = (await getJson(id, doFetch, `${base}/models`, headers(), opts.signal)) as { data?: { id: string }[] };\n return (json.data ?? []).map((m) => ({ id: m.id })).sort((a, b) => a.id.localeCompare(b.id));\n },\n async complete(request: ChatRequest, opts = {}): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n model: request.model ?? options.model,\n messages: toOpenAIMessages(request.messages),\n ...(request.tools?.length\n ? { tools: request.tools.map((t) => ({ type: \"function\", function: { name: t.name, description: t.description, parameters: t.inputSchema } })) }\n : {}),\n ...(request.maxOutputTokens ? { [maxTokensField]: request.maxOutputTokens } : {}),\n ...(stream ? { stream: true, ...(options.streamUsage === false ? {} : { stream_options: { include_usage: true } }) } : {}),\n ...options.params,\n ...request.params,\n };\n const res = await sendWithRetry(\n id,\n doFetch,\n `${base}/chat/completions`,\n { method: \"POST\", headers: headers(), body: JSON.stringify(body) },\n { ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}), ...(opts.signal ? { signal: opts.signal } : {}) },\n );\n if (!stream || !isEventStream(res)) return fromCompletion(await res.json(), opts.onText);\n return readStream(res.body!, opts.onText);\n },\n });\n}\n\ninterface CompletionJson {\n model?: string;\n choices?: { message?: { content?: string | null; tool_calls?: { id: string; function: { name: string; arguments: string } }[] }; finish_reason?: string }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number };\n}\n\nfunction fromCompletion(json: CompletionJson, onText?: (delta: string) => void): ChatResponse {\n const choice = json.choices?.[0];\n const content = choice?.message?.content ?? \"\";\n if (content) onText?.(content);\n const out: ChatResponse = {\n content,\n toolCalls: (choice?.message?.tool_calls ?? []).map((c) => ({ id: c.id, name: c.function.name, arguments: parseToolArguments(c.function.arguments) })),\n finish: FINISH[choice?.finish_reason ?? \"\"] ?? \"other\",\n };\n if (json.model) out.model = json.model;\n if (json.usage) out.usage = usage(json.usage);\n return out;\n}\n\nconst usage = (u: { prompt_tokens?: number; completion_tokens?: number }) => ({\n ...(u.prompt_tokens !== undefined ? { inputTokens: u.prompt_tokens } : {}),\n ...(u.completion_tokens !== undefined ? { outputTokens: u.completion_tokens } : {}),\n});\n\ninterface ChunkJson {\n model?: string;\n choices?: {\n delta?: { content?: string | null; tool_calls?: { index: number; id?: string; function?: { name?: string; arguments?: string } }[] };\n finish_reason?: string | null;\n }[];\n usage?: { prompt_tokens?: number; completion_tokens?: number } | null;\n}\n\n/** Server-sent events → one response; text deltas stream to `onText`, tool-call fragments are joined by index. */\nasync function readStream(body: ReadableStream<Uint8Array>, onText?: (delta: string) => void): Promise<ChatResponse> {\n let content = \"\";\n let finish: ChatResponse[\"finish\"] = \"other\";\n let model: string | undefined;\n let use: ChatResponse[\"usage\"];\n const calls = new Map<number, { id: string; name: string; args: string }>();\n\n const handle = (data: string) => {\n if (data === \"[DONE]\") return;\n let chunk: ChunkJson;\n try {\n chunk = JSON.parse(data) as ChunkJson;\n } catch {\n return;\n }\n if (chunk.model) model = chunk.model;\n if (chunk.usage) use = usage(chunk.usage);\n for (const choice of chunk.choices ?? []) {\n const delta = choice.delta;\n if (delta?.content) {\n content += delta.content;\n onText?.(delta.content);\n }\n for (const tc of delta?.tool_calls ?? []) {\n const call = calls.get(tc.index) ?? { id: \"\", name: \"\", args: \"\" };\n if (tc.id) call.id = tc.id;\n if (tc.function?.name) call.name += tc.function.name;\n if (tc.function?.arguments) call.args += tc.function.arguments;\n calls.set(tc.index, call);\n }\n if (choice.finish_reason) finish = FINISH[choice.finish_reason] ?? \"other\";\n }\n };\n\n await readSse(body, handle);\n\n const toolCalls: ToolCall[] = [...calls.entries()]\n .sort(([a], [b]) => a - b)\n .map(([index, c]) => ({ id: c.id || `call_${index}`, name: c.name, arguments: parseToolArguments(c.args) }));\n const out: ChatResponse = { content, toolCalls, finish };\n if (model) out.model = model;\n if (use) out.usage = use;\n return out;\n}\n","/**\n * Anthropic adapter, over the Messages API with tool use.\n *\n * System messages become the top-level `system` prompt; tool results are\n * grouped into one user turn, as the API expects. When extended thinking is\n * on (`params: { thinking: … }`), the thinking blocks of a tool-using turn\n * ride on the first tool call's `meta` and are sent back on the next request,\n * which the API requires.\n */\nimport {\n ChatModelError,\n defaultFetch,\n defineChatModel,\n type ChatMessage,\n type ChatModel,\n type ChatRequest,\n type ChatResponse,\n type FetchLike,\n type ToolCall,\n} from \"./types.js\";\nimport { getJson, isEventStream, modelList, parseToolArguments, readSse, sendWithRetry, trimSlash } from \"./wire.js\";\n\nexport interface AnthropicChatModelOptions {\n /** Model id, e.g. \"claude-sonnet-5-5\". Required: model names change faster than this package. */\n model: string;\n /** Other models the app may pick per request (`ChatRequest.model`). */\n models?: { id: string; label?: string }[];\n /** API key. Keep it server-side (see `createChatHandler`) unless it's the user's own key in their own browser (`browser`). */\n apiKey?: string | undefined;\n /** Default https://api.anthropic.com (requests go to `{baseUrl}/v1/messages`). */\n baseUrl?: string;\n /** `anthropic-version` header (default \"2023-06-01\"). */\n version?: string;\n /** `anthropic-beta` flags, joined with commas. */\n betas?: string[];\n headers?: Record<string, string>;\n /** Default request fields merged into every call (e.g. `{ thinking: { type: \"enabled\", budget_tokens: 4000 } }`). */\n params?: Record<string, unknown>;\n /** The API requires an output cap; used when a request sets none (default 8192). */\n maxOutputTokens?: number;\n /** Stream responses (default true). */\n stream?: boolean;\n /** Retries on 429, 5xx and 529 (overloaded), as the server asks. Default 4; 0 disables. */\n maxRetries?: number;\n /**\n * Calling from a browser with the user's own key: sends the header the API\n * needs to allow cross-origin requests. Never ship your own key this way.\n */\n browser?: boolean;\n /** Adapter id / label (default \"anthropic\" / \"Anthropic\"). */\n id?: string;\n label?: string;\n fetch?: FetchLike;\n}\n\ntype Block =\n | { type: \"text\"; text: string }\n | { type: \"tool_use\"; id: string; name: string; input: Record<string, unknown> }\n | { type: \"tool_result\"; tool_use_id: string; content: string }\n | { type: \"thinking\"; thinking: string; signature: string }\n | { type: \"redacted_thinking\"; data: string };\n\nexport type AnthropicMessage = { role: \"user\" | \"assistant\"; content: Block[] };\n\n/** Neutral messages → `{ system, messages }` for the Messages API. */\nexport function toAnthropicMessages(messages: readonly ChatMessage[]): { system: string; messages: AnthropicMessage[] } {\n const system: string[] = [];\n const out: AnthropicMessage[] = [];\n const push = (role: AnthropicMessage[\"role\"], blocks: Block[]) => {\n if (!blocks.length) return;\n const last = out[out.length - 1];\n // The API wants user/assistant turns to alternate: fold same-role neighbours together.\n if (last && last.role === role) last.content.push(...blocks);\n else out.push({ role, content: blocks });\n };\n for (const m of messages) {\n if (m.role === \"system\") system.push(m.content);\n else if (m.role === \"user\") push(\"user\", m.content.trim() ? [{ type: \"text\", text: m.content }] : []);\n else if (m.role === \"tool\") push(\"user\", [{ type: \"tool_result\", tool_use_id: m.toolCallId, content: m.content }]);\n else {\n const thinking = (m.toolCalls?.[0]?.meta?.anthropicThinking as Block[] | undefined) ?? [];\n push(\"assistant\", [\n ...thinking,\n ...(m.content.trim() ? [{ type: \"text\" as const, text: m.content }] : []),\n ...(m.toolCalls ?? []).map((c): Block => ({ type: \"tool_use\", id: c.id, name: c.name, input: c.arguments })),\n ]);\n }\n }\n return { system: system.join(\"\\n\\n\"), messages: out };\n}\n\nconst FINISH: Record<string, ChatResponse[\"finish\"]> = {\n end_turn: \"stop\",\n stop_sequence: \"stop\",\n tool_use: \"tool_calls\",\n max_tokens: \"length\",\n model_context_window_exceeded: \"length\",\n refusal: \"content_filter\",\n};\n\ninterface Usage {\n input_tokens?: number;\n output_tokens?: number;\n cache_creation_input_tokens?: number | null;\n cache_read_input_tokens?: number | null;\n}\n\nconst usageOf = (u: Usage) => {\n const input = (u.input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0) + (u.cache_read_input_tokens ?? 0);\n return {\n ...(u.input_tokens !== undefined ? { inputTokens: input } : {}),\n ...(u.output_tokens !== undefined ? { outputTokens: u.output_tokens } : {}),\n };\n};\n\n/** Content blocks → the neutral response (thinking blocks go on the first tool call). */\nfunction fromBlocks(blocks: Block[], stopReason: string | undefined, model: string | undefined, usage: Usage | undefined): ChatResponse {\n const thinking = blocks.filter((b) => b.type === \"thinking\" || b.type === \"redacted_thinking\");\n const toolCalls: ToolCall[] = blocks\n .filter((b): b is Extract<Block, { type: \"tool_use\" }> => b.type === \"tool_use\")\n .map((b, i) => ({ id: b.id, name: b.name, arguments: b.input ?? {}, ...(i === 0 && thinking.length ? { meta: { anthropicThinking: thinking } } : {}) }));\n const out: ChatResponse = {\n content: blocks.map((b) => (b.type === \"text\" ? b.text : \"\")).join(\"\"),\n toolCalls,\n finish: FINISH[stopReason ?? \"\"] ?? \"other\",\n };\n if (model) out.model = model;\n if (usage) out.usage = usageOf(usage);\n return out;\n}\n\nexport function anthropicChatModel(options: AnthropicChatModelOptions): ChatModel {\n const base = trimSlash(options.baseUrl ?? \"https://api.anthropic.com\");\n const id = options.id ?? \"anthropic\";\n const doFetch = options.fetch ?? defaultFetch();\n const stream = options.stream ?? true;\n const models = modelList(options.model, options.models);\n\n const headers = (): Record<string, string> => {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\", \"anthropic-version\": options.version ?? \"2023-06-01\", ...options.headers };\n if (options.apiKey) h[\"x-api-key\"] = options.apiKey;\n if (options.betas?.length) h[\"anthropic-beta\"] = options.betas.join(\",\");\n if (options.browser) h[\"anthropic-dangerous-direct-browser-access\"] = \"true\";\n return h;\n };\n\n return defineChatModel({\n id,\n label: options.label ?? \"Anthropic\",\n models,\n async listModels(opts = {}) {\n const json = (await getJson(id, doFetch, `${base}/v1/models?limit=1000`, headers(), opts.signal)) as { data?: { id: string; display_name?: string }[] };\n return (json.data ?? []).map((m) => ({ id: m.id, ...(m.display_name ? { label: m.display_name } : {}) }));\n },\n async complete(request: ChatRequest, opts = {}): Promise<ChatResponse> {\n const { system, messages } = toAnthropicMessages(request.messages);\n const body: Record<string, unknown> = {\n model: request.model ?? options.model,\n max_tokens: request.maxOutputTokens ?? options.maxOutputTokens ?? 8192,\n messages,\n ...(system ? { system } : {}),\n ...(request.tools?.length ? { tools: request.tools.map((t) => ({ name: t.name, description: t.description, input_schema: t.inputSchema })) } : {}),\n ...(stream ? { stream: true } : {}),\n ...options.params,\n ...request.params,\n };\n const res = await sendWithRetry(\n id,\n doFetch,\n `${base}/v1/messages`,\n { method: \"POST\", headers: headers(), body: JSON.stringify(body) },\n { ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}), ...(opts.signal ? { signal: opts.signal } : {}) },\n );\n if (!stream || !isEventStream(res)) {\n const json = (await res.json()) as { content?: Block[]; stop_reason?: string; model?: string; usage?: Usage };\n const out = fromBlocks(json.content ?? [], json.stop_reason, json.model, json.usage);\n if (out.content) opts.onText?.(out.content);\n return out;\n }\n return readStream(id, res.body!, opts.onText);\n },\n });\n}\n\ninterface StreamEvent {\n type: string;\n index?: number;\n message?: { model?: string; usage?: Usage };\n content_block?: { type: string; id?: string; name?: string; text?: string; thinking?: string; signature?: string; data?: string };\n delta?: { type?: string; text?: string; partial_json?: string; thinking?: string; signature?: string; stop_reason?: string };\n usage?: Usage;\n error?: { message?: string; type?: string };\n}\n\n/** Message stream events → one response; text deltas go to `onText`, tool input JSON is joined per block. */\nasync function readStream(id: string, body: ReadableStream<Uint8Array>, onText?: (delta: string) => void): Promise<ChatResponse> {\n const blocks = new Map<number, { type: string; id?: string; name?: string; text: string; json: string; signature: string; data?: string }>();\n let model: string | undefined;\n let stopReason: string | undefined;\n const usage: Usage = {};\n let failure: string | undefined;\n\n await readSse(body, (data) => {\n let event: StreamEvent;\n try {\n event = JSON.parse(data) as StreamEvent;\n } catch {\n return;\n }\n switch (event.type) {\n case \"message_start\":\n if (event.message?.model) model = event.message.model;\n Object.assign(usage, event.message?.usage ?? {});\n break;\n case \"content_block_start\": {\n const b = event.content_block!;\n blocks.set(event.index ?? blocks.size, {\n type: b.type,\n ...(b.id ? { id: b.id } : {}),\n ...(b.name ? { name: b.name } : {}),\n text: b.text ?? b.thinking ?? \"\",\n json: \"\",\n signature: b.signature ?? \"\",\n ...(b.data ? { data: b.data } : {}),\n });\n if (b.type === \"text\" && b.text) onText?.(b.text);\n break;\n }\n case \"content_block_delta\": {\n const block = blocks.get(event.index ?? 0);\n const d = event.delta ?? {};\n if (!block) break;\n if (d.type === \"text_delta\" && d.text) {\n block.text += d.text;\n onText?.(d.text);\n } else if (d.type === \"input_json_delta\" && d.partial_json) block.json += d.partial_json;\n else if (d.type === \"thinking_delta\" && d.thinking) block.text += d.thinking;\n else if (d.type === \"signature_delta\" && d.signature) block.signature += d.signature;\n break;\n }\n case \"message_delta\":\n if (event.delta?.stop_reason) stopReason = event.delta.stop_reason;\n Object.assign(usage, Object.fromEntries(Object.entries(event.usage ?? {}).filter(([, v]) => v !== null && v !== undefined)));\n break;\n case \"error\":\n failure = event.error?.message ?? event.error?.type ?? \"stream error\";\n break;\n }\n });\n if (failure) throw new ChatModelError(id, failure);\n\n const ordered = [...blocks.entries()].sort(([a], [b]) => a - b).map(([, b]) => b);\n const out: Block[] = ordered.flatMap((b): Block[] => {\n if (b.type === \"text\") return [{ type: \"text\", text: b.text }];\n if (b.type === \"tool_use\") return [{ type: \"tool_use\", id: b.id ?? \"\", name: b.name ?? \"\", input: parseToolArguments(b.json) }];\n if (b.type === \"thinking\") return [{ type: \"thinking\", thinking: b.text, signature: b.signature }];\n if (b.type === \"redacted_thinking\") return [{ type: \"redacted_thinking\", data: b.data ?? \"\" }];\n return [];\n });\n return fromBlocks(out, stopReason, model, Object.keys(usage).length ? usage : undefined);\n}\n","/**\n * Google Gemini adapter, over the Gemini API's `generateContent` with\n * function calling.\n *\n * Tools are sent as full JSON Schema (`parametersJsonSchema`), so the same\n * schemas the other adapters use work unchanged. Gemini's thought signatures\n * (required when thinking models call tools) ride on each tool call's `meta`\n * and are sent back exactly as received.\n */\nimport {\n defaultFetch,\n defineChatModel,\n type ChatMessage,\n type ChatModel,\n type ChatRequest,\n type ChatResponse,\n type FetchLike,\n type ToolCall,\n} from \"./types.js\";\nimport { getJson, isEventStream, modelList, readSse, sendWithRetry, trimSlash } from \"./wire.js\";\n\nexport interface GeminiChatModelOptions {\n /** Model id, e.g. \"gemini-3.8-flash\". Required: model names change faster than this package. */\n model: string;\n /** Other models the app may pick per request (`ChatRequest.model`). */\n models?: { id: string; label?: string }[];\n /** Gemini API key. Keep it server-side (see `createChatHandler`) unless it's the user's own key in their own browser. */\n apiKey?: string | undefined;\n /** Default https://generativelanguage.googleapis.com/v1beta. */\n baseUrl?: string;\n headers?: Record<string, string>;\n /** Default request fields merged into every call; `generationConfig` is merged key by key (e.g. `{ generationConfig: { temperature: 0.2 } }`). */\n params?: Record<string, unknown>;\n /** Stream responses (default true). */\n stream?: boolean;\n /** Retries on 429 and 5xx, as the server asks. Default 4; 0 disables. */\n maxRetries?: number;\n /** Adapter id / label (default \"gemini\" / \"Google Gemini\"). */\n id?: string;\n label?: string;\n fetch?: FetchLike;\n}\n\ntype Part = {\n text?: string;\n thought?: boolean;\n thoughtSignature?: string;\n functionCall?: { id?: string; name: string; args?: Record<string, unknown> };\n functionResponse?: { id?: string; name: string; response: Record<string, unknown> };\n};\nexport type GeminiContent = { role: \"user\" | \"model\"; parts: Part[] };\n\n/** Gemini's documented value for replaying a tool call it didn't sign (e.g. one another model made). */\nconst UNSIGNED = \"skip_thought_signature_validator\";\n\ninterface GeminiMeta {\n /** The call id Gemini assigned, when it assigned one. */\n id?: string;\n signature?: string;\n}\n\nconst metaOf = (call: ToolCall): GeminiMeta => (call.meta?.gemini as GeminiMeta | undefined) ?? {};\n\n/** A tool result as the object `functionResponse.response` must be. */\nfunction responseObject(content: string): Record<string, unknown> {\n try {\n const value = JSON.parse(content) as unknown;\n if (value && typeof value === \"object\" && !Array.isArray(value)) return value as Record<string, unknown>;\n return { result: value };\n } catch {\n return { result: content };\n }\n}\n\n/** Neutral messages → `{ systemInstruction, contents }` for `generateContent`. */\nexport function toGeminiContents(messages: readonly ChatMessage[]): { system: string; contents: GeminiContent[] } {\n const system: string[] = [];\n const contents: GeminiContent[] = [];\n const callIds = new Map<string, string | undefined>(); // our tool-call id → Gemini's id (if it gave one)\n const push = (role: GeminiContent[\"role\"], parts: Part[]) => {\n if (!parts.length) return;\n const last = contents[contents.length - 1];\n if (last && last.role === role) last.parts.push(...parts);\n else contents.push({ role, parts });\n };\n for (const m of messages) {\n if (m.role === \"system\") system.push(m.content);\n else if (m.role === \"user\") push(\"user\", m.content ? [{ text: m.content }] : []);\n else if (m.role === \"tool\") {\n const id = callIds.get(m.toolCallId);\n push(\"user\", [{ functionResponse: { ...(id ? { id } : {}), name: m.name, response: responseObject(m.content) } }]);\n } else {\n const calls = m.toolCalls ?? [];\n const signed = calls.some((c) => metaOf(c).signature);\n push(\"model\", [\n ...(m.content ? [{ text: m.content }] : []),\n ...calls.map((c, i): Part => {\n const meta = metaOf(c);\n callIds.set(c.id, meta.id);\n const signature = meta.signature ?? (i === 0 && !signed ? UNSIGNED : undefined);\n return { functionCall: { ...(meta.id ? { id: meta.id } : {}), name: c.name, args: c.arguments }, ...(signature ? { thoughtSignature: signature } : {}) };\n }),\n ]);\n }\n }\n return { system: system.join(\"\\n\\n\"), contents };\n}\n\nconst FINISH: Record<string, ChatResponse[\"finish\"]> = {\n STOP: \"stop\",\n MAX_TOKENS: \"length\",\n SAFETY: \"content_filter\",\n RECITATION: \"content_filter\",\n BLOCKLIST: \"content_filter\",\n PROHIBITED_CONTENT: \"content_filter\",\n SPII: \"content_filter\",\n IMAGE_SAFETY: \"content_filter\",\n};\n\ninterface ResponseJson {\n candidates?: { content?: { parts?: Part[] }; finishReason?: string }[];\n promptFeedback?: { blockReason?: string };\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number; thoughtsTokenCount?: number };\n modelVersion?: string;\n}\n\n/** Collects parts across one response or many stream chunks. */\nfunction collector(onText?: (delta: string) => void) {\n let content = \"\";\n let finishReason: string | undefined;\n let blocked = false;\n let model: string | undefined;\n let usage: ChatResponse[\"usage\"];\n const toolCalls: ToolCall[] = [];\n const batch = Math.random().toString(36).slice(2, 10);\n return {\n add(json: ResponseJson) {\n if (json.modelVersion) model = json.modelVersion;\n if (json.promptFeedback?.blockReason) blocked = true;\n const u = json.usageMetadata;\n if (u) {\n usage = {\n ...(u.promptTokenCount !== undefined ? { inputTokens: u.promptTokenCount } : {}),\n ...(u.candidatesTokenCount !== undefined || u.thoughtsTokenCount !== undefined ? { outputTokens: (u.candidatesTokenCount ?? 0) + (u.thoughtsTokenCount ?? 0) } : {}),\n };\n }\n const candidate = json.candidates?.[0];\n if (candidate?.finishReason) finishReason = candidate.finishReason;\n for (const part of candidate?.content?.parts ?? []) {\n if (part.functionCall) {\n const gemini: GeminiMeta = { ...(part.functionCall.id ? { id: part.functionCall.id } : {}), ...(part.thoughtSignature ? { signature: part.thoughtSignature } : {}) };\n toolCalls.push({\n // Gemini often gives no id; ours must still be unique across the conversation.\n id: part.functionCall.id ?? `call_${batch}_${toolCalls.length}`,\n name: part.functionCall.name,\n arguments: part.functionCall.args ?? {},\n ...(Object.keys(gemini).length ? { meta: { gemini } } : {}),\n });\n } else if (part.text && !part.thought) {\n content += part.text;\n onText?.(part.text);\n }\n }\n },\n result(): ChatResponse {\n const finish: ChatResponse[\"finish\"] = blocked\n ? \"content_filter\"\n : toolCalls.length && (finishReason === \"STOP\" || finishReason === undefined)\n ? \"tool_calls\"\n : (FINISH[finishReason ?? \"\"] ?? \"other\");\n return { content, toolCalls, finish, ...(model ? { model } : {}), ...(usage ? { usage } : {}) };\n },\n };\n}\n\nconst bareModel = (model: string) => model.replace(/^models\\//, \"\");\n\nexport function geminiChatModel(options: GeminiChatModelOptions): ChatModel {\n const base = trimSlash(options.baseUrl ?? \"https://generativelanguage.googleapis.com/v1beta\");\n const id = options.id ?? \"gemini\";\n const doFetch = options.fetch ?? defaultFetch();\n const stream = options.stream ?? true;\n const models = modelList(bareModel(options.model), options.models?.map((m) => ({ ...m, id: bareModel(m.id) })));\n\n const headers = (): Record<string, string> => ({\n \"Content-Type\": \"application/json\",\n ...(options.apiKey ? { \"x-goog-api-key\": options.apiKey } : {}),\n ...options.headers,\n });\n\n return defineChatModel({\n id,\n label: options.label ?? \"Google Gemini\",\n models,\n async listModels(opts = {}) {\n const json = (await getJson(id, doFetch, `${base}/models?pageSize=1000`, headers(), opts.signal)) as {\n models?: { name: string; displayName?: string; supportedGenerationMethods?: string[] }[];\n };\n return (json.models ?? [])\n .filter((m) => !m.supportedGenerationMethods || m.supportedGenerationMethods.includes(\"generateContent\"))\n .map((m) => ({ id: bareModel(m.name), ...(m.displayName ? { label: m.displayName } : {}) }));\n },\n async complete(request: ChatRequest, opts = {}): Promise<ChatResponse> {\n const { system, contents } = toGeminiContents(request.messages);\n const params = { ...options.params, ...request.params };\n const generationConfig = {\n ...(request.maxOutputTokens ? { maxOutputTokens: request.maxOutputTokens } : {}),\n ...(options.params?.generationConfig as object | undefined),\n ...(request.params?.generationConfig as object | undefined),\n };\n const body: Record<string, unknown> = {\n ...params,\n contents,\n ...(system ? { systemInstruction: { parts: [{ text: system }] } } : {}),\n ...(request.tools?.length\n ? { tools: [{ functionDeclarations: request.tools.map((t) => ({ name: t.name, description: t.description, parametersJsonSchema: t.inputSchema })) }] }\n : {}),\n ...(Object.keys(generationConfig).length ? { generationConfig } : {}),\n };\n const model = bareModel(request.model ?? options.model);\n const url = `${base}/models/${encodeURIComponent(model)}:${stream ? \"streamGenerateContent?alt=sse\" : \"generateContent\"}`;\n const res = await sendWithRetry(\n id,\n doFetch,\n url,\n { method: \"POST\", headers: headers(), body: JSON.stringify(body) },\n { ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}), ...(opts.signal ? { signal: opts.signal } : {}) },\n );\n const collect = collector(opts.onText);\n if (!stream || !isEventStream(res)) collect.add((await res.json()) as ResponseJson);\n else {\n await readSse(res.body!, (data) => {\n try {\n collect.add(JSON.parse(data) as ResponseJson);\n } catch {\n /* keep-alive or partial line */\n }\n });\n }\n const out = collect.result();\n out.model ??= model;\n return out;\n },\n });\n}\n","/**\n * Every model provider the assistant can talk to, behind one factory.\n *\n * Three wire formats cover them all: OpenAI Chat Completions (OpenAI and the\n * many servers that copy it: OpenRouter, Groq, Mistral, DeepSeek, xAI,\n * Together, Ollama, LM Studio, your own), Anthropic Messages and Google\n * Gemini. `createChatModel({ provider, apiKey, model })` picks the adapter;\n * `chatModelsFromEnv` builds one for each provider whose key is set;\n * `routedChatModel` serves several behind one model, addressed as\n * \"provider/model\".\n */\nimport { anthropicChatModel } from \"./anthropic.js\";\nimport { geminiChatModel } from \"./gemini.js\";\nimport { openAIChatModel } from \"./openai.js\";\nimport { ChatModelError, defineChatModel, type ChatModel, type FetchLike, type ModelEntry } from \"./types.js\";\n\nexport type ProviderApi = \"openai\" | \"anthropic\" | \"gemini\";\n\nexport interface AiProviderInfo {\n /** Id used in configs, env names and \"provider/model\" references. */\n id: string;\n label: string;\n /** Which wire format it speaks. */\n api: ProviderApi;\n /** API root; `openai-compatible` has none (you give it). */\n baseUrl?: string;\n /** Whether calls need an API key (local servers don't). */\n needsKey: boolean;\n /** Runs on the user's machine (Ollama, LM Studio): reachable from that machine only. */\n local?: boolean;\n /** Where a user creates a key. */\n keyUrl?: string;\n /** Env var prefix: `{PREFIX}_API_KEY`, `{PREFIX}_MODEL`, `{PREFIX}_BASE_URL`, `{PREFIX}_MODELS`. */\n env: string;\n /** Used when no model is named. Providers without one need a model picked (env or UI). */\n defaultModel?: string;\n /** A few good picks to show before the live list loads. */\n models?: ModelEntry[];\n /** Accepts calls straight from a browser (CORS) with the user's own key. */\n browser?: boolean;\n /** OpenAI-format servers: the output-cap field and whether `stream_options` is accepted. */\n maxTokensField?: \"max_completion_tokens\" | \"max_tokens\";\n streamUsage?: boolean;\n}\n\n/**\n * The built-in provider catalog. Model ids are suggestions as of release; the\n * live list comes from each provider (`ChatModel.listModels`).\n */\nexport const AI_PROVIDERS: readonly AiProviderInfo[] = [\n {\n id: \"openai\",\n label: \"OpenAI\",\n api: \"openai\",\n baseUrl: \"https://api.openai.com/v1\",\n needsKey: true,\n keyUrl: \"https://platform.openai.com/api-keys\",\n env: \"OPENAI\",\n defaultModel: \"gpt-5.4-mini\",\n models: [{ id: \"gpt-5.4-mini\" }, { id: \"gpt-6-luna\" }, { id: \"gpt-6.1-sol\" }],\n browser: true,\n },\n {\n id: \"anthropic\",\n label: \"Anthropic\",\n api: \"anthropic\",\n baseUrl: \"https://api.anthropic.com\",\n needsKey: true,\n keyUrl: \"https://console.anthropic.com/settings/keys\",\n env: \"ANTHROPIC\",\n defaultModel: \"claude-sonnet-5-5\",\n models: [\n { id: \"claude-sonnet-5-5\", label: \"Claude Sonnet 5.5\" },\n { id: \"claude-haiku-5-5\", label: \"Claude Haiku 5.5\" },\n { id: \"claude-opus-5-5\", label: \"Claude Opus 5.5\" },\n ],\n browser: true,\n },\n {\n id: \"gemini\",\n label: \"Google Gemini\",\n api: \"gemini\",\n baseUrl: \"https://generativelanguage.googleapis.com/v1beta\",\n needsKey: true,\n keyUrl: \"https://aistudio.google.com/apikey\",\n env: \"GEMINI\",\n defaultModel: \"gemini-3.8-flash\",\n models: [\n { id: \"gemini-3.8-flash\", label: \"Gemini 3.8 Flash\" },\n { id: \"gemini-3.5-flash-lite\", label: \"Gemini 3.5 Flash-Lite\" },\n { id: \"gemini-3.1-pro-preview\", label: \"Gemini 3.1 Pro (preview)\" },\n ],\n browser: true,\n },\n {\n id: \"openrouter\",\n label: \"OpenRouter\",\n api: \"openai\",\n baseUrl: \"https://openrouter.ai/api/v1\",\n needsKey: true,\n keyUrl: \"https://openrouter.ai/keys\",\n env: \"OPENROUTER\",\n defaultModel: \"openrouter/auto\",\n models: [{ id: \"openrouter/auto\", label: \"Auto (OpenRouter picks)\" }],\n browser: true,\n maxTokensField: \"max_tokens\",\n },\n { id: \"groq\", label: \"Groq\", api: \"openai\", baseUrl: \"https://api.groq.com/openai/v1\", needsKey: true, keyUrl: \"https://console.groq.com/keys\", env: \"GROQ\", maxTokensField: \"max_tokens\" },\n {\n id: \"mistral\",\n label: \"Mistral\",\n api: \"openai\",\n baseUrl: \"https://api.mistral.ai/v1\",\n needsKey: true,\n keyUrl: \"https://console.mistral.ai/api-keys\",\n env: \"MISTRAL\",\n defaultModel: \"mistral-medium-latest\",\n maxTokensField: \"max_tokens\",\n streamUsage: false,\n },\n {\n id: \"deepseek\",\n label: \"DeepSeek\",\n api: \"openai\",\n baseUrl: \"https://api.deepseek.com/v1\",\n needsKey: true,\n keyUrl: \"https://platform.deepseek.com/api_keys\",\n env: \"DEEPSEEK\",\n defaultModel: \"deepseek-chat\",\n maxTokensField: \"max_tokens\",\n },\n { id: \"xai\", label: \"xAI\", api: \"openai\", baseUrl: \"https://api.x.ai/v1\", needsKey: true, keyUrl: \"https://console.x.ai\", env: \"XAI\", maxTokensField: \"max_tokens\" },\n {\n id: \"together\",\n label: \"Together AI\",\n api: \"openai\",\n baseUrl: \"https://api.together.xyz/v1\",\n needsKey: true,\n keyUrl: \"https://api.together.ai/settings/api-keys\",\n env: \"TOGETHER\",\n maxTokensField: \"max_tokens\",\n },\n { id: \"ollama\", label: \"Ollama (local)\", api: \"openai\", baseUrl: \"http://localhost:11434/v1\", needsKey: false, local: true, env: \"OLLAMA\", maxTokensField: \"max_tokens\" },\n { id: \"lmstudio\", label: \"LM Studio (local)\", api: \"openai\", baseUrl: \"http://localhost:1234/v1\", needsKey: false, local: true, env: \"LMSTUDIO\", maxTokensField: \"max_tokens\" },\n { id: \"openai-compatible\", label: \"OpenAI-compatible\", api: \"openai\", needsKey: false, env: \"OPENAI_COMPATIBLE\", maxTokensField: \"max_tokens\" },\n];\n\n/** A provider from the catalog, or undefined. */\nexport function aiProvider(id: string): AiProviderInfo | undefined {\n return AI_PROVIDERS.find((p) => p.id === id);\n}\n\nexport interface CreateChatModelOptions {\n /** A catalog id (`AI_PROVIDERS`): \"openai\", \"anthropic\", \"gemini\", \"openrouter\", \"ollama\", \"openai-compatible\", … */\n provider: string;\n apiKey?: string | undefined;\n /** Model id (default: the provider's `defaultModel`; required for providers without one). */\n model?: string | undefined;\n /** Other models to offer (default: the catalog's suggestions). */\n models?: ModelEntry[];\n /** Override the API root (required for \"openai-compatible\"). */\n baseUrl?: string | undefined;\n headers?: Record<string, string>;\n /** Default request fields for every call (vendor-specific). */\n params?: Record<string, unknown>;\n stream?: boolean;\n maxRetries?: number;\n /** Calling from the browser with the user's own key (sets what the vendor needs for CORS). */\n browser?: boolean;\n /** Adapter id / label (default: the provider's). */\n id?: string;\n label?: string;\n fetch?: FetchLike;\n}\n\n/** One `ChatModel` for any provider in the catalog. */\nexport function createChatModel(options: CreateChatModelOptions): ChatModel {\n const info = aiProvider(options.provider);\n if (!info) throw new Error(`Unknown AI provider \"${options.provider}\". Known: ${AI_PROVIDERS.map((p) => p.id).join(\", \")}`);\n const model = options.model || info.defaultModel;\n if (!model) throw new ChatModelError(info.id, `pick a model (${info.label} has no default; set ${info.env}_MODEL or choose one)`, 400);\n if (info.needsKey && !options.apiKey) throw new ChatModelError(info.id, `needs an API key${info.keyUrl ? ` (create one at ${info.keyUrl})` : \"\"}`, 401);\n const baseUrl = options.baseUrl || info.baseUrl;\n if (!baseUrl) throw new ChatModelError(info.id, \"needs a base URL (the server's /v1 address)\", 400);\n\n const common = {\n model,\n models: options.models ?? info.models ?? [],\n baseUrl,\n id: options.id ?? info.id,\n label: options.label ?? info.label,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n ...(options.headers ? { headers: options.headers } : {}),\n ...(options.params ? { params: options.params } : {}),\n ...(options.stream !== undefined ? { stream: options.stream } : {}),\n ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),\n ...(options.fetch ? { fetch: options.fetch } : {}),\n };\n switch (info.api) {\n case \"anthropic\":\n return anthropicChatModel({ ...common, ...(options.browser ? { browser: true } : {}) });\n case \"gemini\":\n return geminiChatModel(common);\n case \"openai\":\n return openAIChatModel({\n ...common,\n ...(info.maxTokensField ? { maxTokensField: info.maxTokensField } : {}),\n ...(info.streamUsage !== undefined ? { streamUsage: info.streamUsage } : {}),\n });\n }\n}\n\nexport interface ChatModelsFromEnvOptions {\n /** Only these providers (default: all). */\n providers?: string[];\n /** Told about providers that have a key but couldn't be set up (e.g. no model). */\n onSkip?: (provider: string, reason: string) => void;\n fetch?: FetchLike;\n}\n\n/**\n * A model for every provider configured in `env` (`process.env`, Vite's\n * `loadEnv`, a Worker's bindings):\n *\n * {PREFIX}_API_KEY enables a hosted provider (GEMINI also reads GOOGLE_API_KEY)\n * {PREFIX}_MODEL its default model (required where the catalog has none)\n * {PREFIX}_MODELS more models to offer, comma-separated\n * {PREFIX}_BASE_URL another API root (a proxy, a gateway, a regional endpoint)\n *\n * Local servers (OLLAMA, LMSTUDIO) are enabled by their _MODEL or _BASE_URL.\n * OPENAI_BASE_URL alone keeps its old meaning: an OpenAI-compatible server\n * (label OPENAI_LABEL), key optional. Order follows the catalog, so the\n * first entry makes a sensible default.\n */\nexport function chatModelsFromEnv(env: Record<string, string | undefined>, options: ChatModelsFromEnvOptions = {}): ChatModel[] {\n const out: ChatModel[] = [];\n const wanted = options.providers ? new Set(options.providers) : null;\n for (const info of AI_PROVIDERS) {\n if (wanted && !wanted.has(info.id)) continue;\n const p = info.env;\n let apiKey = env[`${p}_API_KEY`] || (info.id === \"gemini\" ? env.GOOGLE_API_KEY : undefined);\n let baseUrl = env[`${p}_BASE_URL`];\n let label: string | undefined;\n if (info.id === \"openai\" && env.OPENAI_BASE_URL) continue; // served as openai-compatible below\n if (info.id === \"openai-compatible\" && !baseUrl && env.OPENAI_BASE_URL) {\n baseUrl = env.OPENAI_BASE_URL;\n apiKey ||= env.OPENAI_API_KEY;\n label = env.OPENAI_LABEL || undefined;\n }\n const model = env[`${p}_MODEL`] || (info.id === \"openai-compatible\" ? env.OPENAI_MODEL : undefined);\n const enabled = info.needsKey ? !!apiKey : info.local ? !!(model || baseUrl) : !!baseUrl;\n if (!enabled) continue;\n const models = (env[`${p}_MODELS`] || (info.id === \"openai-compatible\" && env.OPENAI_BASE_URL ? env.OPENAI_MODELS : \"\") || \"\")\n .split(\",\")\n .map((m) => m.trim())\n .filter(Boolean)\n .map((m) => ({ id: m }));\n try {\n out.push(\n createChatModel({\n provider: info.id,\n ...(apiKey ? { apiKey } : {}),\n ...(model ? { model } : {}),\n ...(models.length ? { models } : {}),\n ...(baseUrl ? { baseUrl } : {}),\n ...(label ? { label } : {}),\n ...(options.fetch ? { fetch: options.fetch } : {}),\n }),\n );\n } catch (err) {\n options.onSkip?.(info.id, (err as Error).message);\n }\n }\n return out;\n}\n\n/** \"anthropic/claude-sonnet-5-5\" → { provider: \"anthropic\", model: \"claude-sonnet-5-5\" } when the prefix is a known id. */\nexport function splitModelRef(ref: string, providerIds: Iterable<string>): { provider?: string; model: string } {\n const slash = ref.indexOf(\"/\");\n if (slash > 0) {\n const provider = ref.slice(0, slash);\n for (const id of providerIds) if (id === provider) return { provider, model: ref.slice(slash + 1) };\n }\n return { model: ref };\n}\n\nexport interface RoutedChatModelOptions {\n id?: string;\n label?: string;\n /** Adapter id used when a request names no provider (default: the first). */\n default?: string;\n}\n\n/**\n * Several providers as one `ChatModel`. Its models are \"provider/model\"\n * (`anthropic/claude-sonnet-5-5`, `openrouter/meta-llama/…`); a request's\n * `model` picks the adapter and the model. A bare model id goes to the\n * adapter that lists it, else to the default adapter; no model → the default\n * adapter's default model.\n */\nexport function routedChatModel(models: readonly ChatModel[], options: RoutedChatModelOptions = {}): ChatModel {\n if (!models.length) throw new Error(\"routedChatModel needs at least one model\");\n const byId = new Map(models.map((m) => [m.id, m]));\n if (byId.size !== models.length) throw new Error(\"routedChatModel: adapter ids must be unique\");\n const fallback = (options.default && byId.get(options.default)) || models[0]!;\n const ordered = [fallback, ...models.filter((m) => m !== fallback)];\n const prefixed = (m: ChatModel, list: ModelEntry[]) => list.map((e) => ({ id: `${m.id}/${e.id}`, label: `${m.label} · ${e.label ?? e.id}` }));\n\n const resolve = (ref: string | undefined): { adapter: ChatModel; model?: string } => {\n if (!ref) return { adapter: fallback };\n const { provider, model } = splitModelRef(ref, byId.keys());\n if (provider) return { adapter: byId.get(provider)!, model };\n const lister = ordered.find((m) => m.models?.some((e) => e.id === ref));\n return { adapter: lister ?? fallback, model: ref };\n };\n\n return defineChatModel({\n id: options.id ?? \"router\",\n label: options.label ?? (models.length === 1 ? fallback.label : \"AI models\"),\n models: ordered.flatMap((m) => prefixed(m, m.models ?? [])),\n providers: ordered.map((m) => ({ id: m.id, label: m.label })),\n async complete(request, opts) {\n const { adapter, model } = resolve(request.model);\n const { model: _drop, ...rest } = request;\n return adapter.complete(model ? { ...rest, model } : rest, opts);\n },\n async listModels(opts) {\n const lists = await Promise.allSettled(ordered.map(async (m) => prefixed(m, m.listModels ? await m.listModels(opts) : (m.models ?? []))));\n return lists.flatMap((r, i) => (r.status === \"fulfilled\" ? r.value : prefixed(ordered[i]!, ordered[i]!.models ?? [])));\n },\n });\n}\n","/**\n * Keys stay on the server: run the real model adapter in your backend behind\n * `createChatHandler`, and give the browser `remoteChatModel(endpoint)` — a\n * proxy with the same `ChatModel` shape. The agent loop and the tools run in\n * the browser, next to the project; only model calls cross the network.\n *\n * GET {base}/ → { id, label, models, providers?, userKeys? }\n * GET {base}/models → { models } (live from the vendor when it can list them)\n * POST {base}/chat { request: ChatRequest } →\n * application/x-ndjson, one JSON object per line:\n * { \"type\": \"text\", \"delta\": \"…\" } (as it streams)\n * { \"type\": \"done\", \"response\": ChatResponse }\n * { \"type\": \"error\", \"error\": \"…\", \"status\": 401 }\n * errors before streaming → { error } with 400 / 401 / 403 / 404 / 413, or the vendor's status\n *\n * Bring your own key (`userKeys`): a request may carry the user's own\n * provider and key in headers (`x-ai-provider`, `x-ai-key`, optionally\n * `x-ai-base-url`). The handler builds a model for that one request and\n * forgets the key — it's never stored or logged. Use it for plans where\n * customers pay their AI vendor directly.\n *\n * Fetch-API handler (`Request` → `Response`): mounts in Node 18+, edge\n * runtimes, Next, Hono, Express (via an adapter).\n */\nimport { AI_PROVIDERS, aiProvider, createChatModel, splitModelRef, type AiProviderInfo, type CreateChatModelOptions } from \"./providers.js\";\nimport { ChatModelError, defaultFetch, type ChatModel, type ChatRequest, type ChatResponse, type FetchLike, type ModelEntry } from \"./types.js\";\n\n/** Header names a request uses to bring the user's own key. */\nexport const USER_KEY_HEADERS = { provider: \"x-ai-provider\", key: \"x-ai-key\", baseUrl: \"x-ai-base-url\" } as const;\n\n/** The user's own provider settings, as the browser sends them. */\nexport interface UserCredentials {\n provider: string;\n apiKey?: string;\n /** Only honored when the server allows it (`userKeys.allowBaseUrl`). */\n baseUrl?: string;\n}\n\nexport interface UserKeyOptions {\n /** Providers users may bring a key for (default: every hosted provider in the catalog). */\n providers?: string[];\n /**\n * Let users send their own API root (OpenAI-compatible servers, gateways).\n * Off by default: your server would call whatever URL a user sends.\n */\n allowBaseUrl?: boolean;\n /** Refuse requests without the user's own key, even when the server has a model. */\n required?: boolean;\n /** Build the model for a user's key (default `createChatModel`): add headers, pin params, wrap with limits. */\n create?: (options: CreateChatModelOptions, request: Request) => ChatModel;\n fetch?: FetchLike;\n}\n\nexport interface ChatHandlerOptions {\n /** Path prefix the handler is mounted at, e.g. \"/api/assistant\". */\n basePath?: string;\n /** Reject request bodies larger than this (default 2 MB). */\n maxBodyBytes?: number;\n /** Return a Response to refuse a request (auth, rate limits, plan checks); undefined to allow. */\n authorize?: (request: Request) => Promise<Response | undefined> | Response | undefined;\n /** Adjust each request server-side (pin a model, cap tokens, add instructions). */\n prepare?: (request: ChatRequest) => ChatRequest;\n /** Accept the user's own provider key per request (see the module note). Off by default. */\n userKeys?: boolean | UserKeyOptions;\n}\n\n/** What `GET {base}/` tells the browser about bring-your-own-key. */\nexport interface UserKeyInfo {\n providers: Pick<AiProviderInfo, \"id\" | \"label\" | \"needsKey\" | \"keyUrl\" | \"defaultModel\" | \"models\">[];\n allowBaseUrl: boolean;\n required: boolean;\n}\n\nconst hostedProviders = () => AI_PROVIDERS.filter((p) => !p.local && p.baseUrl).map((p) => p.id);\n\n/**\n * @param model The server's own model (its keys, from env or config), or\n * `null` when every user brings their own key (`userKeys` must be on).\n */\nexport function createChatHandler(model: ChatModel | null, options: ChatHandlerOptions = {}) {\n const base = (options.basePath ?? \"\").replace(/\\/+$/, \"\");\n const maxBody = options.maxBodyBytes ?? 2_000_000;\n const byok: UserKeyOptions | null = options.userKeys ? (options.userKeys === true ? {} : options.userKeys) : null;\n if (!model && !byok) throw new Error(\"createChatHandler needs a model, or userKeys so users can bring their own\");\n const allowed = new Set(byok?.providers ?? hostedProviders());\n if (byok?.allowBaseUrl) allowed.add(\"openai-compatible\");\n const userKeyInfo: UserKeyInfo | undefined = byok\n ? {\n providers: [...allowed].flatMap((id) => {\n const p = aiProvider(id);\n return p ? [{ id: p.id, label: p.label, needsKey: p.needsKey, ...(p.keyUrl ? { keyUrl: p.keyUrl } : {}), ...(p.defaultModel ? { defaultModel: p.defaultModel } : {}), ...(p.models ? { models: p.models } : {}) }] : [];\n }),\n allowBaseUrl: !!byok.allowBaseUrl,\n required: !!byok.required,\n }\n : undefined;\n\n /** The user's model for this request, null when they sent no key, or a Response refusing it. */\n const userModel = (request: Request, modelRef: string | undefined): ChatModel | Response | null => {\n if (!byok) return null;\n const provider = request.headers.get(USER_KEY_HEADERS.provider)?.trim();\n if (!provider) return null;\n if (!allowed.has(provider)) return json(403, { error: `bringing your own key isn't enabled for \"${provider}\" here` });\n const apiKey = request.headers.get(USER_KEY_HEADERS.key)?.trim() || undefined;\n const baseUrl = request.headers.get(USER_KEY_HEADERS.baseUrl)?.trim() || undefined;\n if (baseUrl && !byok.allowBaseUrl) return json(403, { error: \"custom API addresses aren't allowed here\" });\n const ref = modelRef ? splitModelRef(modelRef, [provider]) : undefined;\n const config: CreateChatModelOptions = {\n provider,\n ...(apiKey ? { apiKey } : {}),\n // Listing models needs no model; the catalog default (or a placeholder) is fine.\n model: ref?.model || aiProvider(provider)?.defaultModel || \"default\",\n ...(baseUrl ? { baseUrl } : {}),\n ...(byok.fetch ? { fetch: byok.fetch } : {}),\n };\n try {\n return byok.create ? byok.create(config, request) : createChatModel(config);\n } catch (err) {\n const status = err instanceof ChatModelError && err.status ? err.status : 400;\n return json(status, { error: (err as Error).message });\n }\n };\n\n const noModel = () => json(401, { error: \"Add your own API key to use AI here.\", needsKey: true });\n\n return async function handle(request: Request): Promise<Response | null> {\n const path = new URL(request.url).pathname;\n if (base && path !== base && !path.startsWith(`${base}/`)) return null;\n const rest = path.slice(base.length).replace(/\\/+$/, \"\");\n\n const refused = await options.authorize?.(request);\n if (refused) return refused;\n\n if (rest === \"\" && request.method === \"GET\") {\n return json(200, {\n id: model?.id ?? \"byok\",\n label: model?.label ?? \"Your API key\",\n models: model?.models ?? [],\n ...(model?.providers ? { providers: model.providers } : {}),\n ...(userKeyInfo ? { userKeys: userKeyInfo } : {}),\n ...(!model || byok?.required ? { needsKey: true } : {}),\n });\n }\n\n if (rest === \"/models\" && request.method === \"GET\") {\n const mine = userModel(request, undefined);\n if (mine instanceof Response) return mine;\n const target = mine ?? (byok?.required ? null : model);\n if (!target) return noModel();\n try {\n const models: ModelEntry[] = target.listModels ? await target.listModels({ signal: request.signal }) : (target.models ?? []);\n return json(200, { models });\n } catch (err) {\n const status = (err as { status?: number })?.status;\n return json(status && status >= 400 && status < 600 ? status : 502, { error: (err as Error)?.message ?? String(err) });\n }\n }\n\n if (rest !== \"/chat\" || request.method !== \"POST\") return json(404, { error: \"not found\" });\n\n const text = await request.text();\n if (text.length > maxBody) return json(413, { error: \"request too large\" });\n let chat: ChatRequest;\n try {\n chat = (JSON.parse(text) as { request: ChatRequest }).request;\n } catch {\n return json(400, { error: \"body must be JSON { request }\" });\n }\n if (!chat || !Array.isArray(chat.messages)) return json(400, { error: \"request.messages is required\" });\n if (options.prepare) chat = options.prepare(chat);\n\n const mine = userModel(request, chat.model);\n if (mine instanceof Response) return mine;\n const target = mine ?? (byok?.required ? null : model);\n if (!target) return noModel();\n if (mine && chat.model) chat = { ...chat, model: splitModelRef(chat.model, [request.headers.get(USER_KEY_HEADERS.provider)!.trim(), mine.id]).model };\n\n const encoder = new TextEncoder();\n const body = new ReadableStream<Uint8Array>({\n async start(controller) {\n const send = (value: unknown) => controller.enqueue(encoder.encode(`${JSON.stringify(value)}\\n`));\n try {\n const response = await target.complete(chat, { signal: request.signal, onText: (delta) => send({ type: \"text\", delta }) });\n send({ type: \"done\", response });\n } catch (err) {\n const status = (err as { status?: number })?.status;\n send({ type: \"error\", error: (err as Error)?.message ?? String(err), ...(status ? { status } : {}) });\n } finally {\n controller.close();\n }\n },\n });\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/x-ndjson\", \"cache-control\": \"no-store\" } });\n };\n}\n\nconst json = (status: number, body: unknown) => new Response(JSON.stringify(body), { status, headers: { \"content-type\": \"application/json\" } });\n\n/** What the server said about itself (`GET {base}/`). */\nexport interface RemoteModelInfo {\n id: string;\n label: string;\n models?: ModelEntry[];\n providers?: { id: string; label: string }[];\n userKeys?: UserKeyInfo;\n /** The server has no model of its own (or requires user keys): calls need the user's key. */\n needsKey?: boolean;\n}\n\nexport interface RemoteChatModelOptions {\n fetch?: FetchLike;\n headers?: Record<string, string>;\n /** Skip the GET for model info (id/label/models default to \"remote\"). */\n info?: RemoteModelInfo;\n /**\n * The user's own provider key, read on every call (so a settings change\n * applies at once). Return nothing to use the server's model.\n */\n credentials?: () => UserCredentials | null | undefined;\n}\n\n/** Headers carrying the user's own key, for any request to a `createChatHandler` server. */\nexport function userKeyHeaders(credentials: UserCredentials | null | undefined): Record<string, string> {\n if (!credentials?.provider) return {};\n return {\n [USER_KEY_HEADERS.provider]: credentials.provider,\n ...(credentials.apiKey ? { [USER_KEY_HEADERS.key]: credentials.apiKey } : {}),\n ...(credentials.baseUrl ? { [USER_KEY_HEADERS.baseUrl]: credentials.baseUrl } : {}),\n };\n}\n\n/** The model a backend serves, as a browser-side `ChatModel` (plus what the server said about itself in `info`). */\nexport async function remoteChatModel(endpoint: string, options: RemoteChatModelOptions = {}): Promise<ChatModel & { info: RemoteModelInfo }> {\n const doFetch = options.fetch ?? defaultFetch();\n const root = endpoint.replace(/\\/+$/, \"\");\n let info = options.info;\n if (!info) {\n const res = await doFetch(`${root}/`, { headers: { Accept: \"application/json\", ...options.headers } });\n if (!res.ok) throw new ChatModelError(\"remote\", `HTTP ${res.status}`, res.status);\n info = (await res.json()) as RemoteModelInfo;\n }\n const { id, label, models, providers } = info;\n const headers = (extra: Record<string, string>) => ({ ...extra, ...options.headers, ...userKeyHeaders(options.credentials?.()) });\n\n return {\n id,\n label,\n info,\n ...(models ? { models } : {}),\n ...(providers ? { providers } : {}),\n async listModels(opts = {}) {\n const res = await doFetch(`${root}/models`, { headers: headers({ Accept: \"application/json\" }), ...(opts.signal ? { signal: opts.signal } : {}) });\n const body = (await res.json().catch(() => null)) as { models?: ModelEntry[]; error?: string } | null;\n if (!res.ok) throw new ChatModelError(id, body?.error ?? `HTTP ${res.status}`, res.status);\n return body?.models ?? [];\n },\n async complete(request, opts = {}): Promise<ChatResponse> {\n const res = await doFetch(`${root}/chat`, {\n method: \"POST\",\n headers: headers({ \"Content-Type\": \"application/json\", Accept: \"application/x-ndjson\" }),\n body: JSON.stringify({ request }),\n ...(opts.signal ? { signal: opts.signal } : {}),\n });\n if (!res.ok || !res.body) {\n const err = (await res.json().catch(() => null)) as { error?: string } | null;\n throw new ChatModelError(id, err?.error ?? `HTTP ${res.status}`, res.status);\n }\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let final: ChatResponse | undefined;\n const handle = (line: string) => {\n if (!line.trim()) return;\n const event = JSON.parse(line) as { type: string; delta?: string; response?: ChatResponse; error?: string; status?: number };\n if (event.type === \"text\" && event.delta) opts.onText?.(event.delta);\n else if (event.type === \"done\") final = event.response;\n else if (event.type === \"error\") throw new ChatModelError(id, event.error ?? \"failed\", event.status);\n };\n for (;;) {\n const { done, value } = await reader.read();\n if (value) buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) >= 0) {\n handle(buffer.slice(0, nl));\n buffer = buffer.slice(nl + 1);\n }\n if (done) break;\n }\n handle(buffer);\n if (!final) throw new ChatModelError(id, \"the server closed the stream without a response\");\n return final;\n },\n };\n}\n","import type { ChatModel, ChatRequest } from \"./types.js\";\n\nexport interface RateLimitOptions {\n /** Tokens per rolling minute across every caller of this model (input + output). */\n tokensPerMinute?: number;\n /** Requests per rolling minute. */\n requestsPerMinute?: number;\n /** Token estimate for a request before it's sent (default: JSON length ÷ 4, plus room for the reply). */\n estimate?: (request: ChatRequest) => number;\n}\n\n/**\n * Wrap a model so calls wait for room under your provider's per-minute\n * limits instead of failing with 429s — for batch jobs (evals, bulk edits)\n * and for a server sharing one key. Each call reserves an estimate, which is\n * replaced by the real usage when the response reports it.\n */\nexport function rateLimitedChatModel(model: ChatModel, options: RateLimitOptions): ChatModel {\n const tpm = options.tokensPerMinute ?? Infinity;\n const rpm = options.requestsPerMinute ?? Infinity;\n const estimate = options.estimate ?? ((r: ChatRequest) => Math.ceil(JSON.stringify(r).length / 4) + (r.maxOutputTokens ?? 1000));\n const window: { at: number; tokens: number }[] = [];\n let gate: Promise<void> = Promise.resolve();\n\n const prune = (now: number) => {\n while (window.length && now - window[0]!.at >= 60_000) window.shift();\n };\n const used = () => window.reduce((n, e) => n + e.tokens, 0);\n\n /** Wait (in arrival order) until this request fits, then reserve it. */\n const reserve = (tokens: number, signal?: AbortSignal) => {\n const want = Math.min(tokens, tpm); // a single request bigger than the limit still goes, alone\n const turn = gate.then(async () => {\n for (;;) {\n if (signal?.aborted) throw signal.reason ?? new Error(\"aborted\");\n const now = Date.now();\n prune(now);\n if (window.length < rpm && used() + want <= tpm) break;\n const oldest = window[0];\n await new Promise((r) => setTimeout(r, oldest ? Math.max(50, 60_000 - (now - oldest.at)) : 50));\n }\n const entry = { at: Date.now(), tokens: want };\n window.push(entry);\n return entry;\n });\n gate = turn.then(\n () => undefined,\n () => undefined,\n );\n return turn;\n };\n\n return {\n ...model,\n async complete(request, opts = {}) {\n const entry = await reserve(estimate(request), opts.signal);\n const response = await model.complete(request, opts);\n const real = (response.usage?.inputTokens ?? 0) + (response.usage?.outputTokens ?? 0);\n if (real > 0) entry.tokens = real;\n return response;\n },\n };\n}\n","import { animationPreset, describeAnimation, describeProject, findCuts, keyframeTimeUs, readAnimation, type AnimationRecipe, type Clip, type ProjectDocument } from \"@miraiclip/core\";\n\n/**\n * The project as the model sees it: core's `describeProject`, plus what a\n * model needs to make RELATIVE edits (\"bigger\", \"louder\", \"keep the\n * entrance\") — track names, every clip's position, size and opacity, text\n * styling, volume, effects and its animation recipe.\n */\nexport function describeForAssistant(doc: ProjectDocument): string {\n const lines = [\n describeProject(doc),\n \"\",\n \"track names: \" +\n doc.trackOrder\n .map((id) => {\n const t = doc.tracks[id] as { name?: string; hidden?: boolean; muted?: boolean; solo?: boolean; locked?: boolean } | undefined;\n const flags = [t?.hidden && \"hidden\", t?.muted && \"muted\", t?.solo && \"solo\", t?.locked && \"locked\"].filter(Boolean);\n return `${id} = \"${t?.name ?? id}\"${flags.length ? ` (${flags.join(\", \")})` : \"\"}`;\n })\n .join(\", \") +\n \" (track flags muted / solo / locked / hidden: track/set-property)\",\n ];\n const cuts = findCuts(doc);\n lines.push(\n cuts.length\n ? `cuts (where one clip ends and the next starts on the same track; transitions go here): ${cuts.map((c) => `${n(c.atUs / 1e6)}s ${c.fromClipId}→${c.toClipId}${c.transition ? ` (${c.transition.kind})` : \"\"}`).join(\", \")}`\n : \"cuts: none\",\n );\n const clips = Object.values(doc.clips).sort((a, b) => a.trackId.localeCompare(b.trackId) || a.startUs - b.startUs);\n if (clips.length) {\n lines.push(\"clip details (transform x/y: 0.5 = center; scale 1 = full size; times in seconds):\");\n for (const clip of clips) lines.push(`- ${clip.id}: ${details(clip)}`);\n }\n return lines.join(\"\\n\");\n}\n\nconst n = (v: number) => Number(v.toFixed(3));\n\nfunction details(clip: Clip): string {\n const parts: string[] = [`${clip.kind} on ${clip.trackId}`, `${n(clip.startUs / 1e6)}–${n((clip.startUs + clip.durationUs) / 1e6)}s`];\n if (clip.kind !== \"audio\") {\n const t = clip.transform;\n parts.push(`x ${n(t.x)} y ${n(t.y)} scale ${n(t.scale)}${t.rotation ? ` rotation ${n(t.rotation)}°` : \"\"} opacity ${n(t.opacity)}`);\n }\n if (clip.kind === \"text\") {\n const c = clip as Clip & { fontSizePx: number; color: string; fontFamily: string; fontWeight?: number; textAlign?: string };\n parts.push(`font ${c.fontFamily} ${c.fontSizePx}px${c.fontWeight ? ` weight ${c.fontWeight}` : \"\"} color ${c.color}${c.textAlign ? ` align ${c.textAlign}` : \"\"}`);\n }\n if (clip.kind === \"caption\") {\n const c = clip as Clip & { words: { text: string }[]; style: { preset: string; color: string; highlightColor: string; backgroundColor?: string } };\n parts.push(\n `words \"${c.words.map((w) => w.text).join(\" \").slice(0, 80)}\" · style preset ${c.style.preset} color ${c.style.color} highlight ${c.style.highlightColor} box ${c.style.backgroundColor ?? \"none\"} (style.backgroundColor)`,\n );\n }\n if (clip.kind === \"html\") {\n const c = clip as Clip & { template: string; params: Record<string, unknown> };\n parts.push(`params ${JSON.stringify(c.params)} (template placeholders: ${htmlPlaceholders(c.template).join(\", \") || \"none\"})`);\n }\n if (\"volume\" in clip) {\n const c = clip as Clip & { volume: number; fadeInUs?: number; fadeOutUs?: number; trimStartUs: number };\n parts.push(`volume ${n(c.volume)}${c.fadeInUs ? ` fade-in ${n(c.fadeInUs / 1e6)}s` : \"\"}${c.fadeOutUs ? ` fade-out ${n(c.fadeOutUs / 1e6)}s` : \"\"}`);\n parts.push(`source from ${n(c.trimStartUs / 1e6)}s`);\n }\n if (clip.effects?.length) parts.push(`effects ${clip.effects.map((e) => `${e.kind}#${e.id}${e.enabled ? \"\" : \" (off)\"}`).join(\", \")}`);\n const volumeKeys = clip.animations?.volume ?? [];\n if (volumeKeys.length) parts.push(`volume keyframes ${volumeKeys.map((k) => `${n((clip.startUs + keyframeTimeUs(k, clip.durationUs)) / 1e6)}s=${n(k.value)}`).join(\", \")}`);\n const visual = Object.entries(clip.animations ?? {}).some(([prop, list]) => prop !== \"volume\" && list && list.length);\n if (visual) {\n const read = readClipAnimation(clip);\n parts.push(read.custom ? `custom keyframes (not presets): ${describeKeyframes(clip)}` : `animation ${describeAnimation(read.recipe)}`);\n }\n return parts.join(\" · \");\n}\n\n/** The `{{name}}` placeholders an html clip's template substitutes from its params. */\nexport function htmlPlaceholders(template: string): string[] {\n return [...new Set([...template.matchAll(/\\{\\{\\s*([\\w.-]+)\\s*\\}\\}/g)].map((m) => m[1]!))];\n}\n\n/**\n * core's `readAnimation`, stricter: a \"stale\" reading (In / Out plus a loop\n * whose spacing a trim broke) is only trusted when the loop's properties have\n * enough keyframes to be a loop. Two keyframes are someone's own animation,\n * and rewriting them as presets would destroy it.\n */\nexport function readClipAnimation(clip: Clip): { recipe: AnimationRecipe; custom: boolean } {\n const read = readAnimation(clip);\n if (read.custom) return { recipe: {}, custom: true };\n if (read.stale && read.recipe.loop) {\n const preset = animationPreset(read.recipe.loop.preset);\n const props = Object.keys(preset?.build(clip.transform, 1_000_000, \"linear\") ?? {}) as (keyof NonNullable<Clip[\"animations\"]>)[];\n const count = props.reduce((sum, prop) => sum + (clip.animations?.[prop]?.length ?? 0), 0);\n if (count < 4) return { recipe: {}, custom: true };\n }\n return { recipe: read.recipe, custom: false };\n}\n\n/** Visual keyframes per property, at timeline seconds: \"opacity 0.5s 0 → 1s 1; scale …\". */\nexport function describeKeyframes(clip: Clip): string {\n return Object.entries(clip.animations ?? {})\n .filter(([prop, list]) => prop !== \"volume\" && list?.length)\n .map(([prop, list]) => `${prop} ${list!.map((k) => `${n((clip.startUs + keyframeTimeUs(k, clip.durationUs)) / 1e6)}s ${n(k.value)}`).join(\" → \")}`)\n .join(\"; \");\n}\n","/**\n * Catch fields a command would silently ignore. Core's schemas strip unknown\n * keys, so `clip/move { at: … }` or `track/set-property { property, value }`\n * validate fine and change nothing — and a model then reports an edit that\n * never happened. Checking payload keys against the command's JSON Schema\n * turns those into errors the model can fix.\n */\ntype Schema = {\n type?: string;\n properties?: Record<string, Schema>;\n required?: string[];\n anyOf?: Schema[];\n oneOf?: Schema[];\n const?: unknown;\n additionalProperties?: boolean | Schema;\n};\n\n/** Object schemas a value may match (unions flattened). */\nfunction branches(schema: Schema): Schema[] {\n const alts = schema.anyOf ?? schema.oneOf;\n return alts ? alts.flatMap(branches) : [schema];\n}\n\n/** `path` entries for keys the schema doesn't declare (one level into nested objects). */\nfunction unknownIn(schema: Schema, value: Record<string, unknown>, prefix = \"\"): string[] {\n const props = schema.properties;\n if (!props || (schema.additionalProperties !== undefined && schema.additionalProperties !== false)) return [];\n const out: string[] = [];\n for (const [key, v] of Object.entries(value)) {\n const sub = props[key];\n if (!sub) out.push(prefix + key);\n else if (!prefix && v && typeof v === \"object\" && !Array.isArray(v)) {\n const objectBranch = branches(sub).find((b) => b.properties);\n if (objectBranch) out.push(...unknownIn(objectBranch, v as Record<string, unknown>, `${key}.`));\n }\n }\n return out;\n}\n\nexport interface UnknownFields {\n unknown: string[];\n /** The fields the command does take (for the error message). */\n allowed: string[];\n}\n\n/** Unknown payload fields for a command, judged against the best-matching schema branch. */\nexport function unknownFields(schema: unknown, payload: unknown): UnknownFields | null {\n if (!schema || !payload || typeof payload !== \"object\" || Array.isArray(payload)) return null;\n const value = payload as Record<string, unknown>;\n let candidates = branches(schema as Schema).filter((b) => b.properties);\n if (candidates.length === 0) return null;\n // A discriminated union: prefer the branch whose `kind` constant matches.\n const byKind = candidates.filter((b) => b.properties!.kind?.const !== undefined && b.properties!.kind.const === value.kind);\n if (byKind.length) candidates = byKind;\n let best: UnknownFields | null = null;\n for (const b of candidates) {\n const unknown = unknownIn(b, value);\n if (!best || unknown.length < best.unknown.length) best = { unknown, allowed: Object.keys(b.properties!) };\n }\n return best && best.unknown.length ? best : null;\n}\n","import {\n ANIMATION_EASINGS,\n ANIMATION_PRESETS,\n animationCommands,\n applyCommands,\n commandCatalog,\n builtinTransitionParamSchemas,\n describeAnimation,\n EFFECT_CATALOG,\n findCuts,\n fitAnimation,\n toToolDefinitions,\n tryDispatch,\n type AnimationEasing,\n type AnimationRecipe,\n type AnimationSlot,\n type Command,\n type Cut,\n type Project,\n} from \"@miraiclip/core\";\nimport { describeForAssistant, describeKeyframes, htmlPlaceholders, readClipAnimation } from \"./state.js\";\nimport { unknownFields } from \"./strict.js\";\nimport type { ToolSpec } from \"./types.js\";\n\n/** What a tool's `run` gets. `project` is the turn's working copy. */\nexport interface ToolContext {\n project: Project;\n signal?: AbortSignal;\n}\n\n/** A tool's answer. `changes` are human-readable lines for the app's \"what changed\" list. */\nexport type ToolOutput =\n | { ok: true; result?: unknown; changes?: string[] }\n | { ok: false; error: unknown };\n\nexport interface AssistantTool extends ToolSpec {\n run(input: Record<string, unknown>, ctx: ToolContext): Promise<ToolOutput> | ToolOutput;\n}\n\nexport function defineTool(tool: AssistantTool): AssistantTool {\n if (!/^[a-zA-Z0-9_-]{1,64}$/.test(tool.name)) throw new Error(`Tool name must match ^[a-zA-Z0-9_-]{1,64}$ (got \"${tool.name}\")`);\n return tool;\n}\n\n/**\n * Adopt tools that come as definitions plus one runner — e.g.\n * `@miraiclip/audio-sources`' `audioToolDefinitions` + `runAudioTool`.\n * Accepts `{ name, description, input_schema }`, OpenAI function tools or\n * Gemini function declarations.\n */\nexport function toolsFromDefinitions(\n definitions: readonly unknown[],\n run: (name: string, input: Record<string, unknown>, ctx: ToolContext) => Promise<{ ok: boolean; result?: unknown; error?: unknown }>,\n options: { changes?: (name: string, input: Record<string, unknown>, result: unknown) => string[] | undefined } = {},\n): AssistantTool[] {\n return definitions.map((d) => {\n const def = d as { name?: string; description?: string; input_schema?: Record<string, unknown>; parametersJsonSchema?: Record<string, unknown>; function?: { name: string; description?: string; parameters?: Record<string, unknown> } };\n const name = def.function?.name ?? def.name!;\n return defineTool({\n name,\n description: def.function?.description ?? def.description ?? \"\",\n inputSchema: def.function?.parameters ?? def.input_schema ?? def.parametersJsonSchema ?? { type: \"object\", properties: {} },\n async run(input, ctx) {\n const out = await run(name, input, ctx);\n if (!out.ok) return { ok: false, error: out.error ?? \"failed\" };\n const changes = options.changes?.(name, input, out.result);\n return { ok: true, result: out.result, ...(changes?.length ? { changes } : {}) };\n },\n });\n });\n}\n\nconst S = 1_000_000;\n/** Slide presets are named by motion; models do better naming the edge, so these map edges to presets. */\nconst SLIDE_IN: Record<string, string> = { \"from-right\": \"left\", \"from-left\": \"right\", \"from-bottom\": \"up\", \"from-top\": \"down\" };\nconst SLIDE_OUT: Record<string, string> = { \"to-left\": \"left\", \"to-right\": \"right\", \"to-top\": \"up\", \"to-bottom\": \"down\" };\nfunction slideAliases(input: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (typeof input.in === \"string\" && SLIDE_IN[input.in]) out.in = SLIDE_IN[input.in];\n if (typeof input.out === \"string\" && SLIDE_OUT[input.out]) out.out = SLIDE_OUT[input.out];\n return out;\n}\n/** The html template set_background uses: one `{{color}}` fill. */\nexport const BACKGROUND_TEMPLATE = '<div style=\"width:100%;height:100%;background:{{color}}\"></div>';\nconst seconds = (us: number) => `${Math.round(us / 100_000) / 10}s`;\nconst n3 = (v: number) => Number(v.toFixed(3));\nconst toUs = (s: unknown) => (typeof s === \"number\" && Number.isFinite(s) ? Math.round(s * S) : undefined);\n\n/* ---------- describing commands for people ---------- */\n\nconst PHRASES: Record<string, (p: Record<string, unknown>) => string> = {\n \"clip/add\": (p) =>\n p.kind === \"text\" ? `Added text \"${String(p.text ?? \"\").slice(0, 40)}\" at ${seconds(Number(p.startUs))}` : `Added a ${p.kind} clip at ${seconds(Number(p.startUs))}`,\n \"clip/remove\": (p) => `Removed clip ${p.clipId}`,\n \"clip/move\": (p) => `Moved clip ${p.clipId}${p.startUs !== undefined ? ` to ${seconds(Number(p.startUs))}` : \"\"}`,\n \"clip/trim\": (p) => `Trimmed clip ${p.clipId}`,\n \"clip/split\": (p) => `Split clip ${p.clipId} at ${seconds(Number(p.atUs))}`,\n \"clip/duplicate\": (p) => `Duplicated clip ${p.clipId}`,\n \"clip/set-property\": (p) => `Changed ${Object.keys(p).filter((k) => k !== \"clipId\").join(\", \")} of clip ${p.clipId}`,\n \"track/add\": (p) => `Added a ${p.kind} track`,\n \"track/remove\": (p) => `Removed track ${p.id}`,\n \"track/set-property\": (p) => `Changed track ${p.trackId}: ${Object.keys(p).filter((k) => k !== \"trackId\").join(\", \")}`,\n \"effect/add\": (p) => `Added ${p.kind} to clip ${p.clipId}`,\n \"effect/update\": (p) => `Adjusted an effect on clip ${p.clipId}`,\n \"effect/remove\": (p) => `Removed an effect from clip ${p.clipId}`,\n \"transition/add\": (p) => `Added a ${p.kind} transition`,\n \"transition/remove\": () => \"Removed a transition\",\n \"project/set-settings\": () => \"Changed the project settings\",\n};\n\n/** One line per command, for a \"what changed\" list (keyframe edits fold into one line per clip). */\nexport function describeCommands(commands: readonly Command[]): string[] {\n const lines: string[] = [];\n const keyframed = new Set<string>();\n for (const c of commands) {\n const p = (c.payload ?? {}) as Record<string, unknown>;\n if (c.type.startsWith(\"keyframe/\")) {\n const id = String(p.clipId);\n if (!keyframed.has(id)) lines.push(`Changed the animation of clip ${id}`);\n keyframed.add(id);\n continue;\n }\n const phrase = PHRASES[c.type];\n lines.push(phrase ? phrase(p) : `${c.type}`);\n }\n return lines;\n}\n\n/* ---------- the editor tools ---------- */\n\nconst US_NOTE = \"Times in commands are integer MICROSECONDS (1 s = 1000000).\";\n\nexport interface EditorToolsOptions {\n /** Transition kinds to offer (default: the built-ins). Add your registered custom kinds. */\n transitionKinds?: string[];\n /** The command catalog to offer in apply_commands (default: the built-ins). Pass `project.commandCatalog()` when you register custom commands. */\n commandCatalog?: Record<string, unknown>;\n}\n\n/**\n * The tools that edit a Miraiclip project: read state, look up a command's\n * schema, apply command batches, and two high-level tools (transitions,\n * animation presets) that use the same logic as the editor's panels.\n */\nexport function editorTools(options: EditorToolsOptions = {}): AssistantTool[] {\n const transitionKinds = options.transitionKinds ?? Object.keys(builtinTransitionParamSchemas);\n const presetIds = (slot: AnimationSlot) => ANIMATION_PRESETS.filter((p) => p.slot === slot).map((p) => p.id.split(\":\")[1]!);\n\n return [\n defineTool({\n name: \"get_state\",\n description: `The project as it is now (after your edits so far): settings, assets, tracks with clips (ids, kinds, time ranges), transitions, and each clip's position, size, opacity, text style, volume, effects and animation. ${US_NOTE}`,\n inputSchema: {\n type: \"object\",\n properties: { includeJson: { type: \"boolean\", description: \"Also return the full document JSON (verbose; only for exact field values).\" } },\n additionalProperties: false,\n },\n run(input, { project }) {\n const summary = describeForAssistant(project.toJSON());\n return { ok: true, result: input.includeJson ? { summary, document: project.toJSON() } : summary };\n },\n }),\n\n defineTool({\n name: \"get_command_schema\",\n description: \"The JSON Schema of one editing command's payload. Look it up before using a command in apply_commands for the first time.\",\n inputSchema: {\n type: \"object\",\n properties: { type: { type: \"string\", description: 'Command type, e.g. \"clip/add\".' } },\n required: [\"type\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const catalog = project.commandCatalog();\n const schema = catalog[String(input.type)];\n return schema ? { ok: true, result: schema } : { ok: false, error: { error: `unknown command \"${input.type}\"`, validTypes: Object.keys(catalog).sort() } };\n },\n }),\n\n defineTool({\n name: \"apply_commands\",\n description:\n \"Apply editing commands as one all-or-nothing batch. On failure nothing changes and the error names the failing index and why (invalid payload issues, or the engine's rejection reason) — fix it and retry. \" +\n `Give new clips, tracks and assets your own readable ids. ${US_NOTE}`,\n inputSchema: applyCommandsSchema(options.commandCatalog ?? commandCatalog()),\n run(input, { project }) {\n const commands = input.commands as Command[] | undefined;\n if (!Array.isArray(commands) || commands.length === 0) return { ok: false, error: \"commands must be a non-empty array of { type, payload }\" };\n return applyChecked(project, commands);\n },\n }),\n\n defineTool({\n name: \"add_transition\",\n description:\n \"Add (or replace, or remove) a transition on cuts — where one clip ends exactly where the next starts on the same video track. Pick the cut by its two clip ids, by a time near it, or all cuts. \" +\n \"A transition overlaps both clips around the cut, so its length is capped by the spare footage there; cuts with none are skipped and reported. \" +\n 'When a video clip directly follows another on its track, \"fade into / dissolve to / slide in / wipe to\" that clip means a transition on the cut before it, not an animation. ' +\n 'Slide / wipe direction is the direction of motion: \"from the left\" = right.',\n inputSchema: {\n type: \"object\",\n properties: {\n kind: { type: \"string\", enum: [...transitionKinds, \"none\"], description: '\"none\" removes the transition.' },\n fromClipId: { type: \"string\", description: \"The clip ending at the cut.\" },\n toClipId: { type: \"string\", description: \"The clip starting at the cut.\" },\n nearSeconds: { type: \"number\", description: \"Pick the cut closest to this time instead.\" },\n allCuts: { type: \"boolean\", description: \"Apply to every cut.\" },\n durationSeconds: { type: \"number\", minimum: 0.1, maximum: 3, description: \"Default 0.6.\" },\n direction: { type: \"string\", enum: [\"left\", \"right\", \"up\", \"down\"], description: \"wipe / slide only.\" },\n },\n required: [\"kind\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const cuts = findCuts(project.getState().doc);\n if (cuts.length === 0) return { ok: false, error: \"There are no cuts: transitions need two clips touching on the same video track.\" };\n let targets: Cut[];\n if (input.allCuts === true) targets = cuts;\n else if (typeof input.fromClipId === \"string\" || typeof input.toClipId === \"string\") {\n targets = cuts.filter((c) => (!input.fromClipId || c.fromClipId === input.fromClipId) && (!input.toClipId || c.toClipId === input.toClipId));\n if (targets.length === 0) return { ok: false, error: { error: noCutReason(project, input.fromClipId, input.toClipId), cuts: cuts.map(cutInfo) } };\n } else {\n const at = toUs(input.nearSeconds) ?? project.getState().playheadUs;\n const nearest = cuts.reduce((a, b) => (Math.abs(b.atUs - at) < Math.abs(a.atUs - at) ? b : a));\n if (input.nearSeconds !== undefined && Math.abs(nearest.atUs - at) > 1.5 * S) {\n return {\n ok: false,\n error: { error: `There is no cut near ${seconds(at)} (the nearest is at ${seconds(nearest.atUs)}). Transitions only go on cuts; nothing was added. Use one of these cuts, or tell the user there isn't one there.`, cuts: cuts.map(cutInfo) },\n };\n }\n targets = [nearest];\n }\n if (targets.length === 0) return { ok: false, error: { error: \"no cut matches\", cuts: cuts.map(cutInfo) } };\n const kind = String(input.kind);\n const wanted = toUs(input.durationSeconds) ?? 600_000;\n const commands: Command[] = [];\n const changes: string[] = [];\n const skipped: unknown[] = [];\n for (const cut of targets) {\n if (cut.transition) commands.push({ type: \"transition/remove\", payload: { transitionId: cut.transition.id } });\n if (kind === \"none\") {\n if (cut.transition) changes.push(`Removed the transition at ${seconds(cut.atUs)}`);\n continue;\n }\n const durationUs = Math.min(wanted, cut.maxTransitionUs);\n if (durationUs < 100_000) {\n skipped.push({ ...cutInfo(cut), reason: `no spare footage (${cut.short === \"from\" ? \"the first clip ends where its media ends\" : cut.short === \"to\" ? \"the second clip starts at its media's start\" : \"both clips use all their media\"})` });\n if (cut.transition) commands.pop();\n continue;\n }\n const params = input.direction && (kind === \"wipe\" || kind === \"slide\") ? { direction: input.direction } : undefined;\n commands.push({ type: \"transition/add\", payload: { kind, fromClipId: cut.fromClipId, toClipId: cut.toClipId, durationUs, ...(params ? { params } : {}) } });\n changes.push(`${cut.transition ? \"Replaced the transition with\" : \"Added\"} ${kind} at ${seconds(cut.atUs)} (${seconds(durationUs)})`);\n }\n if (commands.length) {\n const result = applyCommands(project, commands);\n if (!result.ok) return { ok: false, error: result };\n }\n return { ok: true, result: { changed: changes.length, skipped }, changes };\n },\n }),\n\n defineTool({\n name: \"animate_clip\",\n description:\n \"Give a visual clip (video, image, text) an entrance (in), a loop while on screen, and/or an exit (out), as keyframes. Slots you leave out keep their current animation; \\\"none\\\" removes one; reset:true removes all. \" +\n `In/out presets: ${presetIds(\"in\").join(\", \")}. Loops: ${presetIds(\"loop\").join(\", \")}. Exits stay on the clip's end through trims. ` +\n 'Slides: give the edge, in: \"from-right\" (enters from the right edge, moving left), \"from-left\", \"from-top\", \"from-bottom\"; out: \"to-left\", \"to-right\", \"to-top\", \"to-bottom\". ' +\n \"For text, logos and overlays; between two video clips prefer add_transition. The clip's current animation is in get_state; pass only the slots to change. \" +\n \"Fading the whole VIDEO in at the start and out at the end is two calls: in on the FIRST clip of the main video track, out on the LAST one (an out on the first clip would fade to black at its cut).\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n in: { type: \"string\", enum: [...presetIds(\"in\"), ...Object.keys(SLIDE_IN), \"none\"], description: 'For slides, prefer \"from-left\" / \"from-right\" / \"from-top\" / \"from-bottom\": the edge the clip enters from.' },\n loop: { type: \"string\", enum: [...presetIds(\"loop\"), \"none\"] },\n out: { type: \"string\", enum: [...presetIds(\"out\"), ...Object.keys(SLIDE_OUT), \"none\"], description: 'For slides, prefer \"to-left\" / \"to-right\" / \"to-top\" / \"to-bottom\": the edge the clip leaves by.' },\n inSeconds: { type: \"number\", minimum: 0.2, maximum: 3, description: \"Default 0.6.\" },\n outSeconds: { type: \"number\", minimum: 0.2, maximum: 3, description: \"Default 0.6.\" },\n easing: { type: \"string\", enum: ANIMATION_EASINGS.map((e) => e.id), description: \"Default smooth.\" },\n reset: { type: \"boolean\" },\n },\n required: [\"clipId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n input = { ...input, ...slideAliases(input) };\n const clip = project.getState().doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n if (clip.kind === \"audio\") return { ok: false, error: \"audio clips have no picture to animate (use volume or fades)\" };\n const reading = readClipAnimation(clip);\n if (reading.custom && input.reset !== true) {\n return {\n ok: false,\n error: `${clip.id} has its own keyframes (${describeKeyframes(clip)}), not presets; presets would overwrite them. To remove one property's animation, apply_commands keyframe/clear { clipId, property }. To edit them, use set_keyframes. To replace them all with presets, pass reset: true. Nothing was changed.`,\n };\n }\n const current = input.reset === true ? {} : reading.recipe;\n const next: AnimationRecipe = { ...current };\n const easing = (typeof input.easing === \"string\" ? input.easing : \"smooth\") as AnimationEasing;\n for (const slot of [\"in\", \"loop\", \"out\"] as const) {\n const name = input[slot];\n if (name === undefined) continue;\n if (name === \"none\") {\n delete next[slot];\n continue;\n }\n const durationUs = slot === \"loop\" ? 0 : toUs(input[slot === \"in\" ? \"inSeconds\" : \"outSeconds\"]) ?? current[slot]?.durationUs ?? 600_000;\n next[slot] = { preset: `${slot}:${name}`, durationUs, easing: slot === \"loop\" ? \"linear\" : easing };\n }\n const recipe = fitAnimation(next, clip.durationUs);\n const result = applyCommands(project, animationCommands(clip, recipe));\n if (!result.ok) return { ok: false, error: result };\n const summary = describeAnimation(recipe) || \"no animation\";\n const atCut = input.in && input.in !== \"none\" && clip.kind === \"video\" ? findCuts(project.getState().doc).find((c) => c.toClipId === clip.id) : undefined;\n return {\n ok: true,\n result: {\n clipId: clip.id,\n animation: summary,\n ...(atCut ? { note: `${clip.id} starts at a cut right after ${atCut.fromClipId}. If the user meant going from ${atCut.fromClipId} into ${clip.id} (\"fade into\", \"slide in\", \"dissolve to\"), that is add_transition on this cut: undo this entrance with in:\"none\" and add the transition.` } : {}),\n },\n changes: [`${clip.id}: ${summary}`],\n };\n },\n }),\n\n defineTool({\n name: \"add_effect\",\n description:\n \"Add a visual effect to one or more clips (video, image, text). Kinds, with their params (min–max, default): \" +\n EFFECT_CATALOG.map((e) => `${e.kind} (${e.label}${e.params.length ? `: ${e.params.map((p) => (p.type === \"number\" ? `${p.key} ${p.min}–${p.max}, ${p.default}` : `${p.key} color`)).join(\"; \")}` : \"\"})`).join(\", \") +\n \". Omitted params take their defaults. Black & white is mono; brightness, contrast, saturation and hue are colorAdjust params (-1–1, 0 = unchanged).\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", enum: EFFECT_CATALOG.map((e) => e.kind) },\n params: { type: \"object\", description: \"Effect params by key; see the list above.\" },\n },\n required: [\"clipIds\", \"kind\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const ids = (input.clipIds as string[]) ?? [];\n const doc = project.getState().doc;\n const missing = ids.filter((id) => !doc.clips[id]);\n if (missing.length) return { ok: false, error: `no clip ${missing.map((m) => `\"${m}\"`).join(\", \")}` };\n const audio = ids.filter((id) => doc.clips[id]!.kind === \"audio\");\n if (audio.length) return { ok: false, error: `audio clips have no picture: ${audio.join(\", \")}` };\n const params = input.params && typeof input.params === \"object\" ? (input.params as Record<string, unknown>) : undefined;\n const out = applyChecked(project, ids.map((clipId) => ({ type: \"effect/add\", payload: { clipId, kind: input.kind, ...(params ? { params } : {}) } })));\n if (!out.ok) return out;\n const label = EFFECT_CATALOG.find((e) => e.kind === input.kind)?.label ?? String(input.kind);\n return { ...out, changes: [`Added ${label} to ${ids.join(\", \")}`] };\n },\n }),\n\n defineTool({\n name: \"remove_effects\",\n description: \"Delete effects from clips: one kind, or every effect when kind is omitted. To turn effects off but keep them, use set_effects_enabled.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", description: \"Only effects of this kind (default: all).\" },\n },\n required: [\"clipIds\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const commands: Command[] = [];\n for (const id of (input.clipIds as string[]) ?? []) {\n const clip = doc.clips[id];\n if (!clip) return { ok: false, error: `no clip \"${id}\"` };\n for (const e of clip.effects ?? []) if (!input.kind || e.kind === input.kind) commands.push({ type: \"effect/remove\", payload: { clipId: id, effectId: e.id } });\n }\n if (!commands.length) return { ok: true, result: { removed: 0, note: \"those clips had no matching effects\" } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, result: { removed: commands.length }, changes: [`Removed ${commands.length} effect${commands.length > 1 ? \"s\" : \"\"}`] } : out;\n },\n }),\n\n defineTool({\n name: \"trim_clip\",\n description:\n \"Trim a clip like an editor's edge drag, in seconds. removeFromStart cuts that much off the beginning (the clip's end stays put; for video/audio the source moves on too). \" +\n \"removeFromEnd cuts off the end. setDuration sets the length, keeping the start. startSeconds / endSeconds put the clip's edges at those timeline times (e.g. 0 and the composition length to cover the whole video; a video/audio clip's source shifts with its start edge). \" +\n \"ripple:true shifts later clips on the same track to close (or open) the gap.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n removeFromStart: { type: \"number\", exclusiveMinimum: 0 },\n removeFromEnd: { type: \"number\", exclusiveMinimum: 0 },\n setDuration: { type: \"number\", exclusiveMinimum: 0 },\n startSeconds: { type: \"number\", minimum: 0, description: \"Timeline time for the clip's start edge.\" },\n endSeconds: { type: \"number\", exclusiveMinimum: 0, description: \"Timeline time for the clip's end edge.\" },\n ripple: { type: \"boolean\" },\n },\n required: [\"clipId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const clip = doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n const head = toUs(input.removeFromStart) ?? 0;\n const tail = toUs(input.removeFromEnd) ?? 0;\n const ripple = input.ripple === true;\n const startAt = toUs(input.startSeconds);\n const endAt = toUs(input.endSeconds);\n if ((startAt !== undefined || endAt !== undefined) && (head || tail)) return { ok: false, error: \"use either startSeconds / endSeconds or removeFromStart / removeFromEnd, not both\" };\n let duration = clip.durationUs - head - tail;\n const set = toUs(input.setDuration);\n if (set) duration = set;\n // Without ripple, cutting the head keeps the clip's end in place; with ripple the clip keeps its start and later clips move up.\n let start = ripple ? clip.startUs : clip.startUs + head;\n let sourceShift = head;\n if (startAt !== undefined) {\n start = startAt;\n sourceShift = startAt - clip.startUs;\n if (endAt === undefined && !set) duration = clip.startUs + clip.durationUs - startAt;\n }\n if (endAt !== undefined) duration = endAt - start;\n if (duration <= 0) return { ok: false, error: `that leaves the clip ${seconds(duration)} long; it is ${seconds(clip.durationUs)} (${seconds(clip.startUs)}–${seconds(clip.startUs + clip.durationUs)})` };\n const trimmable = \"trimStartUs\" in clip;\n if (trimmable && (clip as { trimStartUs: number }).trimStartUs + sourceShift < 0) {\n return { ok: false, error: `${clip.id}'s media has only ${seconds((clip as { trimStartUs: number }).trimStartUs)} before its current start, so its start edge can move back at most that far` };\n }\n const commands: Command[] = [\n {\n type: \"clip/trim\",\n payload: {\n clipId: clip.id,\n startUs: start,\n durationUs: duration,\n ...(trimmable && sourceShift ? { trimStartUs: (clip as { trimStartUs: number }).trimStartUs + sourceShift } : {}),\n },\n },\n ];\n if (ripple) {\n const oldEnd = clip.startUs + clip.durationUs;\n const delta = start + duration - oldEnd;\n const later = Object.values(doc.clips)\n .filter((c) => c.trackId === clip.trackId && c.id !== clip.id && c.startUs >= oldEnd)\n .sort((x, y) => (delta < 0 ? x.startUs - y.startUs : y.startUs - x.startUs));\n for (const c of later) commands.push({ type: \"clip/move\", payload: { clipId: c.id, startUs: Math.max(0, c.startUs + delta) } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n const after = project.getState().doc.clips[clip.id]!;\n return { ...out, changes: [`Trimmed ${clip.id} to ${seconds(after.startUs)}–${seconds(after.startUs + after.durationUs)}`] };\n },\n }),\n\n defineTool({\n name: \"set_effects_enabled\",\n description: \"Turn effects off (or back on) without deleting them, keeping their settings: one kind, or every effect when kind is omitted. To delete effects use remove_effects.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipIds: { type: \"array\", items: { type: \"string\" }, minItems: 1 },\n kind: { type: \"string\", description: \"Only effects of this kind (default: all).\" },\n enabled: { type: \"boolean\" },\n },\n required: [\"clipIds\", \"enabled\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const enabled = input.enabled === true;\n const commands: Command[] = [];\n for (const id of (input.clipIds as string[]) ?? []) {\n const clip = doc.clips[id];\n if (!clip) return { ok: false, error: `no clip \"${id}\"` };\n for (const e of clip.effects ?? []) {\n if ((!input.kind || e.kind === input.kind) && e.enabled !== enabled) commands.push({ type: \"effect/update\", payload: { clipId: id, effectId: e.id, enabled } });\n }\n }\n if (!commands.length) return { ok: true, result: { changed: 0, note: `no matching effects that are ${enabled ? \"off\" : \"on\"}` } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, result: { changed: commands.length }, changes: [`Turned ${enabled ? \"on\" : \"off\"} ${commands.length} effect${commands.length > 1 ? \"s\" : \"\"}`] } : out;\n },\n }),\n\n defineTool({\n name: \"set_keyframes\",\n description:\n \"Animate one property of a clip so it CHANGES over time, with keyframes at TIMELINE seconds (the same times as get_state). Replaces that property's existing keyframes (including a preset's) unless keep:true. Between points the value moves smoothly; before the first and after the last it holds. \" +\n \"Properties: x, y (0–1, 0.5 = center), scale (1 = full size), rotation (degrees; 360 = one full turn, so a static 360 looks like 0), opacity (0–1), volume (0–1, audio/video). \" +\n \"Not for constant values (\\\"rotate 45°\\\", \\\"music at 30%\\\", \\\"louder\\\": set those with clip/set-property) or for removing an animation (keyframe/clear). Use it for motion and timed changes the presets don't cover: a spin (rotation 0 → 360 over the clip), a pan, ducking music (volume: normal → low just before a range, low → normal just after), or fading audio between two times.\",\n inputSchema: {\n type: \"object\",\n properties: {\n clipId: { type: \"string\" },\n property: { type: \"string\", enum: [\"x\", \"y\", \"scale\", \"rotation\", \"opacity\", \"volume\"] },\n points: {\n type: \"array\",\n minItems: 1,\n items: {\n type: \"object\",\n properties: { atSeconds: { type: \"number\", minimum: 0 }, value: { type: \"number\" } },\n required: [\"atSeconds\", \"value\"],\n additionalProperties: false,\n },\n },\n easing: { type: \"string\", enum: [\"linear\", \"easeIn\", \"easeOut\", \"easeInOut\", \"hold\"], description: \"Curve between points (default linear).\" },\n keep: { type: \"boolean\", description: \"Keep the property's other keyframes (default false: replace them).\" },\n },\n required: [\"clipId\", \"property\", \"points\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const clip = project.getState().doc.clips[String(input.clipId)];\n if (!clip) return { ok: false, error: `no clip \"${input.clipId}\"` };\n const property = String(input.property);\n if (property === \"volume\" && !(\"volume\" in clip)) return { ok: false, error: `${clip.id} is a ${clip.kind} clip and has no volume` };\n if (property !== \"volume\" && clip.kind === \"audio\") return { ok: false, error: \"audio clips only animate volume\" };\n const end = clip.startUs + clip.durationUs;\n const points = (input.points as { atSeconds: number; value: number }[]).map((p) => ({ atUs: toUs(p.atSeconds)!, value: p.value }));\n const outside = points.filter((p) => p.atUs < clip.startUs - 1000 || p.atUs > end + 1000);\n if (outside.length) return { ok: false, error: `${clip.id} runs ${seconds(clip.startUs)}–${seconds(end)}; points must be inside that range (got ${outside.map((p) => seconds(p.atUs)).join(\", \")})` };\n if (input.keep !== true && new Set(points.map((p) => p.value)).size < 2) {\n const how = property === \"volume\" ? \"clip/set-property { volume }\" : `clip/set-property { transform: { ${property} } }`;\n return {\n ok: false,\n error: `Keyframes are for a value that CHANGES over time; ${points.length === 1 ? \"one point\" : \"these points\"} hold${points.length === 1 ? \"s\" : \"\"} a single value. For a constant ${property}, set it directly with apply_commands ${how}. To remove an animation, apply keyframe/clear { clipId, property }. Nothing was changed.`,\n };\n }\n const commands: Command[] = [];\n if (input.keep !== true && (clip.animations?.[property as \"x\"]?.length ?? 0) > 0) commands.push({ type: \"keyframe/clear\", payload: { clipId: clip.id, property } });\n const easing = typeof input.easing === \"string\" ? input.easing : \"linear\";\n for (const p of points) {\n commands.push({ type: \"keyframe/set\", payload: { clipId: clip.id, property, timeUs: Math.min(clip.durationUs, Math.max(0, p.atUs - clip.startUs)), value: p.value, easing } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n const list = points.map((p) => `${seconds(p.atUs)} ${n3(p.value)}`).join(\" → \");\n return { ...out, changes: [`${clip.id}: ${property} ${list}`] };\n },\n }),\n\n defineTool({\n name: \"set_background\",\n description:\n \"A solid color background behind everything (an html clip on a Background track at the very bottom). Adds one, recolors or re-times the existing one, or removes it with color \\\"none\\\". \" +\n \"Covers the whole video unless fromSeconds / toSeconds say otherwise. Only visible where nothing opaque is on top (behind scaled-down, faded or transparent clips, or where there's no footage).\",\n inputSchema: {\n type: \"object\",\n properties: {\n color: { type: \"string\", description: 'CSS color, e.g. \"#1E3A8A\", or \"none\" to remove the background.' },\n fromSeconds: { type: \"number\", minimum: 0 },\n toSeconds: { type: \"number\", exclusiveMinimum: 0 },\n },\n required: [\"color\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n const color = String(input.color).trim();\n const existing = Object.values(doc.clips).find(\n (c) => c.kind === \"html\" && ((c as { template?: string }).template === BACKGROUND_TEMPLATE || doc.tracks[c.trackId]?.name === \"Background\"),\n );\n if (color.toLowerCase() === \"none\") {\n if (!existing) return { ok: true, result: { note: \"there is no background to remove\" } };\n const commands: Command[] = [{ type: \"clip/remove\", payload: { clipId: existing.id } }];\n if (!Object.values(doc.clips).some((c) => c.trackId === existing.trackId && c.id !== existing.id)) commands.push({ type: \"track/remove\", payload: { id: existing.trackId } });\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, changes: [\"Removed the background\"] } : out;\n }\n let endUs = 0;\n for (const c of Object.values(doc.clips)) if (c.id !== existing?.id) endUs = Math.max(endUs, c.startUs + c.durationUs);\n const startUs = toUs(input.fromSeconds) ?? (existing && input.toSeconds === undefined ? existing.startUs : 0);\n const stopUs = toUs(input.toSeconds) ?? (existing && input.fromSeconds === undefined ? existing.startUs + existing.durationUs : endUs || 10 * S);\n if (stopUs <= startUs) return { ok: false, error: `toSeconds must be after fromSeconds (got ${seconds(startUs)}–${seconds(stopUs)})` };\n const commands: Command[] = [];\n if (existing) {\n const params = existing as { template: string; params: Record<string, unknown> };\n const key = htmlPlaceholders(params.template).find((k) => /colou?r|background|bg/i.test(k)) ?? \"color\";\n if (params.params[key] !== color) commands.push({ type: \"clip/set-property\", payload: { clipId: existing.id, params: { [key]: color } } });\n if (existing.startUs !== startUs || existing.durationUs !== stopUs - startUs) commands.push({ type: \"clip/trim\", payload: { clipId: existing.id, startUs, durationUs: stopUs - startUs } });\n if (!commands.length) return { ok: true, result: { note: \"the background already looks like that\" } };\n } else {\n const trackId = doc.tracks.background ? `background-${Object.keys(doc.tracks).length}` : \"background\";\n commands.push({ type: \"track/add\", payload: { id: trackId, kind: \"video\", name: \"Background\", index: 0 } });\n commands.push({ type: \"clip/add\", payload: { kind: \"html\", id: `${trackId}-clip`, trackId, startUs, durationUs: stopUs - startUs, template: BACKGROUND_TEMPLATE, params: { color } } });\n }\n const out = applyChecked(project, commands);\n if (!out.ok) return out;\n return { ...out, changes: [`${existing ? \"Changed the background to\" : \"Added a background:\"} ${color}, ${seconds(startUs)}–${seconds(stopUs)}`] };\n },\n }),\n\n defineTool({\n name: \"close_gaps\",\n description: \"Close the empty gaps on a track so its clips run back to back, keeping their order (the first clip stays where it is, or starts at 0 with fromZero).\",\n inputSchema: {\n type: \"object\",\n properties: { trackId: { type: \"string\" }, fromZero: { type: \"boolean\" } },\n required: [\"trackId\"],\n additionalProperties: false,\n },\n run(input, { project }) {\n const doc = project.getState().doc;\n if (!doc.tracks[String(input.trackId)]) return { ok: false, error: `no track \"${input.trackId}\"` };\n const clips = Object.values(doc.clips)\n .filter((c) => c.trackId === input.trackId)\n .sort((a, b) => a.startUs - b.startUs);\n let cursor = input.fromZero === true ? 0 : clips[0]?.startUs ?? 0;\n const commands: Command[] = [];\n for (const c of clips) {\n if (c.startUs !== cursor) commands.push({ type: \"clip/move\", payload: { clipId: c.id, startUs: cursor } });\n cursor += c.durationUs;\n }\n if (!commands.length) return { ok: true, result: { moved: 0, note: \"no gaps on that track\" } };\n const out = applyChecked(project, commands);\n return out.ok ? { ...out, changes: [`Closed ${commands.length} gap${commands.length > 1 ? \"s\" : \"\"} on ${input.trackId}`] } : out;\n },\n }),\n ];\n}\n\n/* ---------- apply_commands, checked ---------- */\n\nclass Abort extends Error {}\n\n/**\n * Apply a batch as one all-or-nothing step, with two checks core doesn't do:\n * fields a command would silently ignore are errors, and commands that\n * changed nothing are reported, so the model never claims an edit that didn't\n * happen.\n */\nexport function applyChecked(project: Project, commands: Command[]): ToolOutput {\n const catalog = project.commandCatalog();\n const nothing = commands.length > 1 ? \"Nothing in this batch was applied (not even the commands before it): resend the whole corrected batch.\" : \"Nothing was applied.\";\n const templates = new Map<string, string>();\n for (const [index, command] of commands.entries()) {\n if (!catalog[command?.type]) {\n const looksLikeTool = /^[a-z]+(_[a-z]+)+$/.test(String(command?.type));\n return {\n ok: false,\n error: {\n failedIndex: index,\n kind: \"unknown-command\",\n commandType: command?.type,\n error: `\"${command?.type}\" is not a command${looksLikeTool ? \": it is a tool. Call it as its own tool call, not inside apply_commands\" : \"\"}. ${nothing}`,\n validTypes: Object.keys(catalog).sort(),\n },\n };\n }\n const htmlError = checkHtmlParams(project, command, templates);\n if (htmlError) return { ok: false, error: { failedIndex: index, commandType: command.type, error: `${htmlError} ${nothing}` } };\n const extra = unknownFields(catalog[command?.type], command?.payload);\n if (extra) {\n return {\n ok: false,\n error: {\n failedIndex: index,\n commandType: command.type,\n error: `unknown field${extra.unknown.length > 1 ? \"s\" : \"\"} ${extra.unknown.map((f) => `\"${f}\"`).join(\", \")}: ${command.type} would ignore ${extra.unknown.length > 1 ? \"them\" : \"it\"}. Its fields are: ${extra.allowed.join(\", \")}. ${nothing}`,\n },\n };\n }\n }\n const unchanged: number[] = [];\n let failure: unknown;\n try {\n project.transaction(() => {\n commands.forEach((command, index) => {\n const before = project.getState().doc;\n const result = tryDispatch(project, command);\n if (!result.ok) {\n const hint = rejectionHint(result.error as { code?: string; commandType?: string }, command);\n const skipped = commands.length > 1 ? { notApplied: describeCommands(commands.filter((_, i) => i !== index)) } : {};\n failure = { failedIndex: index, ...result.error, ...(hint ? { hint } : {}), note: nothing, ...skipped };\n throw new Abort();\n }\n if (project.getState().doc === before) unchanged.push(index);\n });\n });\n } catch (err) {\n if (err instanceof Abort) return { ok: false, error: failure };\n throw err;\n }\n const changed = commands.filter((_, i) => !unchanged.includes(i));\n return {\n ok: true,\n result: {\n applied: changed.length,\n ...(unchanged.length\n ? { unchanged: unchanged.map((i) => ({ index: i, type: commands[i]!.type, note: \"changed nothing: the project already had these values. Check the field names and values.\" })) }\n : {}),\n },\n ...(changed.length ? { changes: describeCommands(changed) } : {}),\n };\n}\n\n/** html clips substitute `{{name}}` placeholders: params with any other name change nothing on screen. */\nfunction checkHtmlParams(project: Project, command: Command, templates: Map<string, string>): string | undefined {\n const p = (command.payload ?? {}) as Record<string, unknown>;\n let template: string | undefined;\n if (command.type === \"clip/add\" && p.kind === \"html\" && typeof p.template === \"string\") {\n template = p.template;\n if (typeof p.id === \"string\") templates.set(p.id, template);\n } else if (command.type === \"clip/set-property\" && p.params && typeof p.params === \"object\") {\n const clip = project.getState().doc.clips[String(p.clipId)] as { kind?: string; template?: string } | undefined;\n template = templates.get(String(p.clipId)) ?? (clip?.kind === \"html\" ? clip.template : undefined);\n }\n if (template === undefined || !p.params || typeof p.params !== \"object\") return undefined;\n const names = htmlPlaceholders(template);\n const unknown = Object.keys(p.params).filter((k) => !names.includes(k));\n if (!unknown.length) return undefined;\n return `html params ${unknown.map((k) => `\"${k}\"`).join(\", \")} match no {{placeholder}} in the template, so they would change nothing. Its placeholders: ${names.join(\", \") || \"none\"}.`;\n}\n\n/** What to do instead, for rejections models commonly hit. */\nfunction rejectionHint(error: { code?: string }, _command: Command): string | undefined {\n switch (error.code) {\n case \"no-audio\":\n return \"fadeInUs / fadeOutUs fade audio only. To fade a text, image or video picture in or out, call animate_clip (in / out: fade).\";\n case \"asset-not-found\":\n return \"Clips can only use assets already in the project (see get_state). Audio found with search_audio is added with add_audio, which imports it.\";\n case \"not-caption\":\n case \"not-html\":\n case \"not-text\":\n return \"That field belongs to another clip kind: text clips take color / font fields, caption clips take style, html clips take params (named by the template's {{placeholders}}, shown in get_state).\";\n default:\n return undefined;\n }\n}\n\n/** Why two clips have no cut between them, so the model reports it instead of picking another cut. */\nfunction noCutReason(project: Project, fromId: unknown, toId: unknown): string {\n const doc = project.getState().doc;\n const a = typeof fromId === \"string\" ? doc.clips[fromId] : undefined;\n const b = typeof toId === \"string\" ? doc.clips[toId] : undefined;\n const tail = \"Nothing was added. Don't substitute a different cut: tell the user, and offer an animation (animate_clip) instead if that fits.\";\n for (const [given, clip] of [[fromId, a], [toId, b]] as const) if (typeof given === \"string\" && !clip) return `There is no clip \"${given}\". ${tail}`;\n if (a && b && a.trackId !== b.trackId) return `${a.id} is on track ${a.trackId} and ${b.id} on track ${b.trackId}: a transition joins two clips that touch on the SAME track, so these two have no cut between them. ${tail}`;\n if (a && b) return `${a.id} and ${b.id} don't touch (${a.id} ends at ${seconds(a.startUs + a.durationUs)}, ${b.id} starts at ${seconds(b.startUs)}). ${tail}`;\n return `No cut ${a ? `starts after ${a.id}` : `leads into ${b!.id}`} (it isn't directly after/before another clip on its track). ${tail}`;\n}\n\nfunction cutInfo(c: Cut) {\n return { fromClipId: c.fromClipId, toClipId: c.toClipId, atSeconds: c.atUs / S, maxSeconds: c.maxTransitionUs / S, ...(c.transition ? { transition: c.transition.kind } : {}) };\n}\n\n/** apply_commands' input schema: `type` is an enum of the catalog's commands. */\nexport function applyCommandsSchema(catalog: Record<string, unknown>): Record<string, unknown> {\n const [dispatch] = toToolDefinitions(catalog, { mode: \"dispatch\" }) as { input_schema: Record<string, unknown> }[];\n return {\n type: \"object\",\n properties: {\n commands: { type: \"array\", minItems: 1, items: dispatch!.input_schema, description: \"Commands applied in order, as one batch.\" },\n },\n required: [\"commands\"],\n additionalProperties: false,\n };\n}\n","import { createProject, type Command, type Project } from \"@miraiclip/core\";\n\n/**\n * A working copy of a project that records every command that sticks.\n *\n * The assistant edits the copy while the model thinks (async, many steps);\n * the real project only changes when the turn commits, by replaying the\n * recorded commands in one transaction — one undo step, and nothing half-done\n * if the request fails. Commands inside a transaction that rolls back are\n * dropped, exactly as the copy drops their effects.\n *\n * Replay must produce the same ids the model saw, so commands whose ids are\n * optional get explicit ones before they run.\n */\nexport interface RecordingProject extends Project {\n /** Commands that changed the copy, in order. */\n readonly recorded: readonly Command[];\n}\n\nexport interface ForkOptions {\n /** Build the copy (default: `createProject(doc)`). Register custom commands here. */\n createFork?: (doc: ReturnType<Project[\"toJSON\"]>) => Project;\n /** Give commands explicit ids (default handles the built-ins with optional ids). */\n ensureIds?: (command: Command) => Command;\n}\n\nlet seq = 0;\nconst genId = (prefix: string) => `${prefix}-${Date.now().toString(36)}${(++seq).toString(36)}${Math.random().toString(36).slice(2, 6)}`;\n\n/** Built-in commands that would otherwise get a random id inside the engine. */\nexport function withExplicitIds(command: Command): Command {\n const p = (command.payload ?? {}) as Record<string, unknown>;\n const set = (field: string, prefix: string) =>\n p[field] === undefined ? { ...command, payload: { ...p, [field]: genId(prefix) } } : command;\n switch (command.type) {\n case \"clip/split\":\n case \"clip/duplicate\":\n return set(\"newClipId\", \"clip\");\n case \"effect/add\":\n return set(\"effectId\", \"fx\");\n case \"transition/add\":\n return set(\"id\", \"tr\");\n default:\n return command;\n }\n}\n\nexport function forkProject(project: Project, options: ForkOptions = {}): RecordingProject {\n const fork = (options.createFork ?? ((doc) => createProject(doc)))(project.toJSON());\n const state = project.getState();\n fork.setPlayhead(state.playheadUs);\n fork.setSelection([...state.selection]);\n const ensure = options.ensureIds ?? withExplicitIds;\n const recorded: Command[] = [];\n let depth = 0;\n let buffer: Command[] = [];\n\n return {\n ...fork,\n get recorded() {\n return recorded;\n },\n dispatch(command) {\n const explicit = ensure(command as Command);\n const before = fork.getState().doc;\n fork.dispatch(explicit);\n if (fork.getState().doc === before) return; // no-op: nothing to replay\n if (depth > 0) buffer.push(explicit);\n else recorded.push(explicit);\n },\n transaction(fn, label) {\n if (depth > 0) {\n fn();\n return;\n }\n depth = 1;\n buffer = [];\n try {\n fork.transaction(fn, label);\n recorded.push(...buffer);\n } finally {\n depth = 0;\n buffer = [];\n }\n },\n };\n}\n\nexport type CommitResult = { ok: true; applied: number } | { ok: false; error: string };\n\n/** Replay a fork's commands onto the real project as one undoable step. */\nexport function commitFork(project: Project, fork: RecordingProject, label?: string): CommitResult {\n if (fork.recorded.length === 0) return { ok: true, applied: 0 };\n try {\n project.transaction(() => {\n for (const command of fork.recorded) project.dispatch(command);\n }, label);\n return { ok: true, applied: fork.recorded.length };\n } catch (err) {\n return {\n ok: false,\n error: `The project changed while the assistant was working, so its edit no longer applies (${(err as Error)?.message ?? err}). Ask again.`,\n };\n }\n}\n","import type { Command, Project, ProjectDocument } from \"@miraiclip/core\";\nimport { describeForAssistant } from \"./state.js\";\nimport { commitFork, forkProject, type CommitResult, type ForkOptions } from \"./fork.js\";\nimport { editorTools, type AssistantTool } from \"./tools.js\";\nimport type { ChatMessage, ChatModel, ChatUsage, ToolCall } from \"./types.js\";\n\nexport interface AssistantOptions {\n model: ChatModel;\n /** Default `editorTools()`. Add your own (audio, captions, stock media…). */\n tools?: AssistantTool[];\n /** Extra system instructions (brand voice, house rules). */\n instructions?: string;\n /** Model round-trips per request (default 12). */\n maxSteps?: number;\n /** Model id when the adapter serves several. */\n modelId?: string;\n maxOutputTokens?: number;\n /** Vendor request fields, passed through. */\n params?: Record<string, unknown>;\n fork?: ForkOptions;\n}\n\nexport type AssistantEvent =\n | { type: \"text\"; delta: string }\n | { type: \"tool-start\"; call: ToolCall }\n | { type: \"tool-end\"; call: ToolCall; ok: boolean; changes?: string[]; error?: string }\n | { type: \"step\"; index: number };\n\nexport interface TurnOptions {\n /** Earlier messages of this conversation (`turn.messages` from the last turn). */\n history?: readonly ChatMessage[];\n /** What the user is looking at, e.g. \"Selected: clip t-1. Playhead: 4.2s.\" */\n context?: string;\n /** \"auto\" (default) commits when the request finishes; \"review\" waits for `turn.apply()`. */\n apply?: \"auto\" | \"review\";\n signal?: AbortSignal;\n onEvent?: (event: AssistantEvent) => void;\n /** History label for the undo step (default \"Assistant: <request>\"). */\n label?: string;\n}\n\nexport interface AssistantTurn {\n /** The model's final answer to the user. */\n reply: string;\n /** Human-readable list of what the turn changed (empty when nothing). */\n changes: string[];\n /** The commands the turn makes, in order (replayed onto the project on apply). */\n commands: readonly Command[];\n /**\n * applied: committed as one undo step. review: waiting for apply()/discard().\n * no-changes: nothing to apply. failed / canceled: the project wasn't touched.\n */\n status: \"applied\" | \"review\" | \"no-changes\" | \"failed\" | \"canceled\";\n error?: string;\n /** The project as the turn left it (for previews in review mode). */\n preview: ProjectDocument;\n /** The conversation so far, without the system prompt: pass back as `history`. */\n messages: ChatMessage[];\n usage: Required<ChatUsage>;\n /** Commit a reviewed turn (no-op once applied). */\n apply(): CommitResult;\n discard(): void;\n}\n\nexport interface Assistant {\n readonly tools: readonly AssistantTool[];\n run(project: Project, request: string, options?: TurnOptions): Promise<AssistantTurn>;\n}\n\nconst MAX_TOOL_RESULT = 20_000;\nconst MAX_OLD_TOOL_RESULT = 2_000;\n\nexport const DEFAULT_INSTRUCTIONS = `You are the editing assistant inside a video editor. You change the user's project by calling tools; every change you make lands as ONE undo step when you finish, so act confidently.\n\nHow to work:\n- The current project is summarized below. Clip, track and asset ids there are what tools expect. Call get_state to re-read it after big changes.\n- Prefer the high-level tools when they fit (add_transition, animate_clip, add_effect, set_effects_enabled, set_background, trim_clip, set_keyframes, close_gaps, and any audio or media tools). Call tools directly; apply_commands takes only editing commands like \"clip/add\", never tool names. Use apply_commands for everything else, batching related commands; look up a command's payload with get_command_schema the first time you use it, and use only the fields it lists.\n- Fading a picture (text, image, logo, video) in or out is animate_clip (in / out: fade). fadeInUs / fadeOutUs are audio fades. \"Fade the video in at the start / out at the end\" means the first clip's entrance and the last clip's exit.\n- Constant values are set directly with clip/set-property: rotation (\"rotate 45°\", \"tilt\"), volume (\"lower to 30%\", \"louder\"), position, size, opacity. Only values that CHANGE over a time range (\"duck the music between 10 and 15 s\", \"fade to silence between 18 and 20 s\", \"spin one full turn\", \"pan across\") are keyframes: set_keyframes, with times in timeline seconds. Remove an animation with keyframe/clear.\n- \"Cuts\" are the ones listed in the project summary; use their times (e.g. one sound per cut).\n- \"Add N more seconds of footage\" adds a new clip (clip/add with trimStartUs for the source point) after the last one; it does not stretch an existing clip.\n- Caption looks (box behind the text, outline, shadow, colors, word preset) are the caption clip's style (clip/set-property { style }).\n- \"The whole video\" means from 0 to the composition length (trim_clip startSeconds / endSeconds).\n- A solid color background behind everything is set_background (add, recolor, remove). Other html clips are recolored through the params their template uses (shown in the clip details). A new track goes on top unless track/add gets index 0 (the bottom).\n- \"Replace X with Y\" removes X and adds Y in the same turn, whichever tool adds Y (audio tools take replaceClipId, which does both).\n- Solo / mute / lock / hide a track with track/set-property (solo, muted, locked, hidden). \"Solo X\" is solo: true on X, not muting the others.\n- Relative requests (\"bigger\", \"louder\", \"a bit brighter\", \"twice as big\") start from the current values in the clip details below: make a visible change in the asked direction (about 25% for \"bigger\"/\"smaller\", ×2 for \"twice\").\n- When something is selected, \"this\", \"it\", \"the clip\" and any request that names no target mean ONLY the selection, even with words like \"at the end\" (the end of that clip). Edit nothing else. \"Here\" / \"now\" / \"this point\" mean the playhead. \"Clips\" without a kind mean the video clips on the main video track.\n- \"Again\" / \"also\" / \"another\" mean keep the original and add a copy (clip/duplicate, or clip/add with the same asset); never move the original. \"Instead\" means move or replace.\n- Removing a clip leaves a gap; when asked to close it, also run close_gaps (or trim_clip with ripple).\n- Commands use integer microseconds (1 second = 1000000). High-level tools take seconds.\n- Positions (transform x, y) are fractions of the frame: 0.5, 0.5 is the center.\n- Only reference media that exists in the project or that a tool returned. Never invent file URLs.\n- If a tool fails, read the error, fix the input and retry. A failed apply_commands batch applied NONE of its commands: resend all of them, corrected. If something can't be done, say why.\n- If the request is ambiguous in a way that matters, ask one short question instead of guessing.\n\nWhen you're done, reply in one to three short sentences: what you changed, in plain words (times in seconds, names over ids). Describe only edits your tools reported as applied; if a tool says something changed nothing or failed, fix it or say so. No markdown headings.`;\n\nexport function createAssistant(options: AssistantOptions): Assistant {\n const tools = options.tools ?? editorTools();\n const byName = new Map(tools.map((t) => [t.name, t]));\n const specs = tools.map(({ name, description, inputSchema }) => ({ name, description, inputSchema }));\n const maxSteps = options.maxSteps ?? 12;\n\n return {\n tools,\n async run(project, request, turn = {}) {\n const fork = forkProject(project, options.fork);\n const emit = turn.onEvent ?? (() => {});\n const usage = { inputTokens: 0, outputTokens: 0 };\n const changes: string[] = [];\n const history = trimHistory(turn.history ?? []);\n const added: ChatMessage[] = [{ role: \"user\", content: request }];\n const system = [\n DEFAULT_INSTRUCTIONS,\n options.instructions?.trim(),\n `Current project:\\n${describeForAssistant(fork.toJSON())}`,\n turn.context?.trim() ? `What the user is looking at: ${turn.context.trim()}` : undefined,\n selectionNote(fork.toJSON(), fork.getState().selection),\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n let reply = \"\";\n let status: AssistantTurn[\"status\"] = \"no-changes\";\n let error: string | undefined;\n\n try {\n for (let step = 0; ; step++) {\n if (step >= maxSteps) {\n reply = (reply ? `${reply}\\n\\n` : \"\") + `I stopped after ${maxSteps} steps; what I finished is applied. Ask me to continue if there's more.`;\n break;\n }\n emit({ type: \"step\", index: step });\n const response = await options.model.complete(\n {\n messages: [{ role: \"system\", content: system }, ...history, ...added],\n tools: specs,\n ...(options.modelId ? { model: options.modelId } : {}),\n ...(options.maxOutputTokens ? { maxOutputTokens: options.maxOutputTokens } : {}),\n ...(options.params ? { params: options.params } : {}),\n },\n { ...(turn.signal ? { signal: turn.signal } : {}), onText: (delta) => emit({ type: \"text\", delta }) },\n );\n usage.inputTokens += response.usage?.inputTokens ?? 0;\n usage.outputTokens += response.usage?.outputTokens ?? 0;\n added.push({ role: \"assistant\", content: response.content, ...(response.toolCalls.length ? { toolCalls: response.toolCalls } : {}) });\n if (response.toolCalls.length === 0) {\n reply = response.content.trim();\n break;\n }\n for (const call of response.toolCalls) {\n if (turn.signal?.aborted) throw abortError();\n emit({ type: \"tool-start\", call });\n const out = await runTool(byName.get(call.name), call, fork, turn.signal);\n if (out.ok && out.changes?.length) changes.push(...out.changes);\n emit({\n type: \"tool-end\",\n call,\n ok: out.ok,\n ...(out.ok && out.changes?.length ? { changes: out.changes } : {}),\n ...(!out.ok ? { error: short(out.error) } : {}),\n });\n added.push({ role: \"tool\", toolCallId: call.id, name: call.name, content: cap(out.ok ? out.result ?? { ok: true } : { ok: false, error: out.error }, MAX_TOOL_RESULT) });\n }\n }\n status = fork.recorded.length === 0 ? \"no-changes\" : turn.apply === \"review\" ? \"review\" : \"applied\";\n } catch (err) {\n status = turn.signal?.aborted || (err as Error)?.name === \"AbortError\" ? \"canceled\" : \"failed\";\n error = (err as Error)?.message ?? String(err);\n }\n\n let committed = false;\n let discarded = false;\n const label = turn.label ?? `Assistant: ${request.length > 40 ? `${request.slice(0, 39)}…` : request}`;\n const apply = (): CommitResult => {\n if (committed) return { ok: true, applied: 0 };\n if (discarded) return { ok: false, error: \"This edit was discarded.\" };\n if (status === \"failed\" || status === \"canceled\") return { ok: false, error: error ?? status };\n const result = commitFork(project, fork, label);\n if (result.ok) committed = true;\n return result;\n };\n if (status === \"applied\") {\n const result = apply();\n if (!result.ok) {\n status = \"failed\";\n error = result.error;\n }\n }\n\n return {\n reply,\n changes,\n commands: fork.recorded,\n status,\n ...(error !== undefined ? { error } : {}),\n preview: fork.toJSON(),\n messages: [...history, ...added],\n usage,\n apply,\n discard() {\n if (!committed) discarded = true;\n },\n };\n },\n };\n}\n\nasync function runTool(tool: AssistantTool | undefined, call: ToolCall, project: Project, signal?: AbortSignal) {\n if (!tool) return { ok: false as const, error: `unknown tool \"${call.name}\"` };\n if (\"__invalidArguments\" in call.arguments) return { ok: false as const, error: \"the tool arguments weren't valid JSON; send a JSON object\" };\n try {\n return await tool.run(call.arguments, { project, ...(signal ? { signal } : {}) });\n } catch (err) {\n if ((err as Error)?.name === \"AbortError\") throw err;\n return { ok: false as const, error: (err as Error)?.message ?? String(err) };\n }\n}\n\nfunction cap(value: unknown, max: number): string {\n const text = typeof value === \"string\" ? value : JSON.stringify(value);\n return text.length > max ? `${text.slice(0, max)}… [truncated ${text.length - max} chars]` : text;\n}\n\nconst short = (e: unknown) => {\n const text = typeof e === \"string\" ? e : JSON.stringify(e);\n return text.length > 300 ? `${text.slice(0, 299)}…` : text;\n};\n\n/**\n * Earlier turns keep their shape but not their bulky tool output. A turn cut\n * short (canceled, failed) can leave tool calls without results, which\n * vendors reject: those get a \"not run\" result.\n */\nfunction trimHistory(history: readonly ChatMessage[]): ChatMessage[] {\n const answered = new Set(history.flatMap((m) => (m.role === \"tool\" ? [m.toolCallId] : [])));\n const out: ChatMessage[] = [];\n for (const m of history) {\n if (m.role === \"system\") continue;\n if (m.role === \"tool\") {\n out.push(m.content.length > MAX_OLD_TOOL_RESULT ? { ...m, content: `${m.content.slice(0, MAX_OLD_TOOL_RESULT)}… [truncated]` } : m);\n continue;\n }\n out.push(m);\n if (m.role === \"assistant\") {\n for (const call of m.toolCalls ?? []) {\n if (!answered.has(call.id)) out.push({ role: \"tool\", toolCallId: call.id, name: call.name, content: '{\"ok\":false,\"error\":\"not run: the request was interrupted\"}' });\n }\n }\n }\n return out;\n}\n\nfunction abortError() {\n const err = new Error(\"canceled\");\n err.name = \"AbortError\";\n return err;\n}\n\n/** The selection, stated as a scope rule right before the request (models drift to \"all clips\" otherwise). */\nfunction selectionNote(doc: ProjectDocument, selection: readonly string[]): string | undefined {\n const clips = selection.map((id) => doc.clips[id]).filter((c): c is NonNullable<typeof c> => !!c);\n if (!clips.length) return undefined;\n const list = clips.map((c) => `${c.id} (${c.kind}, ${Number((c.startUs / 1e6).toFixed(2))}–${Number(((c.startUs + c.durationUs) / 1e6).toFixed(2))}s)`).join(\", \");\n return `Selected: ${list}. In this request, \"this\", \"it\", \"the clip\" and anything that names no target mean ONLY ${clips.map((c) => c.id).join(\", \")}. Leave every other clip alone.`;\n}\n","import { defineChatModel, type ChatModel, type ChatRequest, type ChatResponse, type ToolCall } from \"./types.js\";\n\nexport type ScriptStep =\n | string\n | { text?: string; toolCalls?: (Omit<ToolCall, \"id\"> & { id?: string })[] }\n | ((request: ChatRequest, index: number) => ScriptStep);\n\n/**\n * A model that answers from a script: for tests, demos and offline\n * development. Each `complete` call takes the next step; a string is a final\n * text answer, an object can call tools. Requests are kept in `requests`.\n */\nexport function scriptedChatModel(steps: ScriptStep[], options: { id?: string } = {}): ChatModel & { requests: ChatRequest[] } {\n const requests: ChatRequest[] = [];\n let i = 0;\n const model = defineChatModel({\n id: options.id ?? \"scripted\",\n label: \"Scripted model\",\n async complete(request: ChatRequest, opts: { onText?: (delta: string) => void } = {}): Promise<ChatResponse> {\n requests.push(structuredClone(request));\n let step: ScriptStep = steps[Math.min(i, steps.length - 1)] ?? \"Done.\";\n while (typeof step === \"function\") step = step(request, i);\n i++;\n const s = typeof step === \"string\" ? { text: step } : step;\n if (s.text) opts.onText?.(s.text);\n const toolCalls = (s.toolCalls ?? []).map((c, n) => ({ id: c.id ?? `call_${i}_${n}`, name: c.name, arguments: c.arguments }));\n return { content: s.text ?? \"\", toolCalls, finish: toolCalls.length ? \"tool_calls\" : \"stop\", usage: { inputTokens: 10, outputTokens: 5 } };\n },\n });\n return Object.assign(model, { requests });\n}\n"],"mappings":"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","names":["json","FINISH","usage","json","readStream","FINISH","usage","json","mine","target","n","describeAnimation","findCuts","findCuts","describeAnimation","commands","out","usage","n"]}
|