@firstlovecenter/ai-chat 0.5.0 → 0.6.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/tools/types.ts","../../src/server/agent.ts","../../src/server/providers/claude.ts","../../src/server/providers/schema.ts","../../src/server/providers/gemini.ts","../../src/server/providers/index.ts","../../src/server/narrators/_vertex.ts","../../src/server/narrators/claude.ts","../../src/server/narrators/gemini.ts","../../src/server/narrators/grok.ts","../../src/server/narrators/index.ts","../../src/server/routes/agent-custom.ts","../../src/server/vercel-adapter.ts","../../src/server/routes/agent-vercel.ts","../../src/server/routes/chat-sessions.ts","../../src/server/routes/admin-settings.ts","../../src/server/configure.ts"],"names":["tool","AnthropicVertex","parts","vertexHost","patchVertexBuildRequestSync","MODEL_ENDPOINTS","VERTEX_DEFAULT_VERSION","isObj","NARRATIVE_SYSTEM","safeReadText","randomUUID","err","jsonError","defaultGenerateSessionId","StreamData","createVertexAnthropic","createVertex","streamText","toolProviders"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Tool typing for the agent loop.\n *\n * `ToolContext<S>` is the per-request \"session\" handed to every tool. It\n * carries the resolved Scope (so tools can inject scope filters without\n * trusting their own arguments) and a per-session view suffix (so SQL-ish\n * tools can point the LLM at session-scoped views). The Scope shape itself\n * is opaque to this package — `S` is whatever the host configures.\n *\n * `ToolDefinition` is what we hand to the model adapter plus the function\n * that backs the tool name. The agent loop dispatches on `name` and calls\n * `execute(input, ctx)`; the result is JSON-serialised back to the model.\n */\n\nexport type ToolContext<S = unknown> = {\n /** Host-supplied scope (RBAC / tenancy). The package never inspects the shape. */\n scope: S;\n /** Stable per-conversation id (string). Tools may use this for session-scoped views. */\n sessionId: string;\n /** Short human label for diagnostics — e.g. \"Ghana\", \"all 8 countries\". */\n scopeSummary: string;\n /** Number of structured tool calls made before `present` was invoked. */\n toolCallCount: number;\n};\n\nexport type ToolSchema = {\n name: string;\n description: string;\n /** JSON Schema. The package's Vertex Gemini adapter normalises this; the Vercel adapter converts to Zod. */\n input_schema: Record<string, unknown>;\n};\n\nexport type ToolResult =\n | { ok: true; data: unknown }\n | { ok: false; error: { code: string; message: string } };\n\nimport type { ZodType } from 'zod';\n\nexport type ToolDefinition<I = unknown, S = unknown> = {\n schema: ToolSchema;\n /**\n * Optional Zod schema for the same input. Required by the Vercel AI SDK\n * route (which needs Zod to feed `tool({ parameters })`); the custom\n * SSE route ignores it. Tools registered without a `zodSchema` will\n * cause `buildVercelTools` to throw at config time.\n */\n zodSchema?: ZodType<I>;\n execute(input: I, ctx: ToolContext<S>): Promise<ToolResult>;\n};\n\n/** The terminal tool that closes the agent loop. The host's tool registry MUST include it. */\nexport const TERMINAL_TOOL_NAME = 'present';\n\nexport function ok(data: unknown): ToolResult {\n return { ok: true, data };\n}\n\nexport function err(code: string, message: string): ToolResult {\n return { ok: false, error: { code, message } };\n}\n\n// ---------------------------------------------------------------------------\n// Block types — what `present` returns and what AnswerBlocks renders\n// ---------------------------------------------------------------------------\n\nexport type ChartSpec = {\n type: 'line' | 'bar' | 'stacked_bar' | 'pie';\n x: string;\n y: string | string[];\n series?: string;\n};\n\nexport type Block =\n | { kind: 'paragraph_brief'; topic: string; key_facts: string[] }\n | { kind: 'list'; style: 'bullet' | 'numbered'; items: string[]; title?: string }\n | { kind: 'chart'; title: string; spec: ChartSpec; data: Array<Record<string, unknown>> }\n | { kind: 'table'; title: string; columns: string[]; rows: unknown[][] }\n | { kind: 'callout'; tone: 'info' | 'warn' | 'success'; text: string };\n\nexport type PresentPayload = {\n blocks: Block[];\n raw_numbers: Record<string, number | string>;\n};\n\n// ---------------------------------------------------------------------------\n// SystemBlock — system prompt segments (provider-agnostic cache hint)\n// ---------------------------------------------------------------------------\n\nexport type SystemBlock = {\n text: string;\n /**\n * Mark for ephemeral prompt caching where the provider supports it.\n * Anthropic translates this to `cache_control: ephemeral`; Gemini ignores\n * it (Vertex auto-caches stable prefixes). Both still see the same text.\n */\n cached?: boolean;\n};\n","/**\n * Agent tool loop.\n *\n * Drives an injected `ToolProvider` (Claude on Vertex, Gemini on Vertex,\n * or any future adapter that satisfies the contract) with a host-supplied\n * tool catalogue until the model invokes the terminal `present` tool (or\n * hits a hard stop without calling it). Returns the structured\n * `PresentPayload`; the prose narrator pass happens in the route handler.\n *\n * Caching: the system prompt blocks are passed through as the host built\n * them. Blocks marked `cached: true` become Anthropic ephemeral cache\n * markers; Gemini ignores the flag and relies on Vertex's automatic prefix\n * caching. Either way a follow-up question within the cache TTL only pays\n * for the question + tool turns.\n *\n * This package's loop is project-agnostic: tools, prompts, and the\n * provider instance are all injected via `AgentInput`. The host owns the\n * registry (`ToolsPort.tools`), the system blocks (`ToolsPort.buildSystemBlocks`),\n * and the constructed provider (resolved through `toolProviders[id].createProvider`).\n */\nimport type {\n PresentPayload,\n SystemBlock,\n ToolContext,\n ToolDefinition\n} from './tools/types';\nimport { TERMINAL_TOOL_NAME } from './tools/types';\nimport type {\n NormalizedMessage,\n NormalizedToolResult,\n ToolProvider\n} from './providers/types';\n\nexport const DEFAULT_MAX_TOOL_TURNS = 12;\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 4096;\n\nexport type AgentResult =\n | { ok: true; structured: PresentPayload; toolCallCount: number; transcript: TranscriptEntry[] }\n | { ok: false; error: { code: string; message: string }; transcript: TranscriptEntry[] };\n\nexport type TranscriptEntry =\n | { kind: 'user'; text: string }\n | { kind: 'assistant_text'; text: string }\n | { kind: 'tool_use'; name: string; input: unknown }\n | { kind: 'tool_result'; name: string; result: unknown };\n\nexport type AgentInput<S = unknown> = {\n question: string;\n ctx: ToolContext<S>;\n /** Injected tool registry (host-supplied via ToolsPort). MUST include the terminal `present` tool. */\n tools: Record<string, ToolDefinition<unknown, S>>;\n /** Pre-built system blocks (host-supplied via ToolsPort.buildSystemBlocks). */\n systemBlocks: SystemBlock[];\n /** Constructed ToolProvider — caller resolves the right one via toolProviders[id].createProvider({...}). */\n provider: ToolProvider;\n /** Optional caps. Default both. */\n maxToolTurns?: number;\n maxOutputTokens?: number;\n};\n\nexport async function runAgent<S = unknown>(input: AgentInput<S>): Promise<AgentResult> {\n const provider = input.provider;\n const maxToolTurns = input.maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;\n const maxOutputTokens = input.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;\n\n const transcript: TranscriptEntry[] = [];\n transcript.push({ kind: 'user', text: input.question });\n\n const messages: NormalizedMessage[] = [{ role: 'user', text: input.question }];\n const system = input.systemBlocks;\n const toolSchemas = Object.values(input.tools).map((t) => t.schema);\n\n let toolCallCount = 0;\n let presentPayload: PresentPayload | null = null;\n\n for (let turn = 0; turn < maxToolTurns; turn++) {\n const response = await provider.runTurn({\n system,\n tools: toolSchemas,\n messages,\n maxOutputTokens\n });\n\n if (response.text) {\n transcript.push({ kind: 'assistant_text', text: response.text });\n }\n\n if (response.toolCalls.length === 0) {\n // Model ended its turn without a tool call. If we already had a\n // present payload (shouldn't happen — present terminates the loop\n // below), use it.\n if (presentPayload) break;\n\n // Fallback: model emitted text but never reached present(). Most\n // commonly happens for advisory / strategic questions that don't\n // map to any data tool (\"what should we do to ...?\"). Wrap the\n // text as a paragraph_brief block so the user always gets the\n // model's answer instead of a generic \"try rephrasing\" error.\n // The SELF_VERIFY_REQUIRED gate still fires when present() is\n // called explicitly — this synthetic path runs only when the\n // model chose not to use any tools at all.\n const text = (response.text ?? '').trim();\n if (text) {\n const topic =\n input.question.length > 80\n ? input.question.slice(0, 77) + '...'\n : input.question;\n presentPayload = {\n blocks: [\n {\n kind: 'paragraph_brief',\n topic,\n key_facts: [text]\n }\n ],\n raw_numbers: {}\n };\n break;\n }\n\n // No tool calls AND no text — genuine dead end. Surface the error.\n return {\n ok: false,\n error: {\n code: 'AGENT_NO_PRESENT',\n message: 'The agent produced no response. Try rephrasing.'\n },\n transcript\n };\n }\n\n messages.push({\n role: 'assistant',\n text: response.text,\n toolCalls: response.toolCalls,\n providerData: response.providerData\n });\n\n const toolResults: NormalizedToolResult[] = [];\n\n for (const tc of response.toolCalls) {\n transcript.push({ kind: 'tool_use', name: tc.name, input: tc.input });\n const tool = input.tools[tc.name];\n if (!tool) {\n const errResult = {\n ok: false as const,\n error: { code: 'UNKNOWN_TOOL', message: `Unknown tool: ${tc.name}` }\n };\n transcript.push({ kind: 'tool_result', name: tc.name, result: errResult });\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: true,\n content: JSON.stringify(errResult.error)\n });\n continue;\n }\n const result = await tool.execute(tc.input as unknown, {\n ...input.ctx,\n toolCallCount\n });\n transcript.push({ kind: 'tool_result', name: tc.name, result });\n toolCallCount += 1;\n\n if (tc.name === TERMINAL_TOOL_NAME && result.ok) {\n // Enforce: ≥ 2 prior tool calls (primary + cross-check) before\n // present. toolCallCount has been incremented for present, so a\n // count < 3 means there were < 2 prior calls.\n if (toolCallCount < 3) {\n const violation = {\n code: 'SELF_VERIFY_REQUIRED',\n message:\n 'Per FR-8.3 you must run at least one CROSS-CHECK tool call (a different metric, a different period, or a run_sql sanity-check) before present. Make that extra call now, then call present again.'\n };\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: true,\n content: JSON.stringify(violation)\n });\n continue;\n }\n presentPayload = result.data as PresentPayload;\n break;\n }\n\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: !result.ok,\n content: JSON.stringify(result.ok ? result.data : result.error)\n });\n }\n\n if (presentPayload) break;\n messages.push({ role: 'tool', results: toolResults });\n }\n\n if (!presentPayload) {\n return {\n ok: false,\n error: {\n code: 'AGENT_TURN_LIMIT',\n message: `Agent exceeded the ${maxToolTurns}-turn budget without calling present().`\n },\n transcript\n };\n }\n\n // Salvage: the model called present() but produced a payload whose\n // every block is empty (the user sees a row of empty placeholder\n // boxes). Happens when the model is forced through SELF_VERIFY_REQUIRED\n // for an advisory question that doesn't actually have data to back —\n // it satisfies the schema with empty strings. Recover by replacing\n // the payload with a synthetic paragraph_brief built from the most\n // recent assistant text in the transcript, falling back to the older\n // `model emitted text but no present()` path. The user gets the\n // model's actual reasoning instead of empty boxes.\n if (allBlocksEmpty(presentPayload.blocks)) {\n const lastAssistantText = [...transcript]\n .reverse()\n .find((e) => e.kind === 'assistant_text') as\n | { kind: 'assistant_text'; text: string }\n | undefined;\n const text = lastAssistantText?.text.trim();\n if (text) {\n const topic =\n input.question.length > 80\n ? input.question.slice(0, 77) + '...'\n : input.question;\n presentPayload = {\n blocks: [\n {\n kind: 'paragraph_brief',\n topic,\n key_facts: [text]\n }\n ],\n raw_numbers: presentPayload.raw_numbers ?? {}\n };\n }\n }\n\n return { ok: true, structured: presentPayload, toolCallCount, transcript };\n}\n\n/**\n * True when every block in the present payload is functionally empty —\n * no rendered content the user can see. Used to detect models that\n * satisfy the present() schema with placeholder strings after being\n * forced through SELF_VERIFY_REQUIRED on a question that has no data\n * answer. Each block kind has its own emptiness rule.\n */\nfunction allBlocksEmpty(blocks: PresentPayload['blocks']): boolean {\n if (blocks.length === 0) return true;\n return blocks.every((b) => {\n if (b.kind === 'paragraph_brief') {\n return b.key_facts.length === 0 || b.key_facts.every((f) => !f.trim());\n }\n if (b.kind === 'list') {\n return b.items.length === 0 || b.items.every((i) => !i.trim());\n }\n if (b.kind === 'callout') {\n return !b.text.trim();\n }\n if (b.kind === 'chart') {\n return b.data.length === 0;\n }\n if (b.kind === 'table') {\n return b.rows.length === 0;\n }\n return false;\n });\n}\n","/**\n * Claude (Anthropic Messages API on GCP Vertex) — `ToolProvider` adapter.\n *\n * Wraps `AnthropicVertex` with the same `buildRequest` sync-patch the host\n * applies, then translates the agent loop's normalized message log to\n * Anthropic's `MessageParam[]` shape on the way in, and the response's\n * `ContentBlock[]` back to `{ text, toolCalls, stopReason }` on the way\n * out. Ephemeral cache markers are applied to system blocks where the\n * agent loop opted in, so the `system + schema + semantic-layer +\n * scope-summary` prefix stays cached across follow-up turns.\n *\n * Credentials come in as a host-supplied `GoogleAuth` instance; the\n * package never reads `process.env.GCP_*`.\n */\nimport { AnthropicVertex } from '@anthropic-ai/vertex-sdk';\nimport type {\n ContentBlock,\n MessageParam,\n ToolUseBlock\n} from '@anthropic-ai/sdk/resources/messages';\nimport type { GoogleAuth } from 'google-auth-library';\nimport type {\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n ToolProvider\n} from './types';\n\n/**\n * `TextBlockParam` in @anthropic-ai/sdk@0.50 doesn't include\n * `cache_control` in its types, but the production API accepts it on the\n * standard messages endpoint. Local widened type so callers don't need\n * `as any` everywhere.\n */\ntype CachedTextBlock = {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n};\n\nexport type ClaudeProviderOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Vertex region (e.g. 'us-east5' or 'global'). */\n location: string;\n /** Model id pinned by the host (e.g. 'claude-opus-4-7@20250514'). */\n modelId: string;\n};\n\nexport class ClaudeToolProvider implements ToolProvider {\n readonly id = 'claude' as const;\n private client: AnthropicVertex;\n private modelId: string;\n\n constructor(opts: ClaudeProviderOpts) {\n this.modelId = opts.modelId;\n this.client = new AnthropicVertex({\n projectId: opts.projectId,\n region: opts.location,\n googleAuth: opts.auth\n });\n patchVertexBuildRequestSync(this.client);\n }\n\n async runTurn(input: AgentTurnInput): Promise<AgentTurn> {\n // Anthropic caps cache_control markers at 4 per request. If the host\n // (or our role-prompt wrapper) marks more than 4 system blocks\n // `cached: true`, keep the first 4 and silently drop the cache hint\n // from any beyond — better than letting the request fail. The first\n // 4 markers are also where caching has the biggest hit rate, since\n // earlier blocks tend to be the most stable across requests.\n let cacheMarkersUsed = 0;\n const MAX_CACHE_MARKERS = 4;\n const system: CachedTextBlock[] = input.system.map((b) => {\n if (b.cached && cacheMarkersUsed < MAX_CACHE_MARKERS) {\n cacheMarkersUsed++;\n return {\n type: 'text',\n text: b.text,\n cache_control: { type: 'ephemeral' as const }\n };\n }\n return { type: 'text', text: b.text };\n });\n const messages = toAnthropicMessages(input.messages);\n\n const response = await this.client.messages.create({\n model: this.modelId,\n max_tokens: input.maxOutputTokens,\n system,\n tools: input.tools as unknown as any[],\n messages\n });\n\n return fromAnthropicResponse(response);\n }\n}\n\n/** Factory matching the package's provider-init contract. */\nexport function createClaudeProvider(opts: ClaudeProviderOpts): ToolProvider {\n return new ClaudeToolProvider(opts);\n}\n\nexport function toAnthropicMessages(\n messages: NormalizedMessage[]\n): MessageParam[] {\n const out: MessageParam[] = [];\n for (const msg of messages) {\n if (msg.role === 'user') {\n out.push({ role: 'user', content: msg.text });\n } else if (msg.role === 'assistant') {\n const blocks: ContentBlock[] = [];\n if (msg.text) {\n blocks.push({ type: 'text', text: msg.text } as ContentBlock);\n }\n for (const tc of msg.toolCalls) {\n blocks.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.name,\n input: tc.input\n } as unknown as ContentBlock);\n }\n out.push({ role: 'assistant', content: blocks });\n } else {\n // tool results — Anthropic models them as a `user` turn whose content\n // is one tool_result block per call.\n const content = msg.results.map((r) => ({\n type: 'tool_result' as const,\n tool_use_id: r.toolCallId,\n is_error: r.isError,\n content: r.content\n }));\n out.push({ role: 'user', content: content as unknown as ContentBlock[] });\n }\n }\n return out;\n}\n\nexport function fromAnthropicResponse(response: {\n content: ContentBlock[];\n stop_reason?: string | null;\n}): AgentTurn {\n const textParts: string[] = [];\n const toolCalls: AgentTurn['toolCalls'] = [];\n for (const block of response.content) {\n if (block.type === 'text') {\n textParts.push(block.text);\n } else if (block.type === 'tool_use') {\n const tu = block as ToolUseBlock;\n toolCalls.push({\n id: tu.id,\n name: tu.name,\n input: (tu.input ?? {}) as Record<string, unknown>\n });\n }\n }\n return {\n text: textParts.join(''),\n toolCalls,\n stopReason: normalizeStopReason(response.stop_reason)\n };\n}\n\nfunction normalizeStopReason(reason: string | null | undefined): AgentTurn['stopReason'] {\n switch (reason) {\n case 'tool_use':\n return 'tool_use';\n case 'end_turn':\n return 'end_turn';\n case 'max_tokens':\n return 'max_tokens';\n default:\n return 'other';\n }\n}\n\n// ---------------------------------------------------------------------------\n// AnthropicVertex `buildRequest` sync-patch\n// ---------------------------------------------------------------------------\n//\n// Works around the ABI mismatch between `@anthropic-ai/vertex-sdk@0.16.0`\n// (declares `buildRequest` as async) and `@anthropic-ai/sdk@0.50.4`\n// (consumes it synchronously). Without this patch, the destructured\n// `{ req, url, timeout }` returns `undefined`s and the SDK throws\n// \"Cannot read properties of undefined (reading 'headers')\" before any\n// HTTP request is sent.\n//\n// The override mirrors the upstream override's body / path rewriting\n// (split into `rawPredict` vs `streamRawPredict`) but returns the parent\n// synchronously instead of wrapping in a Promise.\n\nconst MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);\nconst VERTEX_DEFAULT_VERSION = 'vertex-2023-10-16';\n\nfunction isObj(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction patchVertexBuildRequestSync(client: AnthropicVertex): void {\n const proto = Object.getPrototypeOf(client) as Record<string, unknown>;\n const grandparent = Object.getPrototypeOf(proto) as {\n buildRequest: (...args: unknown[]) => unknown;\n };\n proto.buildRequest = function patchedBuildRequest(\n this: AnthropicVertex & { projectId?: string; region?: string },\n options: { method?: string; path?: string; body?: unknown },\n extra?: unknown\n ) {\n if (isObj(options.body)) {\n options.body = { ...options.body };\n }\n if (isObj(options.body) && !options.body.anthropic_version) {\n options.body.anthropic_version = VERTEX_DEFAULT_VERSION;\n }\n if (\n options.path &&\n MODEL_ENDPOINTS.has(options.path) &&\n options.method === 'post' &&\n isObj(options.body)\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n const model = options.body.model;\n options.body.model = undefined;\n const stream = options.body.stream ?? false;\n const specifier = stream ? 'streamRawPredict' : 'rawPredict';\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${model}:${specifier}`;\n }\n if (\n options.path === '/v1/messages/count_tokens' ||\n (options.path === '/v1/messages/count_tokens?beta=true' && options.method === 'post')\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`;\n }\n return grandparent.buildRequest.call(this, options, extra);\n } as unknown as (typeof proto)['buildRequest'];\n}\n","/**\n * JSON Schema → Vertex Gemini \"function declaration parameters\" translator.\n *\n * Gemini accepts a subset of OpenAPI 3.0 schema for tool parameters. The\n * tool catalogue uses standard JSON Schema (which Anthropic accepts\n * verbatim) and includes a few constructs that need rewriting:\n *\n * - `oneOf` → `anyOf` (Gemini exposes the union as `anyOf`).\n * - `const` → `enum: [value]` with the matching `type`.\n * - `enum` → Vertex enforces TWO rules: every entry must be a\n * string, AND the parent `type` must be `STRING`. So:\n * • all-string enum → kept as-is (already type=string)\n * • numeric enum → dropped, replaced by `minimum`/`maximum`\n * derived from min/max of the values. The model still picks\n * from a bounded range; tools validate the exact value.\n * • boolean enum → dropped (the `boolean` type already\n * constrains the value space to {true, false}).\n * This is the closest semantics-preserving rewrite that keeps\n * Vertex from rejecting the schema.\n * - `additionalProperties` (object form): dropped — Gemini doesn't\n * model nested additionalProperties; we keep the shape declared by\n * `properties` and lose the escape hatch, which is fine for our\n * tools (none of them rely on extra keys).\n * - `type: 'array'` without explicit `items`: Gemini requires `items`,\n * so we default to `{ type: 'string' }` to keep the schema valid.\n *\n * Anything else is passed through. This translator is intentionally\n * conservative: it doesn't try to validate input or normalize names —\n * its only job is to keep Gemini's parser happy.\n */\n\ntype JsonSchema = Record<string, unknown>;\n\nexport function toGeminiSchema(schema: JsonSchema): JsonSchema {\n const out = walk(schema);\n return (out ?? { type: 'object' }) as JsonSchema;\n}\n\nfunction walk(node: unknown): unknown {\n if (Array.isArray(node)) return node.map(walk);\n if (!isObject(node)) return node;\n\n // const → enum + inferred type\n if ('const' in node) {\n const c = node.const;\n const inferred = inferConstType(c);\n const next: JsonSchema = { ...node };\n delete next.const;\n next.type = (next.type as string | undefined) ?? inferred;\n next.enum = [c];\n return walk(next);\n }\n\n const out: JsonSchema = {};\n for (const [k, v] of Object.entries(node)) {\n if (k === 'oneOf') {\n out.anyOf = (v as unknown[]).map(walk);\n continue;\n }\n if (k === 'additionalProperties') {\n // Gemini OpenAPI subset doesn't model nested additionalProperties.\n // Drop — `properties` on the parent object is still authoritative.\n continue;\n }\n if (k === 'properties' && isObject(v)) {\n const props: JsonSchema = {};\n for (const [pk, pv] of Object.entries(v)) {\n props[pk] = walk(pv);\n }\n out.properties = props;\n continue;\n }\n if (k === 'items') {\n out.items = walk(v);\n continue;\n }\n if (k === 'anyOf' || k === 'allOf') {\n out[k] = (v as unknown[]).map(walk);\n continue;\n }\n if (k === 'enum' && Array.isArray(v)) {\n // Vertex requires `enum` only on `STRING` parameters. We can't\n // just stringify the values — Vertex separately checks that the\n // declared `type` matches. Rewrite based on the value kind:\n // - all strings → keep as-is\n // - all numbers → drop enum, emit min/max instead\n // - otherwise → drop enum entirely; type alone constrains\n const allStrings = v.every((x) => typeof x === 'string');\n if (allStrings) {\n out.enum = v as string[];\n continue;\n }\n const allNumbers = v.length > 0 && v.every((x) => typeof x === 'number');\n if (allNumbers) {\n const nums = v as number[];\n out.minimum = Math.min(...nums);\n out.maximum = Math.max(...nums);\n }\n continue;\n }\n out[k] = v;\n }\n\n // Arrays must declare items; default to string when authors omit it.\n if (out.type === 'array' && out.items === undefined) {\n out.items = { type: 'string' };\n }\n\n return out;\n}\n\nfunction inferConstType(c: unknown): string {\n if (typeof c === 'string') return 'string';\n if (typeof c === 'number') return Number.isInteger(c) ? 'integer' : 'number';\n if (typeof c === 'boolean') return 'boolean';\n return 'string';\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return v != null && typeof v === 'object' && !Array.isArray(v);\n}\n","/**\n * Gemini (Vertex AI) — `ToolProvider` adapter.\n *\n * Talks to Vertex's `:generateContent` endpoint with raw fetch; pulling\n * in `@google-cloud/vertexai` solely for this would balloon the dep tree.\n *\n * Translation contract — keep the agent loop oblivious to vendor diffs:\n *\n * tools tool catalogue → `tools[0].functionDeclarations[]`,\n * each parameter schema rewritten via `toGeminiSchema`.\n *\n * system joined to one `systemInstruction.parts[].text`.\n * Gemini auto-caches stable prefixes on Vertex, so the\n * `cached` hint from the agent loop is dropped here.\n *\n * messages our `NormalizedMessage[]` becomes Gemini `Content[]`:\n * user.text → role:user / parts:[{text}]\n * assistant.text+tcs → role:model / parts:[{text}, {functionCall}, …]\n * tool.results → role:user / parts:[{functionResponse}, …]\n * Gemini's functionResponse parts are name-keyed (no\n * ID), so we surface `toolName` in NormalizedToolResult\n * and rely on call-order parity within a turn.\n *\n * response `candidates[0].content.parts[]` is split into a `text`\n * string and a `toolCalls[]` array. Gemini doesn't emit\n * stable per-call IDs, so we mint `gem_<turn>_<idx>` —\n * the agent only needs them to be unique within a turn.\n *\n * Credentials come in as a host-supplied `GoogleAuth` instance; the\n * package never reads `process.env.GCP_*`.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type {\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n NormalizedToolCall,\n ToolProvider\n} from './types';\nimport { toGeminiSchema } from './schema';\n\n/**\n * One Part in a Gemini Content. Modeled loosely so we can pass through\n * fields we don't introspect (`thoughtSignature`, `thought: true`,\n * future additions). Only the recognized shapes are read; the rest is\n * preserved verbatim when echoed back via `providerData`.\n */\ntype GeminiPart = {\n text?: string;\n thought?: boolean;\n thoughtSignature?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: Record<string, unknown> };\n};\n\ntype GeminiContent = {\n role: 'user' | 'model';\n parts: GeminiPart[];\n};\n\ntype GeminiResponse = {\n candidates?: Array<{\n content?: GeminiContent;\n finishReason?: string;\n }>;\n error?: { code?: number; message?: string; status?: string };\n};\n\nexport type GeminiProviderOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Vertex region (e.g. 'us-east5' or 'global'). */\n location: string;\n /** Model id pinned by the host (e.g. 'gemini-3.1-pro-preview'). */\n modelId: string;\n /** Test seam: lets unit tests stub the Vertex HTTP call without going over the wire. */\n fetchImpl?: typeof fetch;\n};\n\nexport class GeminiToolProvider implements ToolProvider {\n readonly id = 'gemini' as const;\n private auth: GoogleAuth;\n private projectId: string;\n private location: string;\n private modelId: string;\n private fetchImpl: typeof fetch;\n\n constructor(opts: GeminiProviderOpts) {\n this.auth = opts.auth;\n this.projectId = opts.projectId;\n this.location = opts.location;\n this.modelId = opts.modelId;\n this.fetchImpl = opts.fetchImpl ?? fetch;\n }\n\n async runTurn(input: AgentTurnInput): Promise<AgentTurn> {\n const accessToken = await this.auth.getAccessToken();\n if (!accessToken) throw new Error('Failed to obtain GCP access token');\n const url = `https://${vertexHost(this.location)}/v1/projects/${this.projectId}/locations/${this.location}/publishers/google/models/${this.modelId}:generateContent`;\n\n const body = {\n systemInstruction: {\n parts: [{ text: input.system.map((b) => b.text).join('\\n\\n') }]\n },\n contents: toGeminiContents(input.messages),\n tools: [\n {\n functionDeclarations: input.tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: toGeminiSchema(t.input_schema as Record<string, unknown>)\n }))\n }\n ],\n toolConfig: {\n functionCallingConfig: { mode: 'AUTO' }\n },\n generationConfig: {\n maxOutputTokens: input.maxOutputTokens,\n temperature: 0\n }\n };\n\n const res = await this.fetchImpl(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(body)\n });\n\n if (!res.ok) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Gemini request failed (${res.status}): ${detail}`);\n }\n\n const json = (await res.json()) as GeminiResponse;\n if (json.error) {\n throw new Error(\n `Vertex Gemini returned error: ${json.error.status ?? json.error.code ?? '??'} ${\n json.error.message ?? ''\n }`\n );\n }\n return fromGeminiResponse(json);\n }\n}\n\n/** Factory matching the package's provider-init contract. */\nexport function createGeminiProvider(opts: GeminiProviderOpts): ToolProvider {\n return new GeminiToolProvider(opts);\n}\n\n/**\n * Build the Vertex AI host for a given location. Most regions resolve\n * to `{region}-aiplatform.googleapis.com`; the special `global`\n * location uses the un-prefixed `aiplatform.googleapis.com` endpoint.\n */\nexport function vertexHost(location: string): string {\n return location === 'global'\n ? 'aiplatform.googleapis.com'\n : `${location}-aiplatform.googleapis.com`;\n}\n\nexport function toGeminiContents(messages: NormalizedMessage[]): GeminiContent[] {\n const out: GeminiContent[] = [];\n for (const msg of messages) {\n if (msg.role === 'user') {\n out.push({ role: 'user', parts: [{ text: msg.text }] });\n } else if (msg.role === 'assistant') {\n // Prefer the original parts array (carrying thoughtSignatures and\n // thought summaries) when the assistant turn was produced by this\n // adapter. Gemini 2.5+/3.x thinking mode REQUIRES the signatures\n // round-trip; reconstructing from `text + toolCalls` would drop\n // them and the next request would 400 with INVALID_ARGUMENT.\n if (Array.isArray((msg.providerData as { parts?: unknown })?.parts)) {\n const parts = (msg.providerData as { parts: GeminiPart[] }).parts;\n out.push({ role: 'model', parts });\n continue;\n }\n const parts: GeminiPart[] = [];\n if (msg.text) parts.push({ text: msg.text });\n for (const tc of msg.toolCalls) {\n parts.push({ functionCall: { name: tc.name, args: tc.input } });\n }\n // Gemini rejects empty parts arrays; if the assistant said nothing\n // and called no tools (shouldn't happen in our loop), inject an\n // empty text part so the round-trip stays valid.\n if (parts.length === 0) parts.push({ text: '' });\n out.push({ role: 'model', parts });\n } else {\n const parts: GeminiPart[] = msg.results.map((r) => ({\n functionResponse: {\n name: r.toolName,\n response: parseToolResultContent(r.content, r.isError)\n }\n }));\n out.push({ role: 'user', parts });\n }\n }\n return out;\n}\n\n/**\n * Gemini's `functionResponse.response` is an OBJECT, not a free string.\n * Our normalized `tool` messages carry the result as a JSON-stringified\n * payload. Parse it back; on parse failure (e.g. a tool serialized a\n * scalar), wrap so Gemini still gets a valid object. Errors are wrapped\n * under `error` so the model can distinguish success from failure.\n */\nfunction parseToolResultContent(\n content: string,\n isError: boolean\n): Record<string, unknown> {\n let parsed: unknown = null;\n try {\n parsed = JSON.parse(content);\n } catch {\n parsed = content;\n }\n if (isError) {\n return { error: parsed };\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n // Scalars / arrays — wrap so the response is always a JSON object.\n return { result: parsed };\n}\n\nexport function fromGeminiResponse(json: GeminiResponse): AgentTurn {\n const candidate = json.candidates?.[0];\n const parts = candidate?.content?.parts ?? [];\n const textParts: string[] = [];\n const toolCalls: NormalizedToolCall[] = [];\n let idx = 0;\n for (const part of parts) {\n // `thought: true` parts are model thinking summaries — include them\n // in `providerData` (so signatures round-trip) but NOT in `text`,\n // which feeds the transcript shown to the user.\n if (typeof part.text === 'string' && part.thought !== true) {\n textParts.push(part.text);\n } else if (part.functionCall) {\n toolCalls.push({\n id: `gem_${idx}_${part.functionCall.name}`,\n name: part.functionCall.name,\n input: (part.functionCall.args ?? {}) as Record<string, unknown>\n });\n idx += 1;\n }\n }\n return {\n text: textParts.join(''),\n toolCalls,\n stopReason: normalizeFinishReason(candidate?.finishReason, toolCalls.length > 0),\n // Preserve the raw parts so a subsequent runTurn() echoes the\n // assistant turn back faithfully, including any `thoughtSignature`\n // entries thinking-mode requires.\n providerData: { parts }\n };\n}\n\nfunction normalizeFinishReason(\n reason: string | undefined,\n hasToolCalls: boolean\n): AgentTurn['stopReason'] {\n if (hasToolCalls) return 'tool_use';\n switch (reason) {\n case 'STOP':\n return 'end_turn';\n case 'MAX_TOKENS':\n return 'max_tokens';\n default:\n return reason ? 'other' : 'end_turn';\n }\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n","/**\n * Tool-calling provider registry.\n *\n * The agent loop and the routes layer drive providers through this\n * factory; vendor specifics stay inside `claude.ts` / `gemini.ts`.\n * Adding a third provider would slot in alongside without further\n * changes to the agent loop.\n *\n * The host injects credentials (a `GoogleAuth` instance), the GCP\n * project id, the default region, and the pinned model ids via\n * `VertexPort`. A per-request region override flows in as\n * `ProviderInitOpts.location` so admin-managed `aiSettings.gcpLocation`\n * can flip Vertex regions without rebuilding the registry.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport { ClaudeToolProvider, createClaudeProvider } from './claude';\nimport { GeminiToolProvider, createGeminiProvider } from './gemini';\nimport type { ToolProvider, ToolProviderId } from './types';\n\nexport type {\n ToolProvider,\n ToolProviderId,\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n NormalizedToolCall,\n NormalizedToolResult,\n SystemBlock,\n ToolSchema\n} from './types';\nexport { ClaudeToolProvider, createClaudeProvider } from './claude';\nexport { GeminiToolProvider, createGeminiProvider } from './gemini';\nexport { toGeminiSchema } from './schema';\n\nexport type ProviderInitOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Default Vertex region used when `location` is omitted. */\n defaultLocation: string;\n /** Vertex model ids pinned by the host. */\n modelIds: { claude: string; gemini: string };\n /** Per-request override for `aiSettings.gcpLocation`. Falls back to defaultLocation. */\n location?: string;\n};\n\nexport type ToolProviderDef = {\n id: ToolProviderId;\n label: string;\n description: string;\n createProvider(opts: ProviderInitOpts): ToolProvider;\n};\n\nexport const toolProviders: ToolProviderDef[] = [\n {\n id: 'claude',\n label: 'Claude (Vertex)',\n description: 'Anthropic Messages API hosted on GCP Vertex AI.',\n createProvider(opts) {\n return createClaudeProvider({\n auth: opts.auth,\n projectId: opts.projectId,\n location: opts.location ?? opts.defaultLocation,\n modelId: opts.modelIds.claude\n });\n }\n },\n {\n id: 'gemini',\n label: 'Gemini (Vertex)',\n description: 'Google Gemini hosted on GCP Vertex AI (raw generateContent).',\n createProvider(opts) {\n return createGeminiProvider({\n auth: opts.auth,\n projectId: opts.projectId,\n location: opts.location ?? opts.defaultLocation,\n modelId: opts.modelIds.gemini\n });\n }\n }\n];\n\nexport function getToolProvider(id: string): ToolProviderDef | undefined {\n return toolProviders.find((p) => p.id === id);\n}\n","/**\n * Internal helpers shared by the narrators. Lifted verbatim from the host's\n * `src/lib/google-auth.ts` so the narrators can speak Vertex without\n * importing host code. The package never reads `process.env.GCP_*` — every\n * field comes in as an argument from the caller.\n */\nimport { GoogleAuth } from 'google-auth-library';\nimport { AnthropicVertex } from '@anthropic-ai/vertex-sdk';\n\n/**\n * Build the Vertex AI host for a given location. Most regions resolve to\n * `{region}-aiplatform.googleapis.com`; the special `global` location uses\n * the un-prefixed `aiplatform.googleapis.com` endpoint.\n */\nexport function vertexHost(location: string): string {\n return location === 'global'\n ? 'aiplatform.googleapis.com'\n : `${location}-aiplatform.googleapis.com`;\n}\n\n/** Fetch a fresh OAuth access token using the host-supplied GoogleAuth. */\nexport async function getAccessToken(auth: GoogleAuth): Promise<string> {\n const token = await auth.getAccessToken();\n if (!token) throw new Error('Failed to obtain GCP access token');\n return token;\n}\n\n/**\n * Build an `AnthropicVertex` client and patch its `buildRequest` so it is\n * synchronous, working around the ABI mismatch between\n * `@anthropic-ai/vertex-sdk@0.16.0` (declares `buildRequest` as async) and\n * `@anthropic-ai/sdk@0.50.4` (consumes it synchronously). Without this\n * patch, the destructured `{ req, url, timeout }` returns `undefined`s and\n * the SDK throws \"Cannot read properties of undefined (reading 'headers')\"\n * before any HTTP request is sent.\n */\nexport function createAnthropicVertexClient(args: {\n projectId: string;\n location: string;\n auth: GoogleAuth;\n}): AnthropicVertex {\n const client = new AnthropicVertex({\n projectId: args.projectId,\n region: args.location,\n googleAuth: args.auth\n });\n patchVertexBuildRequestSync(client);\n return client;\n}\n\nconst MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);\nconst VERTEX_DEFAULT_VERSION = 'vertex-2023-10-16';\n\nfunction isObj(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction patchVertexBuildRequestSync(client: AnthropicVertex): void {\n const proto = Object.getPrototypeOf(client) as Record<string, unknown>;\n const grandparent = Object.getPrototypeOf(proto) as {\n buildRequest: (...args: unknown[]) => unknown;\n };\n proto.buildRequest = function patchedBuildRequest(\n this: AnthropicVertex & { projectId?: string; region?: string },\n options: { method?: string; path?: string; body?: unknown },\n extra?: unknown\n ) {\n if (isObj(options.body)) {\n options.body = { ...options.body };\n }\n if (isObj(options.body) && !options.body.anthropic_version) {\n options.body.anthropic_version = VERTEX_DEFAULT_VERSION;\n }\n if (\n options.path &&\n MODEL_ENDPOINTS.has(options.path) &&\n options.method === 'post' &&\n isObj(options.body)\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n const model = options.body.model;\n options.body.model = undefined;\n const stream = options.body.stream ?? false;\n const specifier = stream ? 'streamRawPredict' : 'rawPredict';\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${model}:${specifier}`;\n }\n if (\n options.path === '/v1/messages/count_tokens' ||\n (options.path === '/v1/messages/count_tokens?beta=true' && options.method === 'post')\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`;\n }\n return grandparent.buildRequest.call(this, options, extra);\n } as unknown as (typeof proto)['buildRequest'];\n}\n","/**\n * Claude narrator — turns one paragraph_brief block's key_facts into\n * flowing prose using Claude on Vertex AI (Anthropic Messages API served\n * through GCP Vertex Model Garden).\n *\n * The narrator MUST NOT introduce numbers that aren't already in the\n * structured payload — that's the rule the system prompt enforces. The\n * eval harness asserts this indirectly: structured numbers must be\n * byte-identical across providers.\n *\n * Lifted from the host's `src/ai/narrators/claude.ts`. Refactored from a\n * class to a streaming function so the narrator no longer pulls auth out\n * of the host's env-reader; every credential field comes in as an arg.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { createAnthropicVertexClient } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging (\"it appears\", \"perhaps\").\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim — if raw_numbers says\n 1234.56, say \"1,234.56\" or \"$1,235\", never \"about 1.2k\" if that\n drifts.\n - Do not begin with \"Here is\", \"Below\", \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamClaudeNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n input: NarrativeInput;\n};\n\n/**\n * Stream Claude prose tokens for one paragraph_brief block. Yields raw\n * text deltas as the model produces them — the route layer is responsible\n * for any SSE framing on top.\n */\nexport async function* streamClaudeNarration(\n opts: StreamClaudeNarrationOpts\n): AsyncIterable<string> {\n const client = createAnthropicVertexClient({\n projectId: opts.projectId,\n location: opts.location,\n auth: opts.auth\n });\n\n const stream = await client.messages.stream({\n model: opts.modelId,\n max_tokens: 400,\n system: NARRATIVE_SYSTEM,\n messages: [{ role: 'user', content: buildNarrativeUserMessage(opts.input) }]\n });\n\n for await (const event of stream) {\n if (\n event.type === 'content_block_delta' &&\n 'delta' in event &&\n event.delta &&\n 'type' in event.delta &&\n event.delta.type === 'text_delta'\n ) {\n yield (event.delta as { type: 'text_delta'; text: string }).text;\n }\n }\n}\n\nexport function buildNarrativeUserMessage(input: NarrativeInput): string {\n return [\n `User question: ${input.question}`,\n '',\n `Block topic: ${input.topic}`,\n `Block key_facts:\\n${input.keyFacts.map((f) => `- ${f}`).join('\\n')}`,\n '',\n 'Full structured answer (for reference; do not restate the whole thing):',\n JSON.stringify(input.structured, null, 2)\n ].join('\\n');\n}\n","/**\n * Gemini narrator — turns one paragraph_brief block's key_facts into\n * flowing prose using Gemini on Vertex AI. Same prose contract as the\n * Claude and Grok narrators; structured numbers are unchanged so the eval\n * harness's byte-identical equivalence assertion holds across the swap.\n *\n * Auth: a Google access token from the host-supplied `GoogleAuth`\n * instance (the package never reads `process.env.GCP_*`).\n *\n * Streaming: Vertex's `:streamGenerateContent` returns a JSON array of\n * chunks delivered as the prediction unfolds. Setting `alt=sse` flips the\n * transport to SSE-style `data: {chunk}\\n\\n` frames, which we parse inline\n * rather than pulling in `@google-cloud/vertexai`.\n *\n * Lifted from the host's `src/ai/narrators/gemini.ts`. Refactored to take\n * `{ auth, projectId, location, modelId }` explicitly instead of calling\n * `getVertexAuth`/`getVertexAccessToken` from the host.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { buildNarrativeUserMessage } from './claude';\nimport { getAccessToken, vertexHost } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging.\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim.\n - Do not begin with \"Here is\" or \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamGeminiNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n input: NarrativeInput;\n};\n\nexport async function* streamGeminiNarration(\n opts: StreamGeminiNarrationOpts\n): AsyncIterable<string> {\n const accessToken = await getAccessToken(opts.auth);\n const url = `https://${vertexHost(opts.location)}/v1/projects/${opts.projectId}/locations/${opts.location}/publishers/google/models/${opts.modelId}:streamGenerateContent?alt=sse`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n systemInstruction: { parts: [{ text: NARRATIVE_SYSTEM }] },\n contents: [\n {\n role: 'user',\n parts: [{ text: buildNarrativeUserMessage(opts.input) }]\n }\n ],\n generationConfig: { maxOutputTokens: 400, temperature: 0 }\n })\n });\n\n if (!res.ok || !res.body) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Gemini request failed (${res.status}): ${detail}`);\n }\n\n yield* parseGeminiSseTextDeltas(res.body);\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n\n/**\n * Parses Vertex Gemini's SSE-formatted `:streamGenerateContent?alt=sse`\n * response and yields successive text deltas. Each frame is a JSON\n * `GenerateContentResponse` whose `candidates[0].content.parts[*].text`\n * carries the prose tokens. Tool-call frames are ignored — the narrator\n * doesn't expose tools.\n */\nasync function* parseGeminiSseTextDeltas(\n body: ReadableStream<Uint8Array>\n): AsyncIterable<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffered += decoder.decode(value, { stream: true });\n let newlineIndex: number;\n while ((newlineIndex = buffered.indexOf('\\n')) !== -1) {\n const line = buffered.slice(0, newlineIndex).trim();\n buffered = buffered.slice(newlineIndex + 1);\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (!payload) continue;\n try {\n const chunk = JSON.parse(payload) as {\n candidates?: Array<{ content?: { parts?: Array<{ text?: string }> } }>;\n };\n const parts = chunk.candidates?.[0]?.content?.parts ?? [];\n for (const part of parts) {\n if (typeof part.text === 'string' && part.text.length > 0) {\n yield part.text;\n }\n }\n } catch {\n // Mid-frame JSON or keepalive — skip silently.\n }\n }\n }\n}\n","/**\n * Grok narrator — talks to xAI Grok served by GCP Vertex Model Garden via\n * Vertex's OpenAI-compatible chat-completions endpoint. Same prose\n * contract as the Claude narrator; the structured answer is unchanged so\n * byte-identical equivalence holds across the swap.\n *\n * Auth: a Google access token from the host-supplied `GoogleAuth`\n * instance.\n *\n * Streaming: Vertex's OpenAI-compat endpoint returns standard server-sent\n * events (`data: {chunk}\\n\\n` … `data: [DONE]`). We parse the deltas\n * inline rather than pulling in the OpenAI SDK so the only Vertex\n * dependency for Grok is `google-auth-library`.\n *\n * NOTE: `VertexPort.modelIds` does not currently include a `grok` slot —\n * the host's `VertexPort` only pins `claude` and `gemini`. The caller\n * passes the Grok model id explicitly via `modelId` for now.\n * TODO: add `modelIds.grok` to `VertexPort` once the host plumbs the\n * Grok model setting through `ai_settings`.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { buildNarrativeUserMessage } from './claude';\nimport { getAccessToken, vertexHost } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging.\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim.\n - Do not begin with \"Here is\" or \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamGrokNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n input: NarrativeInput;\n};\n\nexport async function* streamGrokNarration(\n opts: StreamGrokNarrationOpts\n): AsyncIterable<string> {\n const accessToken = await getAccessToken(opts.auth);\n const url = `https://${vertexHost(opts.location)}/v1beta1/projects/${opts.projectId}/locations/${opts.location}/endpoints/openapi/chat/completions`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n model: opts.modelId,\n max_tokens: 400,\n stream: true,\n messages: [\n { role: 'system', content: NARRATIVE_SYSTEM },\n { role: 'user', content: buildNarrativeUserMessage(opts.input) }\n ]\n })\n });\n\n if (!res.ok || !res.body) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Grok request failed (${res.status}): ${detail}`);\n }\n\n yield* parseSseDeltas(res.body);\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n\n/** Parses an OpenAI-compatible SSE stream and yields text deltas. */\nasync function* parseSseDeltas(body: ReadableStream<Uint8Array>): AsyncIterable<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffered += decoder.decode(value, { stream: true });\n let newlineIndex: number;\n while ((newlineIndex = buffered.indexOf('\\n')) !== -1) {\n const line = buffered.slice(0, newlineIndex).trim();\n buffered = buffered.slice(newlineIndex + 1);\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (!payload || payload === '[DONE]') {\n if (payload === '[DONE]') return;\n continue;\n }\n try {\n const chunk = JSON.parse(payload) as {\n choices?: Array<{ delta?: { content?: string } }>;\n };\n const delta = chunk.choices?.[0]?.delta?.content;\n if (typeof delta === 'string' && delta.length > 0) yield delta;\n } catch {\n // Mid-chunk JSON or keepalive — skip silently.\n }\n }\n }\n}\n","/**\n * Narrators — the prose pass that turns a structured answer into the\n * paragraph_brief block's flowing text. The agent's tool loop decides\n * WHAT to say (key_facts); the narrator decides HOW to say it.\n *\n * Three implementations:\n * - streamClaudeNarration — Anthropic Messages on GCP Vertex\n * - streamGrokNarration — xAI Grok via Vertex's OpenAI-compatible endpoint\n * - streamGeminiNarration — Google Gemini on GCP Vertex\n *\n * All three expose the same shape: an async generator yielding raw text\n * deltas. The route layer is responsible for any SSE framing on top — the\n * package keeps the streaming primitive provider-agnostic.\n *\n * Lifted from the host's `src/ai/narrators/`. The host's class-based\n * `NarrativeProvider` interface and `createNarrativeProvider` factory are\n * replaced with plain streaming functions plus a `getNarrator(id)` lookup.\n * Every credential field comes in as an explicit argument; no `@/...`\n * imports remain.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { PresentPayload } from '../tools/types';\nimport { streamClaudeNarration, type StreamClaudeNarrationOpts } from './claude';\nimport { streamGeminiNarration, type StreamGeminiNarrationOpts } from './gemini';\nimport { streamGrokNarration, type StreamGrokNarrationOpts } from './grok';\n\nexport type NarratorId = 'claude' | 'gemini' | 'grok';\n\nexport type NarrativeInput = {\n question: string;\n structured: PresentPayload;\n topic: string;\n keyFacts: string[];\n blockIndex: number;\n};\n\n/**\n * Common shape every narrator accepts. Each individual narrator declares a\n * specialised version (e.g. `StreamClaudeNarrationOpts`) for direct use;\n * `getNarrator()` consumes this widened shape so the call site doesn't have\n * to discriminate on the id.\n */\nexport type NarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n input: NarrativeInput;\n};\n\nexport type NarratorFn = (opts: NarrationOpts) => AsyncIterable<string>;\n\n/**\n * Resolve a narrator by id. Returns the streaming function that turns a\n * `NarrationOpts` bundle into an async iterable of text deltas. Throws on\n * an unknown id rather than falling back silently — the caller validates\n * the configured provider against this registry's keys.\n */\nexport function getNarrator(id: NarratorId): NarratorFn {\n switch (id) {\n case 'claude':\n return streamClaudeNarration;\n case 'gemini':\n return streamGeminiNarration;\n case 'grok':\n return streamGrokNarration;\n default: {\n const _exhaustive: never = id;\n throw new Error(`Unknown narrator id: ${String(_exhaustive)}`);\n }\n }\n}\n\nexport {\n streamClaudeNarration,\n streamGeminiNarration,\n streamGrokNarration,\n type StreamClaudeNarrationOpts,\n type StreamGeminiNarrationOpts,\n type StreamGrokNarrationOpts\n};\n","/**\n * `agent-custom` SSE route factory.\n *\n * Host-agnostic refactor of the host repo's `app/api/agent/route.ts`. The\n * SSE wire format is preserved byte-for-byte (the package's UI components\n * consume this stream): `event: meta`, `event: block`, `event: prose`,\n * `event: error`, `event: done`. All host-specific concerns (auth, scope,\n * tools, persistence, credentials) cross the boundary as ports passed in\n * via `AgentCustomRouteCtx`.\n */\nimport { randomUUID } from 'crypto';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from '../ports/types';\nimport type { Block, PresentPayload, ToolContext } from '../tools/types';\nimport { runAgent } from '../agent';\nimport { getToolProvider } from '../providers';\nimport { getNarrator, type NarratorId } from '../narrators';\n\n/**\n * Common lifecycle hooks shared across every route factory. Hooks return\n * `Response | null`: a non-null Response short-circuits the request (the\n * factory returns it untouched), `null` continues the normal flow.\n */\nexport type RouteHooks<S> = {\n /** Runs before auth. Return a Response to short-circuit (e.g. 503 during shutdown). */\n onRequest?(req: Request): Promise<Response | null>;\n /** Runs after successful auth. Return a Response to short-circuit (e.g. 429 rate-limited). */\n onAuthenticated?(args: { req: Request; scope: S; userId: number }): Promise<Response | null>;\n};\n\n/**\n * Streaming-route hooks. Adds three lifecycle points specific to the SSE\n * `agent-custom` path so consumers can plumb in per-request resources\n * (e.g. SQL view creation/cleanup keyed off a fresh sessionId).\n */\nexport type AgentCustomHooks<S> = RouteHooks<S> & {\n /**\n * Generate the per-request session id used in ToolContext (and any\n * project-specific resources keyed off it, e.g. SQL view names).\n * Defaults to a random URL-safe id (16 hex chars from a UUID).\n */\n generateSessionId?(args: {\n scope: S;\n userId: number;\n chatSessionId: number | null;\n }): string | Promise<string>;\n /**\n * Runs once after the session id is resolved, before the agent loop.\n * Throw to abort the request (the route catches and surfaces the error\n * via the SSE error frame + persistence).\n */\n onSessionStart?(args: {\n scope: S;\n sessionId: string;\n userId: number;\n }): Promise<void>;\n /**\n * Always runs in `finally`, regardless of how the stream ended.\n * The route never throws out of this hook — its errors are logged via\n * ctx.logger but don't surface to the client.\n */\n onSessionEnd?(args: {\n scope: S;\n sessionId: string;\n userId: number;\n cause: 'complete' | 'error' | 'abort';\n }): Promise<void>;\n};\n\nexport type AgentCustomRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Resolve which narrator to use for prose generation. Default:\n * `() => aiSettings.toolProvider` (which is only ever `claude` or\n * `gemini` from the registry). Hosts that surface a per-user\n * `narrative_provider` (e.g. allowing `grok`) wire their existing\n * lookup here.\n */\n resolveNarratorId?: (scope: S) => Promise<NarratorId>;\n /**\n * Optional lifecycle hooks. See `AgentCustomHooks` for the available\n * extension points (shutdown gating, rate limiting, per-request\n * resource setup/teardown).\n */\n hooks?: AgentCustomHooks<S>;\n};\n\nconst NARRATOR_IDS: ReadonlySet<NarratorId> = new Set<NarratorId>([\n 'claude',\n 'gemini',\n 'grok'\n]);\n\nfunction isNarratorId(value: string): value is NarratorId {\n return NARRATOR_IDS.has(value as NarratorId);\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'Content-Type': 'application/json' }\n });\n}\n\n/**\n * Default per-request session id generator. 16 hex chars, drawn from a\n * UUID — short enough to fit in identifiers (e.g. SQL view names) and\n * fresh per request so it never collides with the persistent\n * `chatSessionId`.\n */\nfunction defaultGenerateSessionId(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n}\n\n/**\n * Pull a narrator-specific Vertex model id out of the host's\n * `VertexPort.modelIds`. The port pins `claude` and `gemini`; `grok` is\n * optional (may exist as an unsanctioned extra key set by the host).\n */\nfunction pickNarratorModelId(\n vertex: VertexPort,\n narratorId: NarratorId\n): string {\n if (narratorId === 'claude') return vertex.modelIds.claude;\n if (narratorId === 'gemini') return vertex.modelIds.gemini;\n // narratorId === 'grok'\n const extra = vertex.modelIds as { grok?: string };\n if (typeof extra.grok === 'string' && extra.grok.length > 0) {\n return extra.grok;\n }\n throw new Error(\n \"Narrator 'grok' selected but VertexPort.modelIds.grok is not pinned.\"\n );\n}\n\nexport function createAgentCustomRoutes<S>(ctx: AgentCustomRouteCtx<S>) {\n const { persistence, auth, scope, tools, vertex, logger, hooks } = ctx;\n\n return {\n /** Next.js-compatible POST handler. */\n POST: async (req: Request): Promise<Response> => {\n // 0. Pre-auth hook (e.g. shutdown gate → 503).\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n\n // 1. Authenticate via host port.\n const authResult = await auth.requireAuth(req);\n if (!authResult.ok) return authResult.response;\n const { scope: callerScope, userId } = authResult;\n\n // 1b. Post-auth hook (e.g. rate limit → 429).\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: callerScope,\n userId\n });\n if (short) return short;\n }\n\n // 2. Parse + validate body.\n const body = (await req.json().catch(() => null)) as\n | { question?: unknown; chatSessionId?: unknown }\n | null;\n const question =\n typeof body?.question === 'string' ? body.question.trim() : '';\n if (!question) {\n return jsonError(\n 400,\n 'VALIDATION_FAILED',\n 'question must be a non-empty string.'\n );\n }\n const rawChatSessionId = body?.chatSessionId;\n const incomingChatSessionId =\n typeof rawChatSessionId === 'number' &&\n Number.isInteger(rawChatSessionId)\n ? rawChatSessionId\n : null;\n\n // 3. AI settings (singleton).\n const aiSettings = await persistence.getAiSettings();\n\n // 4 & 5. Resolve / create the chat session, then persist the user turn.\n let chatSessionId: number;\n if (incomingChatSessionId !== null) {\n const owned = await persistence.getSession(incomingChatSessionId, userId);\n if (!owned) {\n return jsonError(404, 'NOT_FOUND', 'Chat session not found.');\n }\n chatSessionId = owned.id;\n } else {\n const created = await persistence.createSession({\n userId,\n title: question.slice(0, 200)\n });\n chatSessionId = created.id;\n }\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'user',\n question\n });\n\n // 5b. Resolve the per-request session id (fresh, ephemeral, never\n // collides with the persistent chatSessionId).\n const sessionId: string = hooks?.generateSessionId\n ? await hooks.generateSessionId({\n scope: callerScope,\n userId,\n chatSessionId: incomingChatSessionId\n })\n : defaultGenerateSessionId();\n\n // 6 & 7. Build ToolContext + system blocks.\n const scopeSummary = await scope.buildScopeSummary(callerScope);\n const scopeLabel = await scope.resolveScopeLabel(callerScope);\n const toolContext: ToolContext<S> = {\n scope: callerScope,\n sessionId,\n scopeSummary,\n toolCallCount: 0\n };\n const systemBlocks = await tools.buildSystemBlocks(toolContext);\n\n // 8. Resolve the configured tool provider.\n const def = getToolProvider(aiSettings.toolProvider);\n if (!def) {\n return jsonError(\n 400,\n 'INVALID_PROVIDER',\n `Unknown tool provider in ai_settings: ${aiSettings.toolProvider}`\n );\n }\n const provider = def.createProvider({\n auth: vertex.auth,\n projectId: vertex.projectId,\n defaultLocation: vertex.defaultLocation,\n modelIds: vertex.modelIds,\n location: aiSettings.gcpLocation\n });\n\n // 9. Pick the narrator. Defaults to whatever toolProvider is set —\n // safe because the registry only allows claude/gemini, both of\n // which have pinned model ids.\n let narratorId: NarratorId;\n if (ctx.resolveNarratorId) {\n narratorId = await ctx.resolveNarratorId(callerScope);\n } else if (isNarratorId(aiSettings.toolProvider)) {\n narratorId = aiSettings.toolProvider;\n } else {\n return jsonError(\n 400,\n 'INVALID_NARRATOR',\n `Cannot derive narrator from tool provider: ${aiSettings.toolProvider}`\n );\n }\n\n // 10. Open the SSE stream.\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n let closed = false;\n const send = (event: string, data: unknown) => {\n if (closed) return;\n try {\n controller.enqueue(\n encoder.encode(\n `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`\n )\n );\n } catch {\n // Controller already closed (client gone) — swallow.\n }\n };\n\n // Buffers used to persist the assistant turn at the end of the\n // stream. We mirror the SSE payloads: blocks[] is the structured\n // answer; prose[blockIndex] is the streamed prose for\n // paragraph_brief blocks.\n const persistedBlocks: Block[] = [];\n const persistedProse: Record<number, string> = {};\n let persistedError: { code: string; message: string } | null = null;\n let sessionStarted = false;\n\n try {\n // 10a. Per-request resource setup (e.g. SQL view creation).\n // Errors here surface as a normal SSE error frame and are\n // persisted with the assistant turn.\n if (hooks?.onSessionStart) {\n await hooks.onSessionStart({\n scope: callerScope,\n sessionId,\n userId\n });\n }\n sessionStarted = true;\n\n send('meta', { chatSessionId, scopeLabel });\n\n const agentResult = await runAgent({\n question,\n ctx: toolContext,\n tools: tools.tools,\n systemBlocks,\n provider\n });\n\n if (!agentResult.ok) {\n persistedError = agentResult.error;\n send('error', agentResult.error);\n send('done', {});\n return;\n }\n\n const { structured } = agentResult as {\n structured: PresentPayload;\n };\n\n let narratorModelId: string | null = null;\n const narratorFn = getNarrator(narratorId);\n\n for (let i = 0; i < structured.blocks.length; i++) {\n const block = structured.blocks[i];\n persistedBlocks[i] = block;\n send('block', { index: i, ...block });\n if (block.kind === 'paragraph_brief') {\n persistedProse[i] = '';\n try {\n if (narratorModelId === null) {\n narratorModelId = pickNarratorModelId(vertex, narratorId);\n }\n for await (const token of narratorFn({\n auth: vertex.auth,\n projectId: vertex.projectId,\n location: aiSettings.gcpLocation,\n modelId: narratorModelId,\n input: {\n question,\n structured,\n topic: block.topic,\n keyFacts: block.key_facts,\n blockIndex: i\n }\n })) {\n persistedProse[i] += token;\n send('prose', { block_index: i, delta: token });\n }\n } catch (e) {\n // Narrator failed: fall back to key_facts joined by\n // \". \" so the user still sees the data, then surface\n // the error so the UI can flag it.\n const fallback = block.key_facts.join('. ') + '.';\n persistedProse[i] = fallback;\n send('prose', {\n block_index: i,\n delta: block.key_facts.join('. ')\n });\n send('prose', { block_index: i, delta: '.' });\n send('error', {\n code: 'NARRATOR_FAILED',\n message: `Prose stream failed (${(e as Error).message}); fell back to key facts.`\n });\n }\n }\n }\n\n send('done', {});\n } catch (e) {\n const message = (e as Error).message ?? 'Internal error';\n persistedError = { code: 'INTERNAL', message };\n logger?.error?.(\n { chatSessionId, sessionId, err: message },\n '[agent-custom] stream errored'\n );\n try {\n controller.enqueue(\n encoder.encode(\n `event: error\\ndata: ${JSON.stringify({ code: 'INTERNAL', message })}\\n\\n`\n )\n );\n controller.enqueue(encoder.encode(`event: done\\ndata: {}\\n\\n`));\n } catch {\n // ignore — client already gone.\n }\n } finally {\n // 10b. Per-request resource teardown. Always runs (even when\n // onSessionStart threw — symmetric to the host's view-drop\n // contract: dropOnce is safe to call without a prior create).\n // Errors here are logged but never surfaced; this is the one\n // hook the route deliberately swallows.\n if (hooks?.onSessionEnd) {\n const cause: 'complete' | 'error' | 'abort' = req.signal.aborted\n ? 'abort'\n : persistedError\n ? 'error'\n : 'complete';\n try {\n await hooks.onSessionEnd({\n scope: callerScope,\n sessionId,\n userId,\n cause\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n sessionStarted,\n err: (err as Error).message\n },\n '[agent-custom] onSessionEnd hook failed'\n );\n }\n }\n\n // Persist the assistant turn last so a mid-stream client abort\n // still records what was generated up to that point.\n try {\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: persistedBlocks.length ? persistedBlocks : null,\n prose: Object.keys(persistedProse).length\n ? persistedProse\n : null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n { chatSessionId, sessionId, err: (err as Error).message },\n '[agent-custom] failed to persist assistant turn'\n );\n }\n try {\n closed = true;\n controller.close();\n } catch {\n // already closed\n }\n }\n }\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n }\n });\n }\n };\n}\n","/**\n * Vercel AI SDK tool adapter.\n *\n * Translates the package's `ToolsPort.tools` (the same registry the custom\n * SSE chat consumes) into Vercel AI SDK 4's `tool({...})` map so\n * `streamText({ tools, ... })` can drive the same tool loop natively.\n *\n * Two pieces of behaviour are reproduced from `runAgent`:\n * - `SELF_VERIFY_REQUIRED` gate — the model must run at least two prior\n * tool calls before `present`. We track `toolCallCount` in a closure.\n * - `present` is the terminal tool — its blocks become custom data parts\n * on the `StreamData` writer (so the client renders charts/tables) and\n * the route persists the structured payload via `onPresent`.\n *\n * Tool execute results are surfaced to the model as either `data` (success)\n * or `{ error: { code, message } }` (failure), matching the envelope the\n * model already understands from the custom-route's tool-result frames.\n */\nimport { tool, type Tool } from 'ai';\nimport type { StreamData } from 'ai';\nimport type {\n PresentPayload,\n ToolContext,\n ToolDefinition\n} from './tools/types';\nimport { TERMINAL_TOOL_NAME } from './tools/types';\n\n// `Tool`'s default generic is `<any, any>` already; using the wider\n// signature here lets us mix tools whose Zod schemas / result shapes\n// differ (the SDK validates them per-tool at call time).\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type VercelToolMap = Record<string, Tool<any, any>>;\n\n/**\n * Build a Vercel AI SDK tool map from the host's tool registry.\n *\n * @throws if any tool is registered without a `zodSchema` — the SDK's\n * `tool({ parameters })` requires a Zod (or AI SDK Schema) instance\n * to validate the model's tool-call arguments.\n */\nexport function buildVercelTools<S>(\n tools: Record<string, ToolDefinition<unknown, S>>,\n ctx: ToolContext<S>,\n data: StreamData,\n onPresent: (payload: PresentPayload) => void\n): VercelToolMap {\n const result: VercelToolMap = {};\n let toolCallCount = 0;\n\n for (const [name, def] of Object.entries(tools)) {\n if (!def.zodSchema) {\n throw new Error(\n `Tool '${name}' has no zodSchema; required for the Vercel AI SDK chat. ` +\n `Add a Zod schema to the tool definition (or remove it from the registry ` +\n `if the host only uses the custom SSE chat).`\n );\n }\n\n if (name === TERMINAL_TOOL_NAME) {\n result[name] = tool({\n description: def.schema.description,\n // The Zod schema doubles as the runtime parameter validator the SDK\n // hands the model. We accept whatever Zod shape the host registered;\n // the SDK uses it to validate the tool-call arguments before dispatch.\n parameters: def.zodSchema,\n execute: async (input: unknown) => {\n // Mirror runAgent's self-verify gate. Once present has been\n // requested with toolCallCount < 2, return an error envelope so\n // the model retries with at least one cross-check tool call.\n if (toolCallCount < 2) {\n return {\n error: {\n code: 'SELF_VERIFY_REQUIRED',\n message:\n 'Per FR-8.3 you must run at least one CROSS-CHECK tool call (a different metric, a different period, or a run_sql sanity-check) before present. Make that extra call now, then call present again.'\n }\n };\n }\n const payload = input as PresentPayload;\n // Forward each block to the client as a custom data part. The\n // route persists the same payload via `onPresent`. Block values\n // round-trip as JSON; we cast through `unknown` because chart\n // blocks carry `Record<string, unknown>` cells which are\n // structurally JSON-safe but don't satisfy the AI SDK's narrow\n // `JSONValue` recursive type.\n for (let i = 0; i < payload.blocks.length; i++) {\n data.append({\n type: 'block',\n value: { index: i, ...payload.blocks[i] }\n } as unknown as Parameters<StreamData['append']>[0]);\n }\n onPresent(payload);\n return { ok: true };\n }\n });\n continue;\n }\n\n result[name] = tool({\n description: def.schema.description,\n parameters: def.zodSchema,\n execute: async (input: unknown) => {\n const res = await def.execute(input, { ...ctx, toolCallCount });\n toolCallCount += 1;\n if (res.ok) return res.data as unknown;\n return { error: res.error };\n }\n });\n }\n\n return result;\n}\n","/**\n * `agent-vercel` route factory.\n *\n * Peer to `agent-custom`: same persistence, same tool catalogue, same\n * scope/auth ports, same lifecycle hooks — different transport. Vercel AI\n * SDK 4's `streamText({ tools })` runs the agent loop natively and emits a\n * data stream the `useChat` hook in `@ai-sdk/react` consumes. The\n * structured `present` payload is forwarded as custom `block` data parts\n * (see `vercel-adapter.ts`) so the same `AnswerBlocks` component renders\n * charts/tables identically across both UI shells.\n *\n * Differences from the custom SSE route:\n * - No bespoke SSE protocol — `result.toDataStreamResponse({ data })`.\n * - No separate narrator pass — `streamText` produces prose directly,\n * and the prose is attributed to the first `paragraph_brief` block on\n * persistence (the AI SDK doesn't split prose per-block).\n * - System-prompt `cached` markers are dropped on this path: the AI\n * SDK's `system` parameter is a single string (not an array of\n * blocks). Vertex auto-caches stable prefixes regardless.\n */\nimport { randomUUID } from 'crypto';\nimport { streamText, StreamData } from 'ai';\nimport { createVertex } from '@ai-sdk/google-vertex';\nimport { createVertexAnthropic } from '@ai-sdk/google-vertex/anthropic';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from '../ports/types';\nimport type {\n Block,\n PresentPayload,\n ToolContext\n} from '../tools/types';\nimport type { ToolDefinition } from '../tools/types';\nimport type { AgentCustomHooks } from './agent-custom';\nimport { buildVercelTools } from '../vercel-adapter';\n\n/**\n * Streaming-route hooks for the Vercel AI SDK chat.\n *\n * Identical to `AgentCustomHooks` — the lifecycle (pre-auth → auth →\n * post-auth → resolve session → onSessionStart → stream → onSessionEnd)\n * is the same. We re-alias rather than introducing a new type so consumers\n * can plug a single hook bag into both routes.\n */\nexport type AgentVercelHooks<S> = AgentCustomHooks<S>;\n\nexport type AgentVercelRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Optional lifecycle hooks. See `AgentCustomHooks` for the available\n * extension points (shutdown gating, rate limiting, per-request\n * resource setup/teardown).\n */\n hooks?: AgentVercelHooks<S>;\n};\n\nconst VALID_MODELS: ReadonlySet<string> = new Set(['claude', 'gemini']);\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'Content-Type': 'application/json' }\n });\n}\n\nfunction defaultGenerateSessionId(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n}\n\nexport function createAgentVercelRoutes<S>(ctx: AgentVercelRouteCtx<S>) {\n const { persistence, auth, scope, tools, vertex, logger, hooks } = ctx;\n\n return {\n /** Next.js-compatible POST handler. */\n POST: async (req: Request): Promise<Response> => {\n // 0. Pre-auth hook (e.g. shutdown gate → 503).\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n\n // 1. Authenticate via host port.\n const authResult = await auth.requireAuth(req);\n if (!authResult.ok) return authResult.response;\n const { scope: callerScope, userId } = authResult;\n\n // 1b. Post-auth hook (e.g. rate limit → 429).\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: callerScope,\n userId\n });\n if (short) return short;\n }\n\n // 2. Parse + validate body.\n const body = (await req.json().catch(() => null)) as\n | {\n question?: unknown;\n chatSessionId?: unknown;\n model?: unknown;\n }\n | null;\n const question =\n typeof body?.question === 'string' ? body.question.trim() : '';\n if (!question) {\n return jsonError(\n 400,\n 'VALIDATION_FAILED',\n 'question must be a non-empty string.'\n );\n }\n const rawChatSessionId = body?.chatSessionId;\n const incomingChatSessionId =\n typeof rawChatSessionId === 'number' &&\n Number.isInteger(rawChatSessionId)\n ? rawChatSessionId\n : null;\n const rawModel = body?.model;\n const requestedModel =\n typeof rawModel === 'string' && VALID_MODELS.has(rawModel)\n ? (rawModel as 'claude' | 'gemini')\n : null;\n\n // 3. AI settings (singleton).\n const aiSettings = await persistence.getAiSettings();\n\n // 4 & 5. Resolve / create the chat session, then persist the user turn.\n let chatSessionId: number;\n if (incomingChatSessionId !== null) {\n const owned = await persistence.getSession(\n incomingChatSessionId,\n userId\n );\n if (!owned) {\n return jsonError(404, 'NOT_FOUND', 'Chat session not found.');\n }\n chatSessionId = owned.id;\n } else {\n const created = await persistence.createSession({\n userId,\n title: question.slice(0, 200)\n });\n chatSessionId = created.id;\n }\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'user',\n question\n });\n\n // 5b. Resolve the per-request session id (fresh, ephemeral, never\n // collides with the persistent chatSessionId).\n const sessionId: string = hooks?.generateSessionId\n ? await hooks.generateSessionId({\n scope: callerScope,\n userId,\n chatSessionId: incomingChatSessionId\n })\n : defaultGenerateSessionId();\n\n // 6 & 7. Build ToolContext + system blocks.\n const scopeSummary = await scope.buildScopeSummary(callerScope);\n const scopeLabel = await scope.resolveScopeLabel(callerScope);\n const toolContext: ToolContext<S> = {\n scope: callerScope,\n sessionId,\n scopeSummary,\n toolCallCount: 0\n };\n const systemBlocks = await tools.buildSystemBlocks(toolContext);\n\n // 8. Resolve the model. Body override wins; otherwise fall back to\n // the singleton's `toolProvider`. Only `claude` and `gemini` are\n // valid here — Grok isn't routed through `@ai-sdk/google-vertex`.\n const provider: string = requestedModel ?? aiSettings.toolProvider;\n if (!VALID_MODELS.has(provider)) {\n return jsonError(\n 400,\n 'INVALID_PROVIDER',\n `Vercel chat only supports 'claude' or 'gemini'; got '${provider}'.`\n );\n }\n\n // 9. Open the data stream and assemble the rest under try/catch/finally\n // so `onSessionEnd` always runs and `data.close()` is guaranteed.\n const data = new StreamData();\n let presentPayload: PresentPayload | null = null;\n let persistedError: { code: string; message: string } | null = null;\n let sessionStarted = false;\n\n try {\n // 9a. Per-request resource setup (e.g. SQL view creation). Errors\n // here surface as a normal error data part and are persisted with\n // the assistant turn.\n if (hooks?.onSessionStart) {\n await hooks.onSessionStart({\n scope: callerScope,\n sessionId,\n userId\n });\n }\n sessionStarted = true;\n\n // 9b. Build the Vercel tool map (validates `zodSchema` presence).\n const vercelTools = buildVercelTools(\n tools.tools as Record<string, ToolDefinition<unknown, S>>,\n toolContext,\n data,\n (p) => {\n presentPayload = p;\n }\n );\n\n // 9c. Meta data part — the UI uses these to render the scope chip\n // and pin the persistent chat session id immediately on first byte.\n data.append({\n type: 'meta',\n value: { chatSessionId, scopeLabel }\n });\n\n // 9d. Compose the system prompt. The AI SDK's `system` parameter\n // is a single string — `SystemBlock.cached` markers from the host\n // are dropped on this path (Vertex auto-caches stable prefixes\n // regardless of the hint).\n const system = systemBlocks.map((b) => b.text).join('\\n\\n');\n\n // 9e. Construct the model. Both providers accept `googleAuthOptions`\n // (a `GoogleAuthOptions` bag); they construct their own\n // `GoogleAuth` internally. Our `VertexPort.auth` is a constructed\n // `GoogleAuth` instance — the SDK can't accept it directly, so we\n // pass an empty options object and rely on the same ADC the host's\n // `GoogleAuth` resolves through. (Hosts that need explicit\n // credentials should wire them through ADC env vars / metadata\n // server, which both auth paths consume identically.)\n const model =\n provider === 'claude'\n ? createVertexAnthropic({\n project: vertex.projectId,\n location: vertex.defaultLocation,\n googleAuthOptions: {}\n })(vertex.modelIds.claude)\n : createVertex({\n project: vertex.projectId,\n location: aiSettings.gcpLocation,\n googleAuthOptions: {}\n })(vertex.modelIds.gemini);\n\n const result = streamText({\n model,\n system,\n messages: [{ role: 'user', content: question }],\n tools: vercelTools,\n maxSteps: 12,\n maxTokens: 4096,\n onFinish: async ({ text }) => {\n try {\n // Persist the assistant turn. Mirror the custom adapter's\n // wire shape: `blocks` carries the structured payload,\n // `prose[blockIndex]` carries the prose for paragraph_brief\n // blocks. Since `streamText` produces a single text stream\n // (no per-block split), we attribute the whole text to the\n // FIRST `paragraph_brief` block when one exists.\n let blocks: Block[] = presentPayload?.blocks ?? [];\n const prose: Record<number, string> = {};\n const trimmed = (text ?? '').trim();\n\n if (presentPayload === null && trimmed) {\n // AGENT_NO_PRESENT fallback (mirrors agent.ts:103-119).\n // The model produced text but never called `present` —\n // synthesise a paragraph_brief block so the user always\n // gets the response. Append the synthetic block to the\n // stream BEFORE closing so the client renders it as a\n // normal block.\n const topic =\n question.length > 80\n ? question.slice(0, 77) + '...'\n : question;\n const synthetic: Block = {\n kind: 'paragraph_brief',\n topic,\n key_facts: [trimmed]\n };\n blocks = [synthetic];\n prose[0] = trimmed;\n data.append({\n type: 'block',\n value: { index: 0, ...synthetic }\n });\n } else if (text) {\n const firstPbIdx = blocks.findIndex(\n (b) => b.kind === 'paragraph_brief'\n );\n if (firstPbIdx >= 0) prose[firstPbIdx] = text;\n }\n\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: blocks.length ? blocks : null,\n prose: Object.keys(prose).length ? prose : null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n err: (err as Error).message\n },\n '[agent-vercel] failed to persist assistant turn'\n );\n } finally {\n try {\n await data.close();\n } catch {\n // already closed\n }\n }\n }\n });\n\n // The Vercel AI SDK runs the loop lazily as the response stream is\n // consumed; `toDataStreamResponse` returns a Response whose body\n // pulls from `result` on demand. `onSessionEnd` fires in the\n // `finally` below, but it must NOT wait on the stream (the route\n // returns before the client has consumed it). The lifecycle hook\n // therefore runs at request-handler exit, not stream completion —\n // matching the custom-route's `onSessionEnd` contract (always-runs,\n // never throws out).\n return result.toDataStreamResponse({ data });\n } catch (e) {\n const message = (e as Error).message ?? 'Internal error';\n persistedError = { code: 'INTERNAL', message };\n logger?.error?.(\n { chatSessionId, sessionId, err: message },\n '[agent-vercel] route errored'\n );\n try {\n data.append({\n type: 'error',\n value: { code: 'INTERNAL', message }\n });\n } catch {\n // ignore — stream already closed.\n }\n try {\n await data.close();\n } catch {\n // ignore.\n }\n // Persist the assistant error so the session row is consistent.\n try {\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: null,\n prose: null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n { chatSessionId, sessionId, err: (err as Error).message },\n '[agent-vercel] failed to persist error turn'\n );\n }\n return jsonError(500, 'INTERNAL', message);\n } finally {\n // Always-runs teardown, symmetric to agent-custom. Errors here are\n // logged but never surfaced.\n if (hooks?.onSessionEnd) {\n const cause: 'complete' | 'error' | 'abort' = req.signal.aborted\n ? 'abort'\n : persistedError\n ? 'error'\n : 'complete';\n try {\n await hooks.onSessionEnd({\n scope: callerScope,\n sessionId,\n userId,\n cause\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n sessionStarted,\n err: (err as Error).message\n },\n '[agent-vercel] onSessionEnd hook failed'\n );\n }\n }\n }\n }\n };\n}\n","/**\n * `chat-sessions` route factory — host-agnostic CRUD for chat sessions.\n *\n * Mounts at `/api/chat/sessions` (list+create) and `/api/chat/sessions/[id]`\n * (get one with messages, rename, delete). Auth and persistence cross the\n * boundary as ports; the package never touches a DB or session adapter.\n *\n * Wire format mirrors the host's pre-extraction Next route handlers so the\n * existing UI keeps working unchanged when the host swaps to these factories.\n */\nimport type { AuthPort, LoggerPort, PersistencePort, ChatSession } from '../ports/types';\nimport type { RouteHooks } from './agent-custom';\n\nexport type ChatSessionsRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n logger?: LoggerPort;\n /**\n * Optional pre-auth / post-auth hooks (e.g. shutdown gate, rate\n * limiting). The streaming-specific hooks on `AgentCustomHooks` are\n * ignored here — only `onRequest` and `onAuthenticated` apply.\n */\n hooks?: RouteHooks<S>;\n};\n\nconst DEFAULT_TITLE = 'New chat';\nconst TITLE_MAX = 200;\n\n// ---------------------------------------------------------------------------\n// Tiny inline response helpers — kept here so the package has no shared\n// `lib/api` of its own. These mirror the slice of the host's `apiError`\n// envelope the chat routes actually emit.\n// ---------------------------------------------------------------------------\n\ntype ApiErrorCode =\n | 'UNAUTHORIZED'\n | 'NOT_FOUND'\n | 'VALIDATION_FAILED'\n | 'INTERNAL';\n\nconst STATUS_BY_CODE: Record<ApiErrorCode, number> = {\n UNAUTHORIZED: 401,\n NOT_FOUND: 404,\n VALIDATION_FAILED: 400,\n INTERNAL: 500\n};\n\nfunction apiError(code: ApiErrorCode, message: string): Response {\n return Response.json(\n { error: { code, message, details: {} } },\n { status: STATUS_BY_CODE[code] }\n );\n}\n\nfunction okJson(data: unknown): Response {\n return Response.json(data);\n}\n\n// ---------------------------------------------------------------------------\n// Serialisation — domain types use Date; the wire format is ISO strings.\n// ---------------------------------------------------------------------------\n\nfunction serializeSession(s: ChatSession) {\n return {\n id: s.id,\n title: s.title,\n createdAt: s.createdAt ? s.createdAt.toISOString() : null,\n updatedAt: s.updatedAt ? s.updatedAt.toISOString() : null\n };\n}\n\nfunction parseSessionId(raw: string): number | null {\n const id = Number(raw);\n if (!Number.isInteger(id) || id <= 0) return null;\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>) {\n const { persistence, auth, logger, hooks } = ctx;\n\n /**\n * Run the standard hook chain (`onRequest` → auth → `onAuthenticated`)\n * shared by every handler below. Returns either a short-circuit\n * Response (hook said no, or auth failed) OR the resolved scope/userId\n * for the handler to continue with.\n */\n async function gate(\n req: Request\n ): Promise<{ short: Response } | { ok: true; scope: S; userId: number }> {\n if (hooks?.onRequest) {\n const r = await hooks.onRequest(req);\n if (r) return { short: r };\n }\n const authed = await auth.requireAuth(req);\n if (!authed.ok) return { short: authed.response };\n if (hooks?.onAuthenticated) {\n const r = await hooks.onAuthenticated({\n req,\n scope: authed.scope,\n userId: authed.userId\n });\n if (r) return { short: r };\n }\n return { ok: true, scope: authed.scope, userId: authed.userId };\n }\n\n const list = {\n /**\n * `GET /api/chat/sessions` — caller's recent sessions, newest first,\n * capped at 100. Response: `{ sessions: [{ id, title, createdAt, updatedAt }] }`.\n */\n GET: async (req: Request): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const rows = await persistence.listSessionsForUser(g.userId, { limit: 100 });\n return okJson({ sessions: rows.map(serializeSession) });\n } catch (err) {\n logger?.error('[chat-sessions] list.GET failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `POST /api/chat/sessions` — body `{ title?: string }`. Trims and caps\n * title at 200 chars; defaults to \"New chat\" when blank.\n * Response: `{ session: { id, title, createdAt, updatedAt } }`.\n */\n POST: async (req: Request): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const body = (await req.json().catch(() => ({}))) as { title?: unknown };\n const rawTitle = typeof body.title === 'string' ? body.title.trim() : '';\n const title = rawTitle ? rawTitle.slice(0, TITLE_MAX) : DEFAULT_TITLE;\n const created = await persistence.createSession({ userId: g.userId, title });\n return okJson({ session: serializeSession(created) });\n } catch (err) {\n logger?.error('[chat-sessions] list.POST failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n }\n };\n\n const detail = {\n /**\n * `GET /api/chat/sessions/[id]` — session metadata + ordered messages.\n * 404 when the id doesn't exist or doesn't belong to the caller (we never\n * differentiate the two, to avoid leaking the id space).\n * Response: `{ session: { id, title, createdAt, updatedAt },\n * messages: [{ id, role, question, blocks, prose, errorJson, createdAt }] }`.\n */\n GET: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n const messages = await persistence.listMessagesForSession(id, g.userId);\n return okJson({\n session: serializeSession(meta),\n messages: messages.map((m) => ({\n id: m.id,\n role: m.role,\n question: m.question,\n blocks: m.blocks,\n prose: m.prose,\n errorJson: m.errorJson,\n createdAt: m.createdAt ? m.createdAt.toISOString() : null\n }))\n });\n } catch (err) {\n logger?.error('[chat-sessions] detail.GET failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `PATCH /api/chat/sessions/[id]` — rename. Body `{ title: string }`,\n * trimmed and capped at 200 chars. Response: `{ ok: true }`.\n */\n PATCH: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n\n const body = (await req.json().catch(() => ({}))) as { title?: unknown };\n if (typeof body.title !== 'string') {\n return apiError('VALIDATION_FAILED', 'title must be a string.');\n }\n const trimmed = body.title.trim();\n if (!trimmed) {\n return apiError('VALIDATION_FAILED', 'title must not be empty.');\n }\n await persistence.updateSession(id, g.userId, {\n title: trimmed.slice(0, TITLE_MAX)\n });\n return okJson({ ok: true });\n } catch (err) {\n logger?.error('[chat-sessions] detail.PATCH failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `DELETE /api/chat/sessions/[id]` — drop session and its messages.\n * Response: `{ ok: true }`.\n */\n DELETE: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n await persistence.deleteSession(id, g.userId);\n return okJson({ ok: true });\n } catch (err) {\n logger?.error('[chat-sessions] detail.DELETE failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n }\n };\n\n return { list, detail };\n}\n","/**\n * `/api/admin/ai-settings` route factory — global AI configuration (super_admin only).\n *\n * Three patchable fields on the singleton settings row:\n * - `tool_provider` — vendor that drives the agent tool loop. Validated\n * against the registered `toolProviders` registry passed in via ctx.\n * - `gcp_location` — the Vertex region every provider call hits. Stays\n * a fixed list ('us-east5', 'global') because those are the only\n * regions Claude/Gemini are published in on Vertex.\n * - `chat_interface` — which chat UI module renders globally. Validated\n * against the `chatInterfaces` registry passed in via ctx (the actual\n * registry lives in `@firstlovecenter/ai-chat/ui` so the host wires it through;\n * the route stays free of UI imports).\n *\n * Wire format is snake_case to preserve byte-for-byte parity with the\n * host route the package replaces — existing host UIs keep working\n * unmodified.\n */\nimport type { AuthPort, LoggerPort, PersistencePort, AiSettingsPatch } from '../ports/types';\nimport type { RouteHooks } from './agent-custom';\n\nexport type AdminSettingsRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n /** Registered tool providers (default: built-in toolProviders array). */\n toolProviders: { id: string; label?: string; description?: string }[];\n /** Registered chat interface ids (host or UI module supplies the list). */\n chatInterfaces: { id: string }[];\n logger?: LoggerPort;\n /**\n * Optional pre-auth / post-auth hooks (e.g. shutdown gate, rate\n * limiting). Streaming-specific hooks are not applicable here.\n */\n hooks?: RouteHooks<S>;\n};\n\nconst VALID_LOCATIONS = ['us-east5', 'global'] as const;\n\ntype WireSettings = {\n tool_provider: string;\n gcp_location: string;\n chat_interface: string;\n updated_at: string | null;\n updated_by_user_id: number | null;\n};\n\nfunction isStringRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction jsonResponse(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' }\n });\n}\n\nfunction toWire(settings: {\n toolProvider: string;\n gcpLocation: string;\n chatInterface: string;\n updatedAt: Date | null;\n updatedByUserId: number | null;\n}): WireSettings {\n return {\n tool_provider: settings.toolProvider,\n gcp_location: settings.gcpLocation,\n chat_interface: settings.chatInterface,\n updated_at: settings.updatedAt ? settings.updatedAt.toISOString() : null,\n updated_by_user_id: settings.updatedByUserId\n };\n}\n\nexport function createAdminSettingsRoutes<S>(ctx: AdminSettingsRouteCtx<S>) {\n const { persistence, auth, toolProviders, chatInterfaces, logger, hooks } = ctx;\n\n async function GET(req: Request): Promise<Response> {\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n const result = await auth.requireAuth(req);\n if (!result.ok) return result.response;\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: result.scope,\n userId: result.userId\n });\n if (short) return short;\n }\n if (!auth.isSuperAdmin(result.scope)) {\n return jsonResponse(\n { error: 'forbidden', message: 'Only super admins can read AI settings.' },\n 403\n );\n }\n const settings = await persistence.getAiSettings();\n return jsonResponse(toWire(settings));\n }\n\n async function PATCH(req: Request): Promise<Response> {\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n const result = await auth.requireAuth(req);\n if (!result.ok) return result.response;\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: result.scope,\n userId: result.userId\n });\n if (short) return short;\n }\n if (!auth.isSuperAdmin(result.scope)) {\n return jsonResponse(\n { error: 'forbidden', message: 'Only super admins can change AI settings.' },\n 403\n );\n }\n\n const body = (await req.json().catch(() => null)) as unknown;\n if (!isStringRecord(body)) {\n return jsonResponse({ error: 'invalid_body', message: 'Body must be JSON.' }, 400);\n }\n\n const patch: AiSettingsPatch = {};\n\n if ('tool_provider' in body) {\n const v = body.tool_provider;\n const validIds = toolProviders.map((p) => p.id);\n if (typeof v !== 'string' || !validIds.includes(v)) {\n return jsonResponse({ error: 'invalid_tool_provider' }, 400);\n }\n patch.toolProvider = v;\n }\n\n if ('gcp_location' in body) {\n const v = body.gcp_location;\n if (typeof v !== 'string' || !VALID_LOCATIONS.includes(v as (typeof VALID_LOCATIONS)[number])) {\n return jsonResponse({ error: 'invalid_gcp_location' }, 400);\n }\n patch.gcpLocation = v;\n }\n\n if ('chat_interface' in body) {\n const v = body.chat_interface;\n const validIds = chatInterfaces.map((i) => i.id);\n if (typeof v !== 'string' || !validIds.includes(v)) {\n return jsonResponse({ error: 'invalid_chat_interface' }, 400);\n }\n patch.chatInterface = v;\n }\n\n if (\n patch.toolProvider === undefined &&\n patch.gcpLocation === undefined &&\n patch.chatInterface === undefined\n ) {\n return jsonResponse(\n {\n error: 'empty_patch',\n message: 'Body must set at least one of tool_provider, gcp_location, chat_interface.'\n },\n 400\n );\n }\n\n try {\n const updated = await persistence.updateAiSettings(patch, result.userId);\n return jsonResponse(toWire(updated));\n } catch (err) {\n logger?.error('admin-settings PATCH failed', err);\n throw err;\n }\n }\n\n return { GET, PATCH };\n}\n","/**\n * `configureAiChat({...})` — the runtime factory hosts call once at boot.\n *\n * Takes the five injected ports (persistence, auth, scope, tools, vertex)\n * plus a couple of optional bits (logger, narrator resolver, chat-interface\n * registry, extra tool providers) and returns:\n *\n * - `runAgent` — pre-bound agent loop wrapper.\n * - `routes.agentCustom` — Next-compatible POST handler for the SSE chat.\n * - `routes.chatSessions` — list/POST + detail GET/PATCH/DELETE.\n * - `routes.adminSettings`— admin GET/PATCH.\n * - `registries.toolProviders` — built-in (claude, gemini) plus any host extras.\n *\n * The host wires each route in its own `app/api/.../route.ts` as a thin\n * re-export. Nothing in this package reads `process.env` or imports from\n * the host.\n */\nimport { runAgent as runAgentLoop } from './agent';\nimport type { AgentResult, AgentInput } from './agent';\nimport {\n toolProviders as BUILTIN_TOOL_PROVIDERS,\n getToolProvider as builtinGetToolProvider\n} from './providers';\nimport type { ToolProviderDef } from './providers';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from './ports/types';\nimport type { ToolContext, ToolDefinition } from './tools/types';\nimport { createAgentCustomRoutes } from './routes/agent-custom';\nimport type { AgentCustomHooks } from './routes/agent-custom';\nimport { createAgentVercelRoutes } from './routes/agent-vercel';\nimport { createChatSessionsRoutes } from './routes/chat-sessions';\nimport { createAdminSettingsRoutes } from './routes/admin-settings';\n\n/** Default ids that match the components shipped in `@firstlovecenter/ai-chat/ui`. */\nexport const BUILTIN_CHAT_INTERFACE_IDS = ['custom', 'vercel'] as const;\n\nexport type ChatInterfaceRegistryEntry = { id: string };\n\nexport type ConfigureAiChatOpts<S = unknown> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Resolve which narrator drives the prose pass. Defaults to the\n * current `aiSettings.toolProvider` (claude → claude narrator, gemini →\n * gemini narrator). Override when the host stores a per-user choice.\n */\n resolveNarratorId?: (scope: S) => Promise<'claude' | 'gemini' | 'grok'>;\n /**\n * Chat-interface ids the admin route accepts. Defaults to\n * BUILTIN_CHAT_INTERFACE_IDS (custom, vercel). Hosts that ship only one\n * UI can subset; hosts that register a new one extend.\n */\n chatInterfaces?: ChatInterfaceRegistryEntry[];\n /**\n * Additional tool-calling providers beyond the built-in claude/gemini.\n * Merged into the registry the admin route validates against.\n */\n extraToolProviders?: ToolProviderDef[];\n /**\n * Optional lifecycle hooks shared across all three route factories.\n * The full superset (`AgentCustomHooks`) covers the SSE chat route;\n * `chatSessions` and `adminSettings` only consume the\n * `onRequest` / `onAuthenticated` subset.\n *\n * Common host plumbing this enables (without forking the package):\n * - `onRequest` — shutdown gating (503 + Retry-After).\n * - `onAuthenticated` — per-user rate limiting (429 + Retry-After).\n * - `generateSessionId`— project-specific session ids (e.g. SQL view names).\n * - `onSessionStart` — per-request resource setup (e.g. CREATE VIEW).\n * - `onSessionEnd` — cleanup (always-runs, never throws out).\n */\n hooks?: AgentCustomHooks<S>;\n /**\n * Persona / role given to the AI as the very first cached system block\n * on every turn. Use this to give the assistant a consistent voice and\n * domain perspective across all conversations in your app.\n *\n * Accepts:\n * - a `string` for a static org-wide role, or\n * - a `(ctx) => string | Promise<string>` function for per-request\n * variation (different role per scope, per locale, per A/B cohort).\n *\n * Token economics: the role text is sent on every turn (Vertex APIs\n * are stateless), but it is marked `cached: true`. On Claude that\n * becomes an ephemeral `cache_control` marker — first turn pays ~1.25×\n * for the cache write; subsequent turns within ~5 min pay ~0.1× for\n * cache reads. On Gemini the hint is informational; Vertex auto-caches\n * stable prefixes regardless. For a typical 200–500 token role, the\n * per-turn marginal cost after the first is negligible. The package\n * caps total `cache_control` markers at Anthropic's 4-per-request\n * limit; if the host already marks 4 blocks cached, the extras\n * (including this one if last) silently drop the cache hint rather\n * than reject the request.\n *\n * Example (static):\n * rolePrompt: `You are the head pastor of First Love Center, a\n * multinational church operating across multiple countries. Frame\n * answers from the perspective of advancing the gospel through\n * sustainable growth, financial discipline, compliance, and church\n * planting. Be direct, pastoral, and action-oriented.`\n */\n rolePrompt?: string | ((ctx: ToolContext<S>) => string | Promise<string>);\n};\n\nexport type AiChatRuntime<S = unknown> = {\n /**\n * Pre-bound agent loop. Most hosts call routes instead — but the bound\n * runner is exposed for non-HTTP entry points (jobs, eval harnesses).\n */\n runAgent: (input: {\n question: string;\n ctx: ToolContext<S>;\n /** Override the provider id picked from `aiSettings.toolProvider`. */\n providerId?: string;\n /** Override the location picked from `aiSettings.gcpLocation`. */\n location?: string;\n maxToolTurns?: number;\n maxOutputTokens?: number;\n }) => Promise<AgentResult>;\n routes: {\n agentCustom: ReturnType<typeof createAgentCustomRoutes<S>>;\n agentVercel: ReturnType<typeof createAgentVercelRoutes<S>>;\n chatSessions: ReturnType<typeof createChatSessionsRoutes<S>>;\n adminSettings: ReturnType<typeof createAdminSettingsRoutes<S>>;\n };\n registries: {\n toolProviders: ToolProviderDef[];\n chatInterfaces: ChatInterfaceRegistryEntry[];\n };\n};\n\nexport function configureAiChat<S = unknown>(\n opts: ConfigureAiChatOpts<S>\n): AiChatRuntime<S> {\n const toolProviders = [\n ...BUILTIN_TOOL_PROVIDERS,\n ...(opts.extraToolProviders ?? [])\n ];\n const getProvider = (id: string): ToolProviderDef | undefined =>\n toolProviders.find((p) => p.id === id) ?? builtinGetToolProvider(id);\n\n const chatInterfaces: ChatInterfaceRegistryEntry[] =\n opts.chatInterfaces ?? BUILTIN_CHAT_INTERFACE_IDS.map((id) => ({ id }));\n\n // Wrap the host's `buildSystemBlocks` so the role prompt is always\n // the first (cached) system block when configured. Both the bound\n // runAgent and the agent-custom route consume `tools` through this\n // wrapper, so the role is applied uniformly.\n const tools: ToolsPort = opts.rolePrompt\n ? {\n tools: opts.tools.tools,\n async buildSystemBlocks(ctx) {\n const inner = await opts.tools.buildSystemBlocks(ctx);\n const rolePrompt = opts.rolePrompt!;\n const role =\n typeof rolePrompt === 'function'\n ? await rolePrompt(ctx as ToolContext<S>)\n : rolePrompt;\n if (!role || !role.trim()) return inner;\n return [{ text: role, cached: true }, ...inner];\n }\n }\n : opts.tools;\n\n const runAgentBound: AiChatRuntime<S>['runAgent'] = async ({\n question,\n ctx,\n providerId,\n location,\n maxToolTurns,\n maxOutputTokens\n }) => {\n const settings = await opts.persistence.getAiSettings();\n const def = getProvider(providerId ?? settings.toolProvider);\n if (!def) {\n throw new Error(\n `Unknown tool provider '${providerId ?? settings.toolProvider}'. ` +\n `Registered: ${toolProviders.map((p) => p.id).join(', ')}.`\n );\n }\n const provider = def.createProvider({\n auth: opts.vertex.auth,\n projectId: opts.vertex.projectId,\n defaultLocation: opts.vertex.defaultLocation,\n modelIds: opts.vertex.modelIds,\n location: location ?? settings.gcpLocation\n });\n const systemBlocks = await tools.buildSystemBlocks(ctx);\n const input: AgentInput<S> = {\n question,\n ctx,\n tools: tools.tools as Record<string, ToolDefinition<unknown, S>>,\n systemBlocks,\n provider,\n maxToolTurns,\n maxOutputTokens\n };\n return runAgentLoop(input);\n };\n\n // The non-streaming routes only see the common subset of hooks; the\n // SSE route gets the full superset including session-lifecycle.\n const sharedHooks = opts.hooks\n ? {\n onRequest: opts.hooks.onRequest,\n onAuthenticated: opts.hooks.onAuthenticated\n }\n : undefined;\n\n const agentCustom = createAgentCustomRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n scope: opts.scope,\n tools,\n vertex: opts.vertex,\n logger: opts.logger,\n resolveNarratorId: opts.resolveNarratorId,\n hooks: opts.hooks\n });\n\n // The Vercel AI SDK chat consumes the same wrapped `tools` (so the role\n // prompt applies on both transports) and the same hooks bag. Lifecycle\n // semantics are identical — `AgentVercelHooks` is an alias for\n // `AgentCustomHooks`.\n const agentVercel = createAgentVercelRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n scope: opts.scope,\n tools,\n vertex: opts.vertex,\n logger: opts.logger,\n hooks: opts.hooks\n });\n\n const chatSessions = createChatSessionsRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n logger: opts.logger,\n hooks: sharedHooks\n });\n\n const adminSettings = createAdminSettingsRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n toolProviders,\n chatInterfaces,\n logger: opts.logger,\n hooks: sharedHooks\n });\n\n return {\n runAgent: runAgentBound,\n routes: { agentCustom, agentVercel, chatSessions, adminSettings },\n registries: { toolProviders, chatInterfaces }\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/server/tools/types.ts","../../src/server/agent.ts","../../src/server/providers/claude.ts","../../src/server/providers/schema.ts","../../src/server/providers/gemini.ts","../../src/server/providers/index.ts","../../src/server/narrators/_vertex.ts","../../src/server/narrators/claude.ts","../../src/server/narrators/gemini.ts","../../src/server/narrators/grok.ts","../../src/server/narrators/index.ts","../../src/server/routes/agent-custom.ts","../../src/server/vercel-adapter.ts","../../src/server/routes/agent-vercel.ts","../../src/server/routes/chat-sessions.ts","../../src/server/routes/admin-settings.ts","../../src/server/configure.ts"],"names":["tool","AnthropicVertex","parts","vertexHost","patchVertexBuildRequestSync","MODEL_ENDPOINTS","VERTEX_DEFAULT_VERSION","isObj","NARRATIVE_SYSTEM","safeReadText","randomUUID","err","jsonError","defaultGenerateSessionId","StreamData","createVertexAnthropic","createVertex","streamText","toolProviders"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Tool typing for the agent loop.\n *\n * `ToolContext<S>` is the per-request \"session\" handed to every tool. It\n * carries the resolved Scope (so tools can inject scope filters without\n * trusting their own arguments) and a per-session view suffix (so SQL-ish\n * tools can point the LLM at session-scoped views). The Scope shape itself\n * is opaque to this package — `S` is whatever the host configures.\n *\n * `ToolDefinition` is what we hand to the model adapter plus the function\n * that backs the tool name. The agent loop dispatches on `name` and calls\n * `execute(input, ctx)`; the result is JSON-serialised back to the model.\n */\n\nexport type ToolContext<S = unknown> = {\n /** Host-supplied scope (RBAC / tenancy). The package never inspects the shape. */\n scope: S;\n /** Stable per-conversation id (string). Tools may use this for session-scoped views. */\n sessionId: string;\n /** Short human label for diagnostics — e.g. \"Ghana\", \"all 8 countries\". */\n scopeSummary: string;\n /** Number of structured tool calls made before `present` was invoked. */\n toolCallCount: number;\n};\n\nexport type ToolSchema = {\n name: string;\n description: string;\n /** JSON Schema. The package's Vertex Gemini adapter normalises this; the Vercel adapter converts to Zod. */\n input_schema: Record<string, unknown>;\n};\n\nexport type ToolResult =\n | { ok: true; data: unknown }\n | { ok: false; error: { code: string; message: string } };\n\nimport type { ZodType } from 'zod';\n\nexport type ToolDefinition<I = unknown, S = unknown> = {\n schema: ToolSchema;\n /**\n * Optional Zod schema for the same input. Required by the Vercel AI SDK\n * route (which needs Zod to feed `tool({ parameters })`); the custom\n * SSE route ignores it. Tools registered without a `zodSchema` will\n * cause `buildVercelTools` to throw at config time.\n */\n zodSchema?: ZodType<I>;\n execute(input: I, ctx: ToolContext<S>): Promise<ToolResult>;\n};\n\n/** The terminal tool that closes the agent loop. The host's tool registry MUST include it. */\nexport const TERMINAL_TOOL_NAME = 'present';\n\nexport function ok(data: unknown): ToolResult {\n return { ok: true, data };\n}\n\nexport function err(code: string, message: string): ToolResult {\n return { ok: false, error: { code, message } };\n}\n\n// ---------------------------------------------------------------------------\n// Block types — what `present` returns and what AnswerBlocks renders\n// ---------------------------------------------------------------------------\n\nexport type ChartSpec = {\n type: 'line' | 'bar' | 'stacked_bar' | 'pie';\n x: string;\n y: string | string[];\n series?: string;\n};\n\nexport type Block =\n | { kind: 'paragraph_brief'; topic: string; key_facts: string[] }\n | { kind: 'list'; style: 'bullet' | 'numbered'; items: string[]; title?: string }\n | { kind: 'chart'; title: string; spec: ChartSpec; data: Array<Record<string, unknown>> }\n | { kind: 'table'; title: string; columns: string[]; rows: unknown[][] }\n | { kind: 'callout'; tone: 'info' | 'warn' | 'success'; text: string };\n\nexport type PresentPayload = {\n blocks: Block[];\n raw_numbers: Record<string, number | string>;\n};\n\n// ---------------------------------------------------------------------------\n// SystemBlock — system prompt segments (provider-agnostic cache hint)\n// ---------------------------------------------------------------------------\n\nexport type SystemBlock = {\n text: string;\n /**\n * Mark for ephemeral prompt caching where the provider supports it.\n * Anthropic translates this to `cache_control: ephemeral`; Gemini ignores\n * it (Vertex auto-caches stable prefixes). Both still see the same text.\n */\n cached?: boolean;\n};\n","/**\n * Agent tool loop.\n *\n * Drives an injected `ToolProvider` (Claude on Vertex, Gemini on Vertex,\n * or any future adapter that satisfies the contract) with a host-supplied\n * tool catalogue until the model invokes the terminal `present` tool (or\n * hits a hard stop without calling it). Returns the structured\n * `PresentPayload`; the prose narrator pass happens in the route handler.\n *\n * Caching: the system prompt blocks are passed through as the host built\n * them. Blocks marked `cached: true` become Anthropic ephemeral cache\n * markers; Gemini ignores the flag and relies on Vertex's automatic prefix\n * caching. Either way a follow-up question within the cache TTL only pays\n * for the question + tool turns.\n *\n * This package's loop is project-agnostic: tools, prompts, and the\n * provider instance are all injected via `AgentInput`. The host owns the\n * registry (`ToolsPort.tools`), the system blocks (`ToolsPort.buildSystemBlocks`),\n * and the constructed provider (resolved through `toolProviders[id].createProvider`).\n */\nimport type {\n PresentPayload,\n SystemBlock,\n ToolContext,\n ToolDefinition\n} from './tools/types';\nimport { TERMINAL_TOOL_NAME } from './tools/types';\nimport type {\n NormalizedMessage,\n NormalizedToolResult,\n ToolProvider\n} from './providers/types';\n\nexport const DEFAULT_MAX_TOOL_TURNS = 12;\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 4096;\n\nexport type AgentResult =\n | { ok: true; structured: PresentPayload; toolCallCount: number; transcript: TranscriptEntry[] }\n | { ok: false; error: { code: string; message: string }; transcript: TranscriptEntry[] };\n\nexport type TranscriptEntry =\n | { kind: 'user'; text: string }\n | { kind: 'assistant_text'; text: string }\n | { kind: 'tool_use'; name: string; input: unknown }\n | { kind: 'tool_result'; name: string; result: unknown };\n\nexport type AgentInput<S = unknown> = {\n question: string;\n ctx: ToolContext<S>;\n /** Injected tool registry (host-supplied via ToolsPort). MUST include the terminal `present` tool. */\n tools: Record<string, ToolDefinition<unknown, S>>;\n /** Pre-built system blocks (host-supplied via ToolsPort.buildSystemBlocks). */\n systemBlocks: SystemBlock[];\n /** Constructed ToolProvider — caller resolves the right one via toolProviders[id].createProvider({...}). */\n provider: ToolProvider;\n /** Optional caps. Default both. */\n maxToolTurns?: number;\n maxOutputTokens?: number;\n};\n\nexport async function runAgent<S = unknown>(input: AgentInput<S>): Promise<AgentResult> {\n const provider = input.provider;\n const maxToolTurns = input.maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;\n const maxOutputTokens = input.maxOutputTokens ?? DEFAULT_MAX_OUTPUT_TOKENS;\n\n const transcript: TranscriptEntry[] = [];\n transcript.push({ kind: 'user', text: input.question });\n\n const messages: NormalizedMessage[] = [{ role: 'user', text: input.question }];\n const system = input.systemBlocks;\n const toolSchemas = Object.values(input.tools).map((t) => t.schema);\n\n let toolCallCount = 0;\n let presentPayload: PresentPayload | null = null;\n\n for (let turn = 0; turn < maxToolTurns; turn++) {\n const response = await provider.runTurn({\n system,\n tools: toolSchemas,\n messages,\n maxOutputTokens\n });\n\n if (response.text) {\n transcript.push({ kind: 'assistant_text', text: response.text });\n }\n\n if (response.toolCalls.length === 0) {\n // Model ended its turn without a tool call. If we already had a\n // present payload (shouldn't happen — present terminates the loop\n // below), use it.\n if (presentPayload) break;\n\n // Fallback: model emitted text but never reached present(). Most\n // commonly happens for advisory / strategic questions that don't\n // map to any data tool (\"what should we do to ...?\"). Wrap the\n // text as a paragraph_brief block so the user always gets the\n // model's answer instead of a generic \"try rephrasing\" error.\n // The SELF_VERIFY_REQUIRED gate still fires when present() is\n // called explicitly — this synthetic path runs only when the\n // model chose not to use any tools at all.\n const text = (response.text ?? '').trim();\n if (text) {\n const topic =\n input.question.length > 80\n ? input.question.slice(0, 77) + '...'\n : input.question;\n presentPayload = {\n blocks: [\n {\n kind: 'paragraph_brief',\n topic,\n key_facts: [text]\n }\n ],\n raw_numbers: {}\n };\n break;\n }\n\n // No tool calls AND no text — genuine dead end. Surface the error.\n return {\n ok: false,\n error: {\n code: 'AGENT_NO_PRESENT',\n message: 'The agent produced no response. Try rephrasing.'\n },\n transcript\n };\n }\n\n messages.push({\n role: 'assistant',\n text: response.text,\n toolCalls: response.toolCalls,\n providerData: response.providerData\n });\n\n const toolResults: NormalizedToolResult[] = [];\n\n for (const tc of response.toolCalls) {\n transcript.push({ kind: 'tool_use', name: tc.name, input: tc.input });\n const tool = input.tools[tc.name];\n if (!tool) {\n const errResult = {\n ok: false as const,\n error: { code: 'UNKNOWN_TOOL', message: `Unknown tool: ${tc.name}` }\n };\n transcript.push({ kind: 'tool_result', name: tc.name, result: errResult });\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: true,\n content: JSON.stringify(errResult.error)\n });\n continue;\n }\n const result = await tool.execute(tc.input as unknown, {\n ...input.ctx,\n toolCallCount\n });\n transcript.push({ kind: 'tool_result', name: tc.name, result });\n toolCallCount += 1;\n\n if (tc.name === TERMINAL_TOOL_NAME && result.ok) {\n // Enforce: ≥ 2 prior tool calls (primary + cross-check) before\n // present. toolCallCount has been incremented for present, so a\n // count < 3 means there were < 2 prior calls.\n if (toolCallCount < 3) {\n const violation = {\n code: 'SELF_VERIFY_REQUIRED',\n message:\n 'Per FR-8.3 you must run at least one CROSS-CHECK tool call (a different metric, a different period, or a run_sql sanity-check) before present. Make that extra call now, then call present again.'\n };\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: true,\n content: JSON.stringify(violation)\n });\n continue;\n }\n presentPayload = result.data as PresentPayload;\n break;\n }\n\n toolResults.push({\n toolCallId: tc.id,\n toolName: tc.name,\n isError: !result.ok,\n content: JSON.stringify(result.ok ? result.data : result.error)\n });\n }\n\n if (presentPayload) break;\n messages.push({ role: 'tool', results: toolResults });\n }\n\n if (!presentPayload) {\n return {\n ok: false,\n error: {\n code: 'AGENT_TURN_LIMIT',\n message: `Agent exceeded the ${maxToolTurns}-turn budget without calling present().`\n },\n transcript\n };\n }\n\n // Salvage: the model called present() but produced a payload whose\n // every block is empty (the user sees a row of empty placeholder\n // boxes). Happens when the model is forced through SELF_VERIFY_REQUIRED\n // for an advisory question that doesn't actually have data to back —\n // it satisfies the schema with empty strings. Recover by replacing\n // the payload with a synthetic paragraph_brief built from the most\n // recent assistant text in the transcript, falling back to the older\n // `model emitted text but no present()` path. The user gets the\n // model's actual reasoning instead of empty boxes.\n if (allBlocksEmpty(presentPayload.blocks)) {\n const lastAssistantText = [...transcript]\n .reverse()\n .find((e) => e.kind === 'assistant_text') as\n | { kind: 'assistant_text'; text: string }\n | undefined;\n const text = lastAssistantText?.text.trim();\n if (text) {\n const topic =\n input.question.length > 80\n ? input.question.slice(0, 77) + '...'\n : input.question;\n presentPayload = {\n blocks: [\n {\n kind: 'paragraph_brief',\n topic,\n key_facts: [text]\n }\n ],\n raw_numbers: presentPayload.raw_numbers ?? {}\n };\n }\n }\n\n return { ok: true, structured: presentPayload, toolCallCount, transcript };\n}\n\n/**\n * True when every block in the present payload is functionally empty —\n * no rendered content the user can see. Used to detect models that\n * satisfy the present() schema with placeholder strings after being\n * forced through SELF_VERIFY_REQUIRED on a question that has no data\n * answer. Each block kind has its own emptiness rule.\n */\nfunction allBlocksEmpty(blocks: PresentPayload['blocks']): boolean {\n if (blocks.length === 0) return true;\n return blocks.every((b) => {\n if (b.kind === 'paragraph_brief') {\n return b.key_facts.length === 0 || b.key_facts.every((f) => !f.trim());\n }\n if (b.kind === 'list') {\n return b.items.length === 0 || b.items.every((i) => !i.trim());\n }\n if (b.kind === 'callout') {\n return !b.text.trim();\n }\n if (b.kind === 'chart') {\n return b.data.length === 0;\n }\n if (b.kind === 'table') {\n return b.rows.length === 0;\n }\n return false;\n });\n}\n","/**\n * Claude (Anthropic Messages API on GCP Vertex) — `ToolProvider` adapter.\n *\n * Wraps `AnthropicVertex` with the same `buildRequest` sync-patch the host\n * applies, then translates the agent loop's normalized message log to\n * Anthropic's `MessageParam[]` shape on the way in, and the response's\n * `ContentBlock[]` back to `{ text, toolCalls, stopReason }` on the way\n * out. Ephemeral cache markers are applied to system blocks where the\n * agent loop opted in, so the `system + schema + semantic-layer +\n * scope-summary` prefix stays cached across follow-up turns.\n *\n * Credentials come in as a host-supplied `GoogleAuth` instance; the\n * package never reads `process.env.GCP_*`.\n */\nimport { AnthropicVertex } from '@anthropic-ai/vertex-sdk';\nimport type {\n ContentBlock,\n MessageParam,\n ToolUseBlock\n} from '@anthropic-ai/sdk/resources/messages';\nimport type { GoogleAuth } from 'google-auth-library';\nimport type {\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n ToolProvider\n} from './types';\n\n/**\n * `TextBlockParam` in @anthropic-ai/sdk@0.50 doesn't include\n * `cache_control` in its types, but the production API accepts it on the\n * standard messages endpoint. Local widened type so callers don't need\n * `as any` everywhere.\n */\ntype CachedTextBlock = {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n};\n\nexport type ClaudeProviderOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Vertex region (e.g. 'us-east5' or 'global'). */\n location: string;\n /** Model id pinned by the host (e.g. 'claude-opus-4-7@20250514'). */\n modelId: string;\n};\n\nexport class ClaudeToolProvider implements ToolProvider {\n readonly id = 'claude' as const;\n private client: AnthropicVertex;\n private modelId: string;\n\n constructor(opts: ClaudeProviderOpts) {\n this.modelId = opts.modelId;\n this.client = new AnthropicVertex({\n projectId: opts.projectId,\n region: opts.location,\n googleAuth: opts.auth\n });\n patchVertexBuildRequestSync(this.client);\n }\n\n async runTurn(input: AgentTurnInput): Promise<AgentTurn> {\n // Anthropic caps cache_control markers at 4 per request. If the host\n // (or our role-prompt wrapper) marks more than 4 system blocks\n // `cached: true`, keep the first 4 and silently drop the cache hint\n // from any beyond — better than letting the request fail. The first\n // 4 markers are also where caching has the biggest hit rate, since\n // earlier blocks tend to be the most stable across requests.\n let cacheMarkersUsed = 0;\n const MAX_CACHE_MARKERS = 4;\n const system: CachedTextBlock[] = input.system.map((b) => {\n if (b.cached && cacheMarkersUsed < MAX_CACHE_MARKERS) {\n cacheMarkersUsed++;\n return {\n type: 'text',\n text: b.text,\n cache_control: { type: 'ephemeral' as const }\n };\n }\n return { type: 'text', text: b.text };\n });\n const messages = toAnthropicMessages(input.messages);\n\n const response = await this.client.messages.create({\n model: this.modelId,\n max_tokens: input.maxOutputTokens,\n system,\n tools: input.tools as unknown as any[],\n messages\n });\n\n return fromAnthropicResponse(response);\n }\n}\n\n/** Factory matching the package's provider-init contract. */\nexport function createClaudeProvider(opts: ClaudeProviderOpts): ToolProvider {\n return new ClaudeToolProvider(opts);\n}\n\nexport function toAnthropicMessages(\n messages: NormalizedMessage[]\n): MessageParam[] {\n const out: MessageParam[] = [];\n for (const msg of messages) {\n if (msg.role === 'user') {\n out.push({ role: 'user', content: msg.text });\n } else if (msg.role === 'assistant') {\n const blocks: ContentBlock[] = [];\n if (msg.text) {\n blocks.push({ type: 'text', text: msg.text } as ContentBlock);\n }\n for (const tc of msg.toolCalls) {\n blocks.push({\n type: 'tool_use',\n id: tc.id,\n name: tc.name,\n input: tc.input\n } as unknown as ContentBlock);\n }\n out.push({ role: 'assistant', content: blocks });\n } else {\n // tool results — Anthropic models them as a `user` turn whose content\n // is one tool_result block per call.\n const content = msg.results.map((r) => ({\n type: 'tool_result' as const,\n tool_use_id: r.toolCallId,\n is_error: r.isError,\n content: r.content\n }));\n out.push({ role: 'user', content: content as unknown as ContentBlock[] });\n }\n }\n return out;\n}\n\nexport function fromAnthropicResponse(response: {\n content: ContentBlock[];\n stop_reason?: string | null;\n}): AgentTurn {\n const textParts: string[] = [];\n const toolCalls: AgentTurn['toolCalls'] = [];\n for (const block of response.content) {\n if (block.type === 'text') {\n textParts.push(block.text);\n } else if (block.type === 'tool_use') {\n const tu = block as ToolUseBlock;\n toolCalls.push({\n id: tu.id,\n name: tu.name,\n input: (tu.input ?? {}) as Record<string, unknown>\n });\n }\n }\n return {\n text: textParts.join(''),\n toolCalls,\n stopReason: normalizeStopReason(response.stop_reason)\n };\n}\n\nfunction normalizeStopReason(reason: string | null | undefined): AgentTurn['stopReason'] {\n switch (reason) {\n case 'tool_use':\n return 'tool_use';\n case 'end_turn':\n return 'end_turn';\n case 'max_tokens':\n return 'max_tokens';\n default:\n return 'other';\n }\n}\n\n// ---------------------------------------------------------------------------\n// AnthropicVertex `buildRequest` sync-patch\n// ---------------------------------------------------------------------------\n//\n// Works around the ABI mismatch between `@anthropic-ai/vertex-sdk@0.16.0`\n// (declares `buildRequest` as async) and `@anthropic-ai/sdk@0.50.4`\n// (consumes it synchronously). Without this patch, the destructured\n// `{ req, url, timeout }` returns `undefined`s and the SDK throws\n// \"Cannot read properties of undefined (reading 'headers')\" before any\n// HTTP request is sent.\n//\n// The override mirrors the upstream override's body / path rewriting\n// (split into `rawPredict` vs `streamRawPredict`) but returns the parent\n// synchronously instead of wrapping in a Promise.\n\nconst MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);\nconst VERTEX_DEFAULT_VERSION = 'vertex-2023-10-16';\n\nfunction isObj(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction patchVertexBuildRequestSync(client: AnthropicVertex): void {\n const proto = Object.getPrototypeOf(client) as Record<string, unknown>;\n const grandparent = Object.getPrototypeOf(proto) as {\n buildRequest: (...args: unknown[]) => unknown;\n };\n proto.buildRequest = function patchedBuildRequest(\n this: AnthropicVertex & { projectId?: string; region?: string },\n options: { method?: string; path?: string; body?: unknown },\n extra?: unknown\n ) {\n if (isObj(options.body)) {\n options.body = { ...options.body };\n }\n if (isObj(options.body) && !options.body.anthropic_version) {\n options.body.anthropic_version = VERTEX_DEFAULT_VERSION;\n }\n if (\n options.path &&\n MODEL_ENDPOINTS.has(options.path) &&\n options.method === 'post' &&\n isObj(options.body)\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n const model = options.body.model;\n options.body.model = undefined;\n const stream = options.body.stream ?? false;\n const specifier = stream ? 'streamRawPredict' : 'rawPredict';\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${model}:${specifier}`;\n }\n if (\n options.path === '/v1/messages/count_tokens' ||\n (options.path === '/v1/messages/count_tokens?beta=true' && options.method === 'post')\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`;\n }\n return grandparent.buildRequest.call(this, options, extra);\n } as unknown as (typeof proto)['buildRequest'];\n}\n","/**\n * JSON Schema → Vertex Gemini \"function declaration parameters\" translator.\n *\n * Gemini accepts a subset of OpenAPI 3.0 schema for tool parameters. The\n * tool catalogue uses standard JSON Schema (which Anthropic accepts\n * verbatim) and includes a few constructs that need rewriting:\n *\n * - `oneOf` → `anyOf` (Gemini exposes the union as `anyOf`).\n * - `const` → `enum: [value]` with the matching `type`.\n * - `enum` → Vertex enforces TWO rules: every entry must be a\n * string, AND the parent `type` must be `STRING`. So:\n * • all-string enum → kept as-is (already type=string)\n * • numeric enum → dropped, replaced by `minimum`/`maximum`\n * derived from min/max of the values. The model still picks\n * from a bounded range; tools validate the exact value.\n * • boolean enum → dropped (the `boolean` type already\n * constrains the value space to {true, false}).\n * This is the closest semantics-preserving rewrite that keeps\n * Vertex from rejecting the schema.\n * - `additionalProperties` (object form): dropped — Gemini doesn't\n * model nested additionalProperties; we keep the shape declared by\n * `properties` and lose the escape hatch, which is fine for our\n * tools (none of them rely on extra keys).\n * - `type: 'array'` without explicit `items`: Gemini requires `items`,\n * so we default to `{ type: 'string' }` to keep the schema valid.\n *\n * Anything else is passed through. This translator is intentionally\n * conservative: it doesn't try to validate input or normalize names —\n * its only job is to keep Gemini's parser happy.\n */\n\ntype JsonSchema = Record<string, unknown>;\n\nexport function toGeminiSchema(schema: JsonSchema): JsonSchema {\n const out = walk(schema);\n return (out ?? { type: 'object' }) as JsonSchema;\n}\n\nfunction walk(node: unknown): unknown {\n if (Array.isArray(node)) return node.map(walk);\n if (!isObject(node)) return node;\n\n // const → enum + inferred type\n if ('const' in node) {\n const c = node.const;\n const inferred = inferConstType(c);\n const next: JsonSchema = { ...node };\n delete next.const;\n next.type = (next.type as string | undefined) ?? inferred;\n next.enum = [c];\n return walk(next);\n }\n\n const out: JsonSchema = {};\n for (const [k, v] of Object.entries(node)) {\n if (k === 'oneOf') {\n out.anyOf = (v as unknown[]).map(walk);\n continue;\n }\n if (k === 'additionalProperties') {\n // Gemini OpenAPI subset doesn't model nested additionalProperties.\n // Drop — `properties` on the parent object is still authoritative.\n continue;\n }\n if (k === 'properties' && isObject(v)) {\n const props: JsonSchema = {};\n for (const [pk, pv] of Object.entries(v)) {\n props[pk] = walk(pv);\n }\n out.properties = props;\n continue;\n }\n if (k === 'items') {\n out.items = walk(v);\n continue;\n }\n if (k === 'anyOf' || k === 'allOf') {\n out[k] = (v as unknown[]).map(walk);\n continue;\n }\n if (k === 'enum' && Array.isArray(v)) {\n // Vertex requires `enum` only on `STRING` parameters. We can't\n // just stringify the values — Vertex separately checks that the\n // declared `type` matches. Rewrite based on the value kind:\n // - all strings → keep as-is\n // - all numbers → drop enum, emit min/max instead\n // - otherwise → drop enum entirely; type alone constrains\n const allStrings = v.every((x) => typeof x === 'string');\n if (allStrings) {\n out.enum = v as string[];\n continue;\n }\n const allNumbers = v.length > 0 && v.every((x) => typeof x === 'number');\n if (allNumbers) {\n const nums = v as number[];\n out.minimum = Math.min(...nums);\n out.maximum = Math.max(...nums);\n }\n continue;\n }\n out[k] = v;\n }\n\n // Arrays must declare items; default to string when authors omit it.\n if (out.type === 'array' && out.items === undefined) {\n out.items = { type: 'string' };\n }\n\n return out;\n}\n\nfunction inferConstType(c: unknown): string {\n if (typeof c === 'string') return 'string';\n if (typeof c === 'number') return Number.isInteger(c) ? 'integer' : 'number';\n if (typeof c === 'boolean') return 'boolean';\n return 'string';\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return v != null && typeof v === 'object' && !Array.isArray(v);\n}\n","/**\n * Gemini (Vertex AI) — `ToolProvider` adapter.\n *\n * Talks to Vertex's `:generateContent` endpoint with raw fetch; pulling\n * in `@google-cloud/vertexai` solely for this would balloon the dep tree.\n *\n * Translation contract — keep the agent loop oblivious to vendor diffs:\n *\n * tools tool catalogue → `tools[0].functionDeclarations[]`,\n * each parameter schema rewritten via `toGeminiSchema`.\n *\n * system joined to one `systemInstruction.parts[].text`.\n * Gemini auto-caches stable prefixes on Vertex, so the\n * `cached` hint from the agent loop is dropped here.\n *\n * messages our `NormalizedMessage[]` becomes Gemini `Content[]`:\n * user.text → role:user / parts:[{text}]\n * assistant.text+tcs → role:model / parts:[{text}, {functionCall}, …]\n * tool.results → role:user / parts:[{functionResponse}, …]\n * Gemini's functionResponse parts are name-keyed (no\n * ID), so we surface `toolName` in NormalizedToolResult\n * and rely on call-order parity within a turn.\n *\n * response `candidates[0].content.parts[]` is split into a `text`\n * string and a `toolCalls[]` array. Gemini doesn't emit\n * stable per-call IDs, so we mint `gem_<turn>_<idx>` —\n * the agent only needs them to be unique within a turn.\n *\n * Credentials come in as a host-supplied `GoogleAuth` instance; the\n * package never reads `process.env.GCP_*`.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type {\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n NormalizedToolCall,\n ToolProvider\n} from './types';\nimport { toGeminiSchema } from './schema';\n\n/**\n * One Part in a Gemini Content. Modeled loosely so we can pass through\n * fields we don't introspect (`thoughtSignature`, `thought: true`,\n * future additions). Only the recognized shapes are read; the rest is\n * preserved verbatim when echoed back via `providerData`.\n */\ntype GeminiPart = {\n text?: string;\n thought?: boolean;\n thoughtSignature?: string;\n functionCall?: { name: string; args: Record<string, unknown> };\n functionResponse?: { name: string; response: Record<string, unknown> };\n};\n\ntype GeminiContent = {\n role: 'user' | 'model';\n parts: GeminiPart[];\n};\n\ntype GeminiResponse = {\n candidates?: Array<{\n content?: GeminiContent;\n finishReason?: string;\n }>;\n error?: { code?: number; message?: string; status?: string };\n};\n\nexport type GeminiProviderOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Vertex region (e.g. 'us-east5' or 'global'). */\n location: string;\n /** Model id pinned by the host (e.g. 'gemini-3.1-pro-preview'). */\n modelId: string;\n /** Test seam: lets unit tests stub the Vertex HTTP call without going over the wire. */\n fetchImpl?: typeof fetch;\n};\n\nexport class GeminiToolProvider implements ToolProvider {\n readonly id = 'gemini' as const;\n private auth: GoogleAuth;\n private projectId: string;\n private location: string;\n private modelId: string;\n private fetchImpl: typeof fetch;\n\n constructor(opts: GeminiProviderOpts) {\n this.auth = opts.auth;\n this.projectId = opts.projectId;\n this.location = opts.location;\n this.modelId = opts.modelId;\n this.fetchImpl = opts.fetchImpl ?? fetch;\n }\n\n async runTurn(input: AgentTurnInput): Promise<AgentTurn> {\n const accessToken = await this.auth.getAccessToken();\n if (!accessToken) throw new Error('Failed to obtain GCP access token');\n const url = `https://${vertexHost(this.location)}/v1/projects/${this.projectId}/locations/${this.location}/publishers/google/models/${this.modelId}:generateContent`;\n\n const body = {\n systemInstruction: {\n parts: [{ text: input.system.map((b) => b.text).join('\\n\\n') }]\n },\n contents: toGeminiContents(input.messages),\n tools: [\n {\n functionDeclarations: input.tools.map((t) => ({\n name: t.name,\n description: t.description,\n parameters: toGeminiSchema(t.input_schema as Record<string, unknown>)\n }))\n }\n ],\n toolConfig: {\n functionCallingConfig: { mode: 'AUTO' }\n },\n generationConfig: {\n maxOutputTokens: input.maxOutputTokens,\n temperature: 0\n }\n };\n\n const res = await this.fetchImpl(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(body)\n });\n\n if (!res.ok) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Gemini request failed (${res.status}): ${detail}`);\n }\n\n const json = (await res.json()) as GeminiResponse;\n if (json.error) {\n throw new Error(\n `Vertex Gemini returned error: ${json.error.status ?? json.error.code ?? '??'} ${\n json.error.message ?? ''\n }`\n );\n }\n return fromGeminiResponse(json);\n }\n}\n\n/** Factory matching the package's provider-init contract. */\nexport function createGeminiProvider(opts: GeminiProviderOpts): ToolProvider {\n return new GeminiToolProvider(opts);\n}\n\n/**\n * Build the Vertex AI host for a given location. Most regions resolve\n * to `{region}-aiplatform.googleapis.com`; the special `global`\n * location uses the un-prefixed `aiplatform.googleapis.com` endpoint.\n */\nexport function vertexHost(location: string): string {\n return location === 'global'\n ? 'aiplatform.googleapis.com'\n : `${location}-aiplatform.googleapis.com`;\n}\n\nexport function toGeminiContents(messages: NormalizedMessage[]): GeminiContent[] {\n const out: GeminiContent[] = [];\n for (const msg of messages) {\n if (msg.role === 'user') {\n out.push({ role: 'user', parts: [{ text: msg.text }] });\n } else if (msg.role === 'assistant') {\n // Prefer the original parts array (carrying thoughtSignatures and\n // thought summaries) when the assistant turn was produced by this\n // adapter. Gemini 2.5+/3.x thinking mode REQUIRES the signatures\n // round-trip; reconstructing from `text + toolCalls` would drop\n // them and the next request would 400 with INVALID_ARGUMENT.\n if (Array.isArray((msg.providerData as { parts?: unknown })?.parts)) {\n const parts = (msg.providerData as { parts: GeminiPart[] }).parts;\n out.push({ role: 'model', parts });\n continue;\n }\n const parts: GeminiPart[] = [];\n if (msg.text) parts.push({ text: msg.text });\n for (const tc of msg.toolCalls) {\n parts.push({ functionCall: { name: tc.name, args: tc.input } });\n }\n // Gemini rejects empty parts arrays; if the assistant said nothing\n // and called no tools (shouldn't happen in our loop), inject an\n // empty text part so the round-trip stays valid.\n if (parts.length === 0) parts.push({ text: '' });\n out.push({ role: 'model', parts });\n } else {\n const parts: GeminiPart[] = msg.results.map((r) => ({\n functionResponse: {\n name: r.toolName,\n response: parseToolResultContent(r.content, r.isError)\n }\n }));\n out.push({ role: 'user', parts });\n }\n }\n return out;\n}\n\n/**\n * Gemini's `functionResponse.response` is an OBJECT, not a free string.\n * Our normalized `tool` messages carry the result as a JSON-stringified\n * payload. Parse it back; on parse failure (e.g. a tool serialized a\n * scalar), wrap so Gemini still gets a valid object. Errors are wrapped\n * under `error` so the model can distinguish success from failure.\n */\nfunction parseToolResultContent(\n content: string,\n isError: boolean\n): Record<string, unknown> {\n let parsed: unknown = null;\n try {\n parsed = JSON.parse(content);\n } catch {\n parsed = content;\n }\n if (isError) {\n return { error: parsed };\n }\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n // Scalars / arrays — wrap so the response is always a JSON object.\n return { result: parsed };\n}\n\nexport function fromGeminiResponse(json: GeminiResponse): AgentTurn {\n const candidate = json.candidates?.[0];\n const parts = candidate?.content?.parts ?? [];\n const textParts: string[] = [];\n const toolCalls: NormalizedToolCall[] = [];\n let idx = 0;\n for (const part of parts) {\n // `thought: true` parts are model thinking summaries — include them\n // in `providerData` (so signatures round-trip) but NOT in `text`,\n // which feeds the transcript shown to the user.\n if (typeof part.text === 'string' && part.thought !== true) {\n textParts.push(part.text);\n } else if (part.functionCall) {\n toolCalls.push({\n id: `gem_${idx}_${part.functionCall.name}`,\n name: part.functionCall.name,\n input: (part.functionCall.args ?? {}) as Record<string, unknown>\n });\n idx += 1;\n }\n }\n return {\n text: textParts.join(''),\n toolCalls,\n stopReason: normalizeFinishReason(candidate?.finishReason, toolCalls.length > 0),\n // Preserve the raw parts so a subsequent runTurn() echoes the\n // assistant turn back faithfully, including any `thoughtSignature`\n // entries thinking-mode requires.\n providerData: { parts }\n };\n}\n\nfunction normalizeFinishReason(\n reason: string | undefined,\n hasToolCalls: boolean\n): AgentTurn['stopReason'] {\n if (hasToolCalls) return 'tool_use';\n switch (reason) {\n case 'STOP':\n return 'end_turn';\n case 'MAX_TOKENS':\n return 'max_tokens';\n default:\n return reason ? 'other' : 'end_turn';\n }\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n","/**\n * Tool-calling provider registry.\n *\n * The agent loop and the routes layer drive providers through this\n * factory; vendor specifics stay inside `claude.ts` / `gemini.ts`.\n * Adding a third provider would slot in alongside without further\n * changes to the agent loop.\n *\n * The host injects credentials (a `GoogleAuth` instance), the GCP\n * project id, the default region, and the pinned model ids via\n * `VertexPort`. A per-request region override flows in as\n * `ProviderInitOpts.location` so admin-managed `aiSettings.gcpLocation`\n * can flip Vertex regions without rebuilding the registry.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport { ClaudeToolProvider, createClaudeProvider } from './claude';\nimport { GeminiToolProvider, createGeminiProvider } from './gemini';\nimport type { ToolProvider, ToolProviderId } from './types';\n\nexport type {\n ToolProvider,\n ToolProviderId,\n AgentTurn,\n AgentTurnInput,\n NormalizedMessage,\n NormalizedToolCall,\n NormalizedToolResult,\n SystemBlock,\n ToolSchema\n} from './types';\nexport { ClaudeToolProvider, createClaudeProvider } from './claude';\nexport { GeminiToolProvider, createGeminiProvider } from './gemini';\nexport { toGeminiSchema } from './schema';\n\nexport type ProviderInitOpts = {\n /** Pre-built GoogleAuth instance (host-supplied). */\n auth: GoogleAuth;\n /** GCP project id. */\n projectId: string;\n /** Default Vertex region used when `location` is omitted. */\n defaultLocation: string;\n /** Vertex model ids pinned by the host. */\n modelIds: { claude: string; gemini: string };\n /** Per-request override for `aiSettings.gcpLocation`. Falls back to defaultLocation. */\n location?: string;\n};\n\nexport type ToolProviderDef = {\n id: ToolProviderId;\n label: string;\n description: string;\n createProvider(opts: ProviderInitOpts): ToolProvider;\n};\n\nexport const toolProviders: ToolProviderDef[] = [\n {\n id: 'claude',\n label: 'Claude (Vertex)',\n description: 'Anthropic Messages API hosted on GCP Vertex AI.',\n createProvider(opts) {\n return createClaudeProvider({\n auth: opts.auth,\n projectId: opts.projectId,\n location: opts.location ?? opts.defaultLocation,\n modelId: opts.modelIds.claude\n });\n }\n },\n {\n id: 'gemini',\n label: 'Gemini (Vertex)',\n description: 'Google Gemini hosted on GCP Vertex AI (raw generateContent).',\n createProvider(opts) {\n return createGeminiProvider({\n auth: opts.auth,\n projectId: opts.projectId,\n location: opts.location ?? opts.defaultLocation,\n modelId: opts.modelIds.gemini\n });\n }\n }\n];\n\nexport function getToolProvider(id: string): ToolProviderDef | undefined {\n return toolProviders.find((p) => p.id === id);\n}\n","/**\n * Internal helpers shared by the narrators. Lifted verbatim from the host's\n * `src/lib/google-auth.ts` so the narrators can speak Vertex without\n * importing host code. The package never reads `process.env.GCP_*` — every\n * field comes in as an argument from the caller.\n */\nimport { GoogleAuth } from 'google-auth-library';\nimport { AnthropicVertex } from '@anthropic-ai/vertex-sdk';\n\n/**\n * Build the Vertex AI host for a given location. Most regions resolve to\n * `{region}-aiplatform.googleapis.com`; the special `global` location uses\n * the un-prefixed `aiplatform.googleapis.com` endpoint.\n */\nexport function vertexHost(location: string): string {\n return location === 'global'\n ? 'aiplatform.googleapis.com'\n : `${location}-aiplatform.googleapis.com`;\n}\n\n/** Fetch a fresh OAuth access token using the host-supplied GoogleAuth. */\nexport async function getAccessToken(auth: GoogleAuth): Promise<string> {\n const token = await auth.getAccessToken();\n if (!token) throw new Error('Failed to obtain GCP access token');\n return token;\n}\n\n/**\n * Build an `AnthropicVertex` client and patch its `buildRequest` so it is\n * synchronous, working around the ABI mismatch between\n * `@anthropic-ai/vertex-sdk@0.16.0` (declares `buildRequest` as async) and\n * `@anthropic-ai/sdk@0.50.4` (consumes it synchronously). Without this\n * patch, the destructured `{ req, url, timeout }` returns `undefined`s and\n * the SDK throws \"Cannot read properties of undefined (reading 'headers')\"\n * before any HTTP request is sent.\n */\nexport function createAnthropicVertexClient(args: {\n projectId: string;\n location: string;\n auth: GoogleAuth;\n}): AnthropicVertex {\n const client = new AnthropicVertex({\n projectId: args.projectId,\n region: args.location,\n googleAuth: args.auth\n });\n patchVertexBuildRequestSync(client);\n return client;\n}\n\nconst MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);\nconst VERTEX_DEFAULT_VERSION = 'vertex-2023-10-16';\n\nfunction isObj(value: unknown): value is Record<string, unknown> {\n return value != null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction patchVertexBuildRequestSync(client: AnthropicVertex): void {\n const proto = Object.getPrototypeOf(client) as Record<string, unknown>;\n const grandparent = Object.getPrototypeOf(proto) as {\n buildRequest: (...args: unknown[]) => unknown;\n };\n proto.buildRequest = function patchedBuildRequest(\n this: AnthropicVertex & { projectId?: string; region?: string },\n options: { method?: string; path?: string; body?: unknown },\n extra?: unknown\n ) {\n if (isObj(options.body)) {\n options.body = { ...options.body };\n }\n if (isObj(options.body) && !options.body.anthropic_version) {\n options.body.anthropic_version = VERTEX_DEFAULT_VERSION;\n }\n if (\n options.path &&\n MODEL_ENDPOINTS.has(options.path) &&\n options.method === 'post' &&\n isObj(options.body)\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n const model = options.body.model;\n options.body.model = undefined;\n const stream = options.body.stream ?? false;\n const specifier = stream ? 'streamRawPredict' : 'rawPredict';\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${model}:${specifier}`;\n }\n if (\n options.path === '/v1/messages/count_tokens' ||\n (options.path === '/v1/messages/count_tokens?beta=true' && options.method === 'post')\n ) {\n if (!this.projectId) throw new Error('AnthropicVertex: projectId is required');\n options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`;\n }\n return grandparent.buildRequest.call(this, options, extra);\n } as unknown as (typeof proto)['buildRequest'];\n}\n","/**\n * Claude narrator — turns one paragraph_brief block's key_facts into\n * flowing prose using Claude on Vertex AI (Anthropic Messages API served\n * through GCP Vertex Model Garden).\n *\n * The narrator MUST NOT introduce numbers that aren't already in the\n * structured payload — that's the rule the system prompt enforces. The\n * eval harness asserts this indirectly: structured numbers must be\n * byte-identical across providers.\n *\n * Lifted from the host's `src/ai/narrators/claude.ts`. Refactored from a\n * class to a streaming function so the narrator no longer pulls auth out\n * of the host's env-reader; every credential field comes in as an arg.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { createAnthropicVertexClient } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging (\"it appears\", \"perhaps\").\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim — if raw_numbers says\n 1234.56, say \"1,234.56\" or \"$1,235\", never \"about 1.2k\" if that\n drifts.\n - Do not begin with \"Here is\", \"Below\", \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamClaudeNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n /** Hard cap on output tokens. Reasoning models charge internal thinking against this. */\n maxTokens: number;\n input: NarrativeInput;\n};\n\n/**\n * Stream Claude prose tokens for one paragraph_brief block. Yields raw\n * text deltas as the model produces them — the route layer is responsible\n * for any SSE framing on top.\n */\nexport async function* streamClaudeNarration(\n opts: StreamClaudeNarrationOpts\n): AsyncIterable<string> {\n const client = createAnthropicVertexClient({\n projectId: opts.projectId,\n location: opts.location,\n auth: opts.auth\n });\n\n const stream = await client.messages.stream({\n model: opts.modelId,\n max_tokens: opts.maxTokens,\n system: NARRATIVE_SYSTEM,\n messages: [{ role: 'user', content: buildNarrativeUserMessage(opts.input) }]\n });\n\n for await (const event of stream) {\n if (\n event.type === 'content_block_delta' &&\n 'delta' in event &&\n event.delta &&\n 'type' in event.delta &&\n event.delta.type === 'text_delta'\n ) {\n yield (event.delta as { type: 'text_delta'; text: string }).text;\n }\n }\n}\n\nexport function buildNarrativeUserMessage(input: NarrativeInput): string {\n return [\n `User question: ${input.question}`,\n '',\n `Block topic: ${input.topic}`,\n `Block key_facts:\\n${input.keyFacts.map((f) => `- ${f}`).join('\\n')}`,\n '',\n 'Full structured answer (for reference; do not restate the whole thing):',\n JSON.stringify(input.structured, null, 2)\n ].join('\\n');\n}\n","/**\n * Gemini narrator — turns one paragraph_brief block's key_facts into\n * flowing prose using Gemini on Vertex AI. Same prose contract as the\n * Claude and Grok narrators; structured numbers are unchanged so the eval\n * harness's byte-identical equivalence assertion holds across the swap.\n *\n * Auth: a Google access token from the host-supplied `GoogleAuth`\n * instance (the package never reads `process.env.GCP_*`).\n *\n * Streaming: Vertex's `:streamGenerateContent` returns a JSON array of\n * chunks delivered as the prediction unfolds. Setting `alt=sse` flips the\n * transport to SSE-style `data: {chunk}\\n\\n` frames, which we parse inline\n * rather than pulling in `@google-cloud/vertexai`.\n *\n * Lifted from the host's `src/ai/narrators/gemini.ts`. Refactored to take\n * `{ auth, projectId, location, modelId }` explicitly instead of calling\n * `getVertexAuth`/`getVertexAccessToken` from the host.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { buildNarrativeUserMessage } from './claude';\nimport { getAccessToken, vertexHost } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging.\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim.\n - Do not begin with \"Here is\" or \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamGeminiNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n /** Hard cap on output tokens. Reasoning models charge internal thinking against this. */\n maxTokens: number;\n input: NarrativeInput;\n};\n\nexport async function* streamGeminiNarration(\n opts: StreamGeminiNarrationOpts\n): AsyncIterable<string> {\n const accessToken = await getAccessToken(opts.auth);\n const url = `https://${vertexHost(opts.location)}/v1/projects/${opts.projectId}/locations/${opts.location}/publishers/google/models/${opts.modelId}:streamGenerateContent?alt=sse`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n systemInstruction: { parts: [{ text: NARRATIVE_SYSTEM }] },\n contents: [\n {\n role: 'user',\n parts: [{ text: buildNarrativeUserMessage(opts.input) }]\n }\n ],\n generationConfig: { maxOutputTokens: opts.maxTokens, temperature: 0 }\n })\n });\n\n if (!res.ok || !res.body) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Gemini request failed (${res.status}): ${detail}`);\n }\n\n yield* parseGeminiSseTextDeltas(res.body);\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n\n/**\n * Parses Vertex Gemini's SSE-formatted `:streamGenerateContent?alt=sse`\n * response and yields successive text deltas. Each frame is a JSON\n * `GenerateContentResponse` whose `candidates[0].content.parts[*].text`\n * carries the prose tokens. Tool-call frames are ignored — the narrator\n * doesn't expose tools.\n */\nasync function* parseGeminiSseTextDeltas(\n body: ReadableStream<Uint8Array>\n): AsyncIterable<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffered += decoder.decode(value, { stream: true });\n let newlineIndex: number;\n while ((newlineIndex = buffered.indexOf('\\n')) !== -1) {\n const line = buffered.slice(0, newlineIndex).trim();\n buffered = buffered.slice(newlineIndex + 1);\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (!payload) continue;\n try {\n const chunk = JSON.parse(payload) as {\n candidates?: Array<{ content?: { parts?: Array<{ text?: string }> } }>;\n };\n const parts = chunk.candidates?.[0]?.content?.parts ?? [];\n for (const part of parts) {\n if (typeof part.text === 'string' && part.text.length > 0) {\n yield part.text;\n }\n }\n } catch {\n // Mid-frame JSON or keepalive — skip silently.\n }\n }\n }\n}\n","/**\n * Grok narrator — talks to xAI Grok served by GCP Vertex Model Garden via\n * Vertex's OpenAI-compatible chat-completions endpoint. Same prose\n * contract as the Claude narrator; the structured answer is unchanged so\n * byte-identical equivalence holds across the swap.\n *\n * Auth: a Google access token from the host-supplied `GoogleAuth`\n * instance.\n *\n * Streaming: Vertex's OpenAI-compat endpoint returns standard server-sent\n * events (`data: {chunk}\\n\\n` … `data: [DONE]`). We parse the deltas\n * inline rather than pulling in the OpenAI SDK so the only Vertex\n * dependency for Grok is `google-auth-library`.\n *\n * NOTE: `VertexPort.modelIds` does not currently include a `grok` slot —\n * the host's `VertexPort` only pins `claude` and `gemini`. The caller\n * passes the Grok model id explicitly via `modelId` for now.\n * TODO: add `modelIds.grok` to `VertexPort` once the host plumbs the\n * Grok model setting through `ai_settings`.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { NarrativeInput } from './index';\nimport { buildNarrativeUserMessage } from './claude';\nimport { getAccessToken, vertexHost } from './_vertex';\n\nconst NARRATIVE_SYSTEM = `You are the prose narrator for the FLC Data Intelligence agent.\n\nYou receive:\n - The user's original question.\n - The full structured answer the agent already computed (blocks +\n raw_numbers).\n - One specific paragraph_brief block's topic and key_facts.\n\nYour job: write 2–4 short sentences (≤ 80 words total) of natural,\nuseful prose for THIS paragraph block.\n\nRules:\n - Use only the facts in key_facts and raw_numbers. Do not invent\n numbers, dates, country names, or trends.\n - Be neutral and direct. No hedging.\n - No headings, no markdown, no bullet lists. Plain prose.\n - Reference the same numbers verbatim.\n - Do not begin with \"Here is\" or \"Based on the data\".\n - Stop. Do not repeat yourself.`;\n\nexport type StreamGrokNarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n /** Hard cap on output tokens. Reasoning models charge internal thinking against this. */\n maxTokens: number;\n input: NarrativeInput;\n};\n\nexport async function* streamGrokNarration(\n opts: StreamGrokNarrationOpts\n): AsyncIterable<string> {\n const accessToken = await getAccessToken(opts.auth);\n const url = `https://${vertexHost(opts.location)}/v1beta1/projects/${opts.projectId}/locations/${opts.location}/endpoints/openapi/chat/completions`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n model: opts.modelId,\n max_tokens: opts.maxTokens,\n stream: true,\n messages: [\n { role: 'system', content: NARRATIVE_SYSTEM },\n { role: 'user', content: buildNarrativeUserMessage(opts.input) }\n ]\n })\n });\n\n if (!res.ok || !res.body) {\n const detail = await safeReadText(res);\n throw new Error(`Vertex Grok request failed (${res.status}): ${detail}`);\n }\n\n yield* parseSseDeltas(res.body);\n}\n\nasync function safeReadText(res: Response): Promise<string> {\n try {\n return (await res.text()).slice(0, 500);\n } catch {\n return '';\n }\n}\n\n/** Parses an OpenAI-compatible SSE stream and yields text deltas. */\nasync function* parseSseDeltas(body: ReadableStream<Uint8Array>): AsyncIterable<string> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffered = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffered += decoder.decode(value, { stream: true });\n let newlineIndex: number;\n while ((newlineIndex = buffered.indexOf('\\n')) !== -1) {\n const line = buffered.slice(0, newlineIndex).trim();\n buffered = buffered.slice(newlineIndex + 1);\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (!payload || payload === '[DONE]') {\n if (payload === '[DONE]') return;\n continue;\n }\n try {\n const chunk = JSON.parse(payload) as {\n choices?: Array<{ delta?: { content?: string } }>;\n };\n const delta = chunk.choices?.[0]?.delta?.content;\n if (typeof delta === 'string' && delta.length > 0) yield delta;\n } catch {\n // Mid-chunk JSON or keepalive — skip silently.\n }\n }\n }\n}\n","/**\n * Narrators — the prose pass that turns a structured answer into the\n * paragraph_brief block's flowing text. The agent's tool loop decides\n * WHAT to say (key_facts); the narrator decides HOW to say it.\n *\n * Three implementations:\n * - streamClaudeNarration — Anthropic Messages on GCP Vertex\n * - streamGrokNarration — xAI Grok via Vertex's OpenAI-compatible endpoint\n * - streamGeminiNarration — Google Gemini on GCP Vertex\n *\n * All three expose the same shape: an async generator yielding raw text\n * deltas. The route layer is responsible for any SSE framing on top — the\n * package keeps the streaming primitive provider-agnostic.\n *\n * Lifted from the host's `src/ai/narrators/`. The host's class-based\n * `NarrativeProvider` interface and `createNarrativeProvider` factory are\n * replaced with plain streaming functions plus a `getNarrator(id)` lookup.\n * Every credential field comes in as an explicit argument; no `@/...`\n * imports remain.\n */\nimport type { GoogleAuth } from 'google-auth-library';\nimport type { PresentPayload } from '../tools/types';\nimport { streamClaudeNarration, type StreamClaudeNarrationOpts } from './claude';\nimport { streamGeminiNarration, type StreamGeminiNarrationOpts } from './gemini';\nimport { streamGrokNarration, type StreamGrokNarrationOpts } from './grok';\n\nexport type NarratorId = 'claude' | 'gemini' | 'grok';\n\nexport type NarrativeInput = {\n question: string;\n structured: PresentPayload;\n topic: string;\n keyFacts: string[];\n blockIndex: number;\n};\n\n/**\n * Common shape every narrator accepts. Each individual narrator declares a\n * specialised version (e.g. `StreamClaudeNarrationOpts`) for direct use;\n * `getNarrator()` consumes this widened shape so the call site doesn't have\n * to discriminate on the id.\n *\n * `maxTokens` caps the prose pass. Reasoning models charge internal\n * thinking against this — pass the same value as the agent loop's\n * maxOutputTokens (driven by `aiSettings.maxOutputTokens`) so the same\n * admin lever controls both.\n */\nexport type NarrationOpts = {\n auth: GoogleAuth;\n projectId: string;\n location: string;\n modelId: string;\n maxTokens: number;\n input: NarrativeInput;\n};\n\nexport type NarratorFn = (opts: NarrationOpts) => AsyncIterable<string>;\n\n/**\n * Resolve a narrator by id. Returns the streaming function that turns a\n * `NarrationOpts` bundle into an async iterable of text deltas. Throws on\n * an unknown id rather than falling back silently — the caller validates\n * the configured provider against this registry's keys.\n */\nexport function getNarrator(id: NarratorId): NarratorFn {\n switch (id) {\n case 'claude':\n return streamClaudeNarration;\n case 'gemini':\n return streamGeminiNarration;\n case 'grok':\n return streamGrokNarration;\n default: {\n const _exhaustive: never = id;\n throw new Error(`Unknown narrator id: ${String(_exhaustive)}`);\n }\n }\n}\n\nexport {\n streamClaudeNarration,\n streamGeminiNarration,\n streamGrokNarration,\n type StreamClaudeNarrationOpts,\n type StreamGeminiNarrationOpts,\n type StreamGrokNarrationOpts\n};\n","/**\n * `agent-custom` SSE route factory.\n *\n * Host-agnostic refactor of the host repo's `app/api/agent/route.ts`. The\n * SSE wire format is preserved byte-for-byte (the package's UI components\n * consume this stream): `event: meta`, `event: block`, `event: prose`,\n * `event: error`, `event: done`. All host-specific concerns (auth, scope,\n * tools, persistence, credentials) cross the boundary as ports passed in\n * via `AgentCustomRouteCtx`.\n */\nimport { randomUUID } from 'crypto';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from '../ports/types';\nimport type { Block, PresentPayload, ToolContext } from '../tools/types';\nimport { runAgent } from '../agent';\nimport { getToolProvider } from '../providers';\nimport { getNarrator, type NarratorId } from '../narrators';\n\n/**\n * Common lifecycle hooks shared across every route factory. Hooks return\n * `Response | null`: a non-null Response short-circuits the request (the\n * factory returns it untouched), `null` continues the normal flow.\n */\nexport type RouteHooks<S> = {\n /** Runs before auth. Return a Response to short-circuit (e.g. 503 during shutdown). */\n onRequest?(req: Request): Promise<Response | null>;\n /** Runs after successful auth. Return a Response to short-circuit (e.g. 429 rate-limited). */\n onAuthenticated?(args: { req: Request; scope: S; userId: number }): Promise<Response | null>;\n};\n\n/**\n * Streaming-route hooks. Adds three lifecycle points specific to the SSE\n * `agent-custom` path so consumers can plumb in per-request resources\n * (e.g. SQL view creation/cleanup keyed off a fresh sessionId).\n */\nexport type AgentCustomHooks<S> = RouteHooks<S> & {\n /**\n * Generate the per-request session id used in ToolContext (and any\n * project-specific resources keyed off it, e.g. SQL view names).\n * Defaults to a random URL-safe id (16 hex chars from a UUID).\n */\n generateSessionId?(args: {\n scope: S;\n userId: number;\n chatSessionId: number | null;\n }): string | Promise<string>;\n /**\n * Runs once after the session id is resolved, before the agent loop.\n * Throw to abort the request (the route catches and surfaces the error\n * via the SSE error frame + persistence).\n */\n onSessionStart?(args: {\n scope: S;\n sessionId: string;\n userId: number;\n }): Promise<void>;\n /**\n * Always runs in `finally`, regardless of how the stream ended.\n * The route never throws out of this hook — its errors are logged via\n * ctx.logger but don't surface to the client.\n */\n onSessionEnd?(args: {\n scope: S;\n sessionId: string;\n userId: number;\n cause: 'complete' | 'error' | 'abort';\n }): Promise<void>;\n};\n\nexport type AgentCustomRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Resolve which narrator to use for prose generation. Default:\n * `() => aiSettings.toolProvider` (which is only ever `claude` or\n * `gemini` from the registry). Hosts that surface a per-user\n * `narrative_provider` (e.g. allowing `grok`) wire their existing\n * lookup here.\n */\n resolveNarratorId?: (scope: S) => Promise<NarratorId>;\n /**\n * Optional lifecycle hooks. See `AgentCustomHooks` for the available\n * extension points (shutdown gating, rate limiting, per-request\n * resource setup/teardown).\n */\n hooks?: AgentCustomHooks<S>;\n};\n\nconst NARRATOR_IDS: ReadonlySet<NarratorId> = new Set<NarratorId>([\n 'claude',\n 'gemini',\n 'grok'\n]);\n\nfunction isNarratorId(value: string): value is NarratorId {\n return NARRATOR_IDS.has(value as NarratorId);\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'Content-Type': 'application/json' }\n });\n}\n\n/**\n * Default per-request session id generator. 16 hex chars, drawn from a\n * UUID — short enough to fit in identifiers (e.g. SQL view names) and\n * fresh per request so it never collides with the persistent\n * `chatSessionId`.\n */\nfunction defaultGenerateSessionId(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n}\n\n/**\n * Pull a narrator-specific Vertex model id out of the host's\n * `VertexPort.modelIds`. The port pins `claude` and `gemini`; `grok` is\n * optional (may exist as an unsanctioned extra key set by the host).\n */\nfunction pickNarratorModelId(\n vertex: VertexPort,\n narratorId: NarratorId\n): string {\n if (narratorId === 'claude') return vertex.modelIds.claude;\n if (narratorId === 'gemini') return vertex.modelIds.gemini;\n // narratorId === 'grok'\n const extra = vertex.modelIds as { grok?: string };\n if (typeof extra.grok === 'string' && extra.grok.length > 0) {\n return extra.grok;\n }\n throw new Error(\n \"Narrator 'grok' selected but VertexPort.modelIds.grok is not pinned.\"\n );\n}\n\nexport function createAgentCustomRoutes<S>(ctx: AgentCustomRouteCtx<S>) {\n const { persistence, auth, scope, tools, vertex, logger, hooks } = ctx;\n\n return {\n /** Next.js-compatible POST handler. */\n POST: async (req: Request): Promise<Response> => {\n // 0. Pre-auth hook (e.g. shutdown gate → 503).\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n\n // 1. Authenticate via host port.\n const authResult = await auth.requireAuth(req);\n if (!authResult.ok) return authResult.response;\n const { scope: callerScope, userId } = authResult;\n\n // 1b. Post-auth hook (e.g. rate limit → 429).\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: callerScope,\n userId\n });\n if (short) return short;\n }\n\n // 2. Parse + validate body.\n const body = (await req.json().catch(() => null)) as\n | { question?: unknown; chatSessionId?: unknown }\n | null;\n const question =\n typeof body?.question === 'string' ? body.question.trim() : '';\n if (!question) {\n return jsonError(\n 400,\n 'VALIDATION_FAILED',\n 'question must be a non-empty string.'\n );\n }\n const rawChatSessionId = body?.chatSessionId;\n const incomingChatSessionId =\n typeof rawChatSessionId === 'number' &&\n Number.isInteger(rawChatSessionId)\n ? rawChatSessionId\n : null;\n\n // 3. AI settings (singleton).\n const aiSettings = await persistence.getAiSettings();\n\n // 4 & 5. Resolve / create the chat session, then persist the user turn.\n let chatSessionId: number;\n if (incomingChatSessionId !== null) {\n const owned = await persistence.getSession(incomingChatSessionId, userId);\n if (!owned) {\n return jsonError(404, 'NOT_FOUND', 'Chat session not found.');\n }\n chatSessionId = owned.id;\n } else {\n const created = await persistence.createSession({\n userId,\n title: question.slice(0, 200)\n });\n chatSessionId = created.id;\n }\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'user',\n question\n });\n\n // 5b. Resolve the per-request session id (fresh, ephemeral, never\n // collides with the persistent chatSessionId).\n const sessionId: string = hooks?.generateSessionId\n ? await hooks.generateSessionId({\n scope: callerScope,\n userId,\n chatSessionId: incomingChatSessionId\n })\n : defaultGenerateSessionId();\n\n // 6 & 7. Build ToolContext + system blocks.\n const scopeSummary = await scope.buildScopeSummary(callerScope);\n const scopeLabel = await scope.resolveScopeLabel(callerScope);\n const toolContext: ToolContext<S> = {\n scope: callerScope,\n sessionId,\n scopeSummary,\n toolCallCount: 0\n };\n const systemBlocks = await tools.buildSystemBlocks(toolContext);\n\n // 8. Resolve the configured tool provider.\n const def = getToolProvider(aiSettings.toolProvider);\n if (!def) {\n return jsonError(\n 400,\n 'INVALID_PROVIDER',\n `Unknown tool provider in ai_settings: ${aiSettings.toolProvider}`\n );\n }\n const provider = def.createProvider({\n auth: vertex.auth,\n projectId: vertex.projectId,\n defaultLocation: vertex.defaultLocation,\n modelIds: vertex.modelIds,\n location: aiSettings.gcpLocation\n });\n\n // 9. Pick the narrator. Defaults to whatever toolProvider is set —\n // safe because the registry only allows claude/gemini, both of\n // which have pinned model ids.\n let narratorId: NarratorId;\n if (ctx.resolveNarratorId) {\n narratorId = await ctx.resolveNarratorId(callerScope);\n } else if (isNarratorId(aiSettings.toolProvider)) {\n narratorId = aiSettings.toolProvider;\n } else {\n return jsonError(\n 400,\n 'INVALID_NARRATOR',\n `Cannot derive narrator from tool provider: ${aiSettings.toolProvider}`\n );\n }\n\n // 10. Open the SSE stream.\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n let closed = false;\n const send = (event: string, data: unknown) => {\n if (closed) return;\n try {\n controller.enqueue(\n encoder.encode(\n `event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`\n )\n );\n } catch {\n // Controller already closed (client gone) — swallow.\n }\n };\n\n // Buffers used to persist the assistant turn at the end of the\n // stream. We mirror the SSE payloads: blocks[] is the structured\n // answer; prose[blockIndex] is the streamed prose for\n // paragraph_brief blocks.\n const persistedBlocks: Block[] = [];\n const persistedProse: Record<number, string> = {};\n let persistedError: { code: string; message: string } | null = null;\n let sessionStarted = false;\n\n try {\n // 10a. Per-request resource setup (e.g. SQL view creation).\n // Errors here surface as a normal SSE error frame and are\n // persisted with the assistant turn.\n if (hooks?.onSessionStart) {\n await hooks.onSessionStart({\n scope: callerScope,\n sessionId,\n userId\n });\n }\n sessionStarted = true;\n\n send('meta', { chatSessionId, scopeLabel });\n\n const agentResult = await runAgent({\n question,\n ctx: toolContext,\n tools: tools.tools,\n systemBlocks,\n provider,\n maxOutputTokens: aiSettings.maxOutputTokens\n });\n\n if (!agentResult.ok) {\n persistedError = agentResult.error;\n send('error', agentResult.error);\n send('done', {});\n return;\n }\n\n const { structured } = agentResult as {\n structured: PresentPayload;\n };\n\n let narratorModelId: string | null = null;\n const narratorFn = getNarrator(narratorId);\n\n for (let i = 0; i < structured.blocks.length; i++) {\n const block = structured.blocks[i];\n persistedBlocks[i] = block;\n send('block', { index: i, ...block });\n if (block.kind === 'paragraph_brief') {\n persistedProse[i] = '';\n try {\n if (narratorModelId === null) {\n narratorModelId = pickNarratorModelId(vertex, narratorId);\n }\n for await (const token of narratorFn({\n auth: vertex.auth,\n projectId: vertex.projectId,\n location: aiSettings.gcpLocation,\n modelId: narratorModelId,\n maxTokens: aiSettings.maxOutputTokens,\n input: {\n question,\n structured,\n topic: block.topic,\n keyFacts: block.key_facts,\n blockIndex: i\n }\n })) {\n persistedProse[i] += token;\n send('prose', { block_index: i, delta: token });\n }\n } catch (e) {\n // Narrator failed: fall back to key_facts joined by\n // \". \" so the user still sees the data, then surface\n // the error so the UI can flag it.\n const fallback = block.key_facts.join('. ') + '.';\n persistedProse[i] = fallback;\n send('prose', {\n block_index: i,\n delta: block.key_facts.join('. ')\n });\n send('prose', { block_index: i, delta: '.' });\n send('error', {\n code: 'NARRATOR_FAILED',\n message: `Prose stream failed (${(e as Error).message}); fell back to key facts.`\n });\n }\n }\n }\n\n send('done', {});\n } catch (e) {\n const message = (e as Error).message ?? 'Internal error';\n persistedError = { code: 'INTERNAL', message };\n logger?.error?.(\n { chatSessionId, sessionId, err: message },\n '[agent-custom] stream errored'\n );\n try {\n controller.enqueue(\n encoder.encode(\n `event: error\\ndata: ${JSON.stringify({ code: 'INTERNAL', message })}\\n\\n`\n )\n );\n controller.enqueue(encoder.encode(`event: done\\ndata: {}\\n\\n`));\n } catch {\n // ignore — client already gone.\n }\n } finally {\n // 10b. Per-request resource teardown. Always runs (even when\n // onSessionStart threw — symmetric to the host's view-drop\n // contract: dropOnce is safe to call without a prior create).\n // Errors here are logged but never surfaced; this is the one\n // hook the route deliberately swallows.\n if (hooks?.onSessionEnd) {\n const cause: 'complete' | 'error' | 'abort' = req.signal.aborted\n ? 'abort'\n : persistedError\n ? 'error'\n : 'complete';\n try {\n await hooks.onSessionEnd({\n scope: callerScope,\n sessionId,\n userId,\n cause\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n sessionStarted,\n err: (err as Error).message\n },\n '[agent-custom] onSessionEnd hook failed'\n );\n }\n }\n\n // Persist the assistant turn last so a mid-stream client abort\n // still records what was generated up to that point.\n try {\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: persistedBlocks.length ? persistedBlocks : null,\n prose: Object.keys(persistedProse).length\n ? persistedProse\n : null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n { chatSessionId, sessionId, err: (err as Error).message },\n '[agent-custom] failed to persist assistant turn'\n );\n }\n try {\n closed = true;\n controller.close();\n } catch {\n // already closed\n }\n }\n }\n });\n\n return new Response(stream, {\n headers: {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive'\n }\n });\n }\n };\n}\n","/**\n * Vercel AI SDK tool adapter.\n *\n * Translates the package's `ToolsPort.tools` (the same registry the custom\n * SSE chat consumes) into Vercel AI SDK 4's `tool({...})` map so\n * `streamText({ tools, ... })` can drive the same tool loop natively.\n *\n * Two pieces of behaviour are reproduced from `runAgent`:\n * - `SELF_VERIFY_REQUIRED` gate — the model must run at least two prior\n * tool calls before `present`. We track `toolCallCount` in a closure.\n * - `present` is the terminal tool — its blocks become custom data parts\n * on the `StreamData` writer (so the client renders charts/tables) and\n * the route persists the structured payload via `onPresent`.\n *\n * Tool execute results are surfaced to the model as either `data` (success)\n * or `{ error: { code, message } }` (failure), matching the envelope the\n * model already understands from the custom-route's tool-result frames.\n */\nimport { tool, type Tool } from 'ai';\nimport type { StreamData } from 'ai';\nimport type {\n PresentPayload,\n ToolContext,\n ToolDefinition\n} from './tools/types';\nimport { TERMINAL_TOOL_NAME } from './tools/types';\n\n// `Tool`'s default generic is `<any, any>` already; using the wider\n// signature here lets us mix tools whose Zod schemas / result shapes\n// differ (the SDK validates them per-tool at call time).\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type VercelToolMap = Record<string, Tool<any, any>>;\n\n/**\n * Build a Vercel AI SDK tool map from the host's tool registry.\n *\n * @throws if any tool is registered without a `zodSchema` — the SDK's\n * `tool({ parameters })` requires a Zod (or AI SDK Schema) instance\n * to validate the model's tool-call arguments.\n */\nexport function buildVercelTools<S>(\n tools: Record<string, ToolDefinition<unknown, S>>,\n ctx: ToolContext<S>,\n data: StreamData,\n onPresent: (payload: PresentPayload) => void\n): VercelToolMap {\n const result: VercelToolMap = {};\n let toolCallCount = 0;\n\n for (const [name, def] of Object.entries(tools)) {\n if (!def.zodSchema) {\n throw new Error(\n `Tool '${name}' has no zodSchema; required for the Vercel AI SDK chat. ` +\n `Add a Zod schema to the tool definition (or remove it from the registry ` +\n `if the host only uses the custom SSE chat).`\n );\n }\n\n if (name === TERMINAL_TOOL_NAME) {\n result[name] = tool({\n description: def.schema.description,\n // The Zod schema doubles as the runtime parameter validator the SDK\n // hands the model. We accept whatever Zod shape the host registered;\n // the SDK uses it to validate the tool-call arguments before dispatch.\n parameters: def.zodSchema,\n execute: async (input: unknown) => {\n // Mirror runAgent's self-verify gate. Once present has been\n // requested with toolCallCount < 2, return an error envelope so\n // the model retries with at least one cross-check tool call.\n if (toolCallCount < 2) {\n return {\n error: {\n code: 'SELF_VERIFY_REQUIRED',\n message:\n 'Per FR-8.3 you must run at least one CROSS-CHECK tool call (a different metric, a different period, or a run_sql sanity-check) before present. Make that extra call now, then call present again.'\n }\n };\n }\n const payload = input as PresentPayload;\n // Forward each block to the client as a custom data part. The\n // route persists the same payload via `onPresent`. Block values\n // round-trip as JSON; we cast through `unknown` because chart\n // blocks carry `Record<string, unknown>` cells which are\n // structurally JSON-safe but don't satisfy the AI SDK's narrow\n // `JSONValue` recursive type.\n for (let i = 0; i < payload.blocks.length; i++) {\n data.append({\n type: 'block',\n value: { index: i, ...payload.blocks[i] }\n } as unknown as Parameters<StreamData['append']>[0]);\n }\n onPresent(payload);\n return { ok: true };\n }\n });\n continue;\n }\n\n result[name] = tool({\n description: def.schema.description,\n parameters: def.zodSchema,\n execute: async (input: unknown) => {\n const res = await def.execute(input, { ...ctx, toolCallCount });\n toolCallCount += 1;\n if (res.ok) return res.data as unknown;\n return { error: res.error };\n }\n });\n }\n\n return result;\n}\n","/**\n * `agent-vercel` route factory.\n *\n * Peer to `agent-custom`: same persistence, same tool catalogue, same\n * scope/auth ports, same lifecycle hooks — different transport. Vercel AI\n * SDK 4's `streamText({ tools })` runs the agent loop natively and emits a\n * data stream the `useChat` hook in `@ai-sdk/react` consumes. The\n * structured `present` payload is forwarded as custom `block` data parts\n * (see `vercel-adapter.ts`) so the same `AnswerBlocks` component renders\n * charts/tables identically across both UI shells.\n *\n * Differences from the custom SSE route:\n * - No bespoke SSE protocol — `result.toDataStreamResponse({ data })`.\n * - No separate narrator pass — `streamText` produces prose directly,\n * and the prose is attributed to the first `paragraph_brief` block on\n * persistence (the AI SDK doesn't split prose per-block).\n * - System-prompt `cached` markers are dropped on this path: the AI\n * SDK's `system` parameter is a single string (not an array of\n * blocks). Vertex auto-caches stable prefixes regardless.\n */\nimport { randomUUID } from 'crypto';\nimport { streamText, StreamData } from 'ai';\nimport { createVertex } from '@ai-sdk/google-vertex';\nimport { createVertexAnthropic } from '@ai-sdk/google-vertex/anthropic';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from '../ports/types';\nimport type {\n Block,\n PresentPayload,\n ToolContext\n} from '../tools/types';\nimport type { ToolDefinition } from '../tools/types';\nimport type { AgentCustomHooks } from './agent-custom';\nimport { buildVercelTools } from '../vercel-adapter';\n\n/**\n * Streaming-route hooks for the Vercel AI SDK chat.\n *\n * Identical to `AgentCustomHooks` — the lifecycle (pre-auth → auth →\n * post-auth → resolve session → onSessionStart → stream → onSessionEnd)\n * is the same. We re-alias rather than introducing a new type so consumers\n * can plug a single hook bag into both routes.\n */\nexport type AgentVercelHooks<S> = AgentCustomHooks<S>;\n\nexport type AgentVercelRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Optional lifecycle hooks. See `AgentCustomHooks` for the available\n * extension points (shutdown gating, rate limiting, per-request\n * resource setup/teardown).\n */\n hooks?: AgentVercelHooks<S>;\n};\n\nconst VALID_MODELS: ReadonlySet<string> = new Set(['claude', 'gemini']);\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'Content-Type': 'application/json' }\n });\n}\n\nfunction defaultGenerateSessionId(): string {\n return randomUUID().replace(/-/g, '').slice(0, 16);\n}\n\nexport function createAgentVercelRoutes<S>(ctx: AgentVercelRouteCtx<S>) {\n const { persistence, auth, scope, tools, vertex, logger, hooks } = ctx;\n\n return {\n /** Next.js-compatible POST handler. */\n POST: async (req: Request): Promise<Response> => {\n // 0. Pre-auth hook (e.g. shutdown gate → 503).\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n\n // 1. Authenticate via host port.\n const authResult = await auth.requireAuth(req);\n if (!authResult.ok) return authResult.response;\n const { scope: callerScope, userId } = authResult;\n\n // 1b. Post-auth hook (e.g. rate limit → 429).\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: callerScope,\n userId\n });\n if (short) return short;\n }\n\n // 2. Parse + validate body.\n const body = (await req.json().catch(() => null)) as\n | {\n question?: unknown;\n chatSessionId?: unknown;\n model?: unknown;\n }\n | null;\n const question =\n typeof body?.question === 'string' ? body.question.trim() : '';\n if (!question) {\n return jsonError(\n 400,\n 'VALIDATION_FAILED',\n 'question must be a non-empty string.'\n );\n }\n const rawChatSessionId = body?.chatSessionId;\n const incomingChatSessionId =\n typeof rawChatSessionId === 'number' &&\n Number.isInteger(rawChatSessionId)\n ? rawChatSessionId\n : null;\n const rawModel = body?.model;\n const requestedModel =\n typeof rawModel === 'string' && VALID_MODELS.has(rawModel)\n ? (rawModel as 'claude' | 'gemini')\n : null;\n\n // 3. AI settings (singleton).\n const aiSettings = await persistence.getAiSettings();\n\n // 4 & 5. Resolve / create the chat session, then persist the user turn.\n let chatSessionId: number;\n if (incomingChatSessionId !== null) {\n const owned = await persistence.getSession(\n incomingChatSessionId,\n userId\n );\n if (!owned) {\n return jsonError(404, 'NOT_FOUND', 'Chat session not found.');\n }\n chatSessionId = owned.id;\n } else {\n const created = await persistence.createSession({\n userId,\n title: question.slice(0, 200)\n });\n chatSessionId = created.id;\n }\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'user',\n question\n });\n\n // 5b. Resolve the per-request session id (fresh, ephemeral, never\n // collides with the persistent chatSessionId).\n const sessionId: string = hooks?.generateSessionId\n ? await hooks.generateSessionId({\n scope: callerScope,\n userId,\n chatSessionId: incomingChatSessionId\n })\n : defaultGenerateSessionId();\n\n // 6 & 7. Build ToolContext + system blocks.\n const scopeSummary = await scope.buildScopeSummary(callerScope);\n const scopeLabel = await scope.resolveScopeLabel(callerScope);\n const toolContext: ToolContext<S> = {\n scope: callerScope,\n sessionId,\n scopeSummary,\n toolCallCount: 0\n };\n const systemBlocks = await tools.buildSystemBlocks(toolContext);\n\n // 8. Resolve the model. Body override wins; otherwise fall back to\n // the singleton's `toolProvider`. Only `claude` and `gemini` are\n // valid here — Grok isn't routed through `@ai-sdk/google-vertex`.\n const provider: string = requestedModel ?? aiSettings.toolProvider;\n if (!VALID_MODELS.has(provider)) {\n return jsonError(\n 400,\n 'INVALID_PROVIDER',\n `Vercel chat only supports 'claude' or 'gemini'; got '${provider}'.`\n );\n }\n\n // 9. Open the data stream and assemble the rest under try/catch/finally\n // so `onSessionEnd` always runs and `data.close()` is guaranteed.\n const data = new StreamData();\n let presentPayload: PresentPayload | null = null;\n let persistedError: { code: string; message: string } | null = null;\n let sessionStarted = false;\n\n try {\n // 9a. Per-request resource setup (e.g. SQL view creation). Errors\n // here surface as a normal error data part and are persisted with\n // the assistant turn.\n if (hooks?.onSessionStart) {\n await hooks.onSessionStart({\n scope: callerScope,\n sessionId,\n userId\n });\n }\n sessionStarted = true;\n\n // 9b. Build the Vercel tool map (validates `zodSchema` presence).\n const vercelTools = buildVercelTools(\n tools.tools as Record<string, ToolDefinition<unknown, S>>,\n toolContext,\n data,\n (p) => {\n presentPayload = p;\n }\n );\n\n // 9c. Meta data part — the UI uses these to render the scope chip\n // and pin the persistent chat session id immediately on first byte.\n data.append({\n type: 'meta',\n value: { chatSessionId, scopeLabel }\n });\n\n // 9d. Compose the system prompt. The AI SDK's `system` parameter\n // is a single string — `SystemBlock.cached` markers from the host\n // are dropped on this path (Vertex auto-caches stable prefixes\n // regardless of the hint).\n const system = systemBlocks.map((b) => b.text).join('\\n\\n');\n\n // 9e. Construct the model. Both providers accept `googleAuthOptions`\n // (a `GoogleAuthOptions` bag); they construct their own\n // `GoogleAuth` internally. Our `VertexPort.auth` is a constructed\n // `GoogleAuth` instance — the SDK can't accept it directly, so we\n // pass an empty options object and rely on the same ADC the host's\n // `GoogleAuth` resolves through. (Hosts that need explicit\n // credentials should wire them through ADC env vars / metadata\n // server, which both auth paths consume identically.)\n const model =\n provider === 'claude'\n ? createVertexAnthropic({\n project: vertex.projectId,\n location: vertex.defaultLocation,\n googleAuthOptions: {}\n })(vertex.modelIds.claude)\n : createVertex({\n project: vertex.projectId,\n location: aiSettings.gcpLocation,\n googleAuthOptions: {}\n })(vertex.modelIds.gemini);\n\n const result = streamText({\n model,\n system,\n messages: [{ role: 'user', content: question }],\n tools: vercelTools,\n maxSteps: 12,\n maxTokens: aiSettings.maxOutputTokens,\n onFinish: async ({ text }) => {\n try {\n // Persist the assistant turn. Mirror the custom adapter's\n // wire shape: `blocks` carries the structured payload,\n // `prose[blockIndex]` carries the prose for paragraph_brief\n // blocks. Since `streamText` produces a single text stream\n // (no per-block split), we attribute the whole text to the\n // FIRST `paragraph_brief` block when one exists.\n let blocks: Block[] = presentPayload?.blocks ?? [];\n const prose: Record<number, string> = {};\n const trimmed = (text ?? '').trim();\n\n if (presentPayload === null && trimmed) {\n // AGENT_NO_PRESENT fallback (mirrors agent.ts:103-119).\n // The model produced text but never called `present` —\n // synthesise a paragraph_brief block so the user always\n // gets the response. Append the synthetic block to the\n // stream BEFORE closing so the client renders it as a\n // normal block.\n const topic =\n question.length > 80\n ? question.slice(0, 77) + '...'\n : question;\n const synthetic: Block = {\n kind: 'paragraph_brief',\n topic,\n key_facts: [trimmed]\n };\n blocks = [synthetic];\n prose[0] = trimmed;\n data.append({\n type: 'block',\n value: { index: 0, ...synthetic }\n });\n } else if (text) {\n const firstPbIdx = blocks.findIndex(\n (b) => b.kind === 'paragraph_brief'\n );\n if (firstPbIdx >= 0) prose[firstPbIdx] = text;\n }\n\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: blocks.length ? blocks : null,\n prose: Object.keys(prose).length ? prose : null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n err: (err as Error).message\n },\n '[agent-vercel] failed to persist assistant turn'\n );\n } finally {\n try {\n await data.close();\n } catch {\n // already closed\n }\n }\n }\n });\n\n // The Vercel AI SDK runs the loop lazily as the response stream is\n // consumed; `toDataStreamResponse` returns a Response whose body\n // pulls from `result` on demand. `onSessionEnd` fires in the\n // `finally` below, but it must NOT wait on the stream (the route\n // returns before the client has consumed it). The lifecycle hook\n // therefore runs at request-handler exit, not stream completion —\n // matching the custom-route's `onSessionEnd` contract (always-runs,\n // never throws out).\n return result.toDataStreamResponse({ data });\n } catch (e) {\n const message = (e as Error).message ?? 'Internal error';\n persistedError = { code: 'INTERNAL', message };\n logger?.error?.(\n { chatSessionId, sessionId, err: message },\n '[agent-vercel] route errored'\n );\n try {\n data.append({\n type: 'error',\n value: { code: 'INTERNAL', message }\n });\n } catch {\n // ignore — stream already closed.\n }\n try {\n await data.close();\n } catch {\n // ignore.\n }\n // Persist the assistant error so the session row is consistent.\n try {\n await persistence.appendMessage({\n sessionId: chatSessionId,\n role: 'assistant',\n blocks: null,\n prose: null,\n errorJson: persistedError\n });\n } catch (err) {\n logger?.warn?.(\n { chatSessionId, sessionId, err: (err as Error).message },\n '[agent-vercel] failed to persist error turn'\n );\n }\n return jsonError(500, 'INTERNAL', message);\n } finally {\n // Always-runs teardown, symmetric to agent-custom. Errors here are\n // logged but never surfaced.\n if (hooks?.onSessionEnd) {\n const cause: 'complete' | 'error' | 'abort' = req.signal.aborted\n ? 'abort'\n : persistedError\n ? 'error'\n : 'complete';\n try {\n await hooks.onSessionEnd({\n scope: callerScope,\n sessionId,\n userId,\n cause\n });\n } catch (err) {\n logger?.warn?.(\n {\n chatSessionId,\n sessionId,\n sessionStarted,\n err: (err as Error).message\n },\n '[agent-vercel] onSessionEnd hook failed'\n );\n }\n }\n }\n }\n };\n}\n","/**\n * `chat-sessions` route factory — host-agnostic CRUD for chat sessions.\n *\n * Mounts at `/api/chat/sessions` (list+create) and `/api/chat/sessions/[id]`\n * (get one with messages, rename, delete). Auth and persistence cross the\n * boundary as ports; the package never touches a DB or session adapter.\n *\n * Wire format mirrors the host's pre-extraction Next route handlers so the\n * existing UI keeps working unchanged when the host swaps to these factories.\n */\nimport type { AuthPort, LoggerPort, PersistencePort, ChatSession } from '../ports/types';\nimport type { RouteHooks } from './agent-custom';\n\nexport type ChatSessionsRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n logger?: LoggerPort;\n /**\n * Optional pre-auth / post-auth hooks (e.g. shutdown gate, rate\n * limiting). The streaming-specific hooks on `AgentCustomHooks` are\n * ignored here — only `onRequest` and `onAuthenticated` apply.\n */\n hooks?: RouteHooks<S>;\n};\n\nconst DEFAULT_TITLE = 'New chat';\nconst TITLE_MAX = 200;\n\n// ---------------------------------------------------------------------------\n// Tiny inline response helpers — kept here so the package has no shared\n// `lib/api` of its own. These mirror the slice of the host's `apiError`\n// envelope the chat routes actually emit.\n// ---------------------------------------------------------------------------\n\ntype ApiErrorCode =\n | 'UNAUTHORIZED'\n | 'NOT_FOUND'\n | 'VALIDATION_FAILED'\n | 'INTERNAL';\n\nconst STATUS_BY_CODE: Record<ApiErrorCode, number> = {\n UNAUTHORIZED: 401,\n NOT_FOUND: 404,\n VALIDATION_FAILED: 400,\n INTERNAL: 500\n};\n\nfunction apiError(code: ApiErrorCode, message: string): Response {\n return Response.json(\n { error: { code, message, details: {} } },\n { status: STATUS_BY_CODE[code] }\n );\n}\n\nfunction okJson(data: unknown): Response {\n return Response.json(data);\n}\n\n// ---------------------------------------------------------------------------\n// Serialisation — domain types use Date; the wire format is ISO strings.\n// ---------------------------------------------------------------------------\n\nfunction serializeSession(s: ChatSession) {\n return {\n id: s.id,\n title: s.title,\n createdAt: s.createdAt ? s.createdAt.toISOString() : null,\n updatedAt: s.updatedAt ? s.updatedAt.toISOString() : null\n };\n}\n\nfunction parseSessionId(raw: string): number | null {\n const id = Number(raw);\n if (!Number.isInteger(id) || id <= 0) return null;\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createChatSessionsRoutes<S>(ctx: ChatSessionsRouteCtx<S>) {\n const { persistence, auth, logger, hooks } = ctx;\n\n /**\n * Run the standard hook chain (`onRequest` → auth → `onAuthenticated`)\n * shared by every handler below. Returns either a short-circuit\n * Response (hook said no, or auth failed) OR the resolved scope/userId\n * for the handler to continue with.\n */\n async function gate(\n req: Request\n ): Promise<{ short: Response } | { ok: true; scope: S; userId: number }> {\n if (hooks?.onRequest) {\n const r = await hooks.onRequest(req);\n if (r) return { short: r };\n }\n const authed = await auth.requireAuth(req);\n if (!authed.ok) return { short: authed.response };\n if (hooks?.onAuthenticated) {\n const r = await hooks.onAuthenticated({\n req,\n scope: authed.scope,\n userId: authed.userId\n });\n if (r) return { short: r };\n }\n return { ok: true, scope: authed.scope, userId: authed.userId };\n }\n\n const list = {\n /**\n * `GET /api/chat/sessions` — caller's recent sessions, newest first,\n * capped at 100. Response: `{ sessions: [{ id, title, createdAt, updatedAt }] }`.\n */\n GET: async (req: Request): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const rows = await persistence.listSessionsForUser(g.userId, { limit: 100 });\n return okJson({ sessions: rows.map(serializeSession) });\n } catch (err) {\n logger?.error('[chat-sessions] list.GET failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `POST /api/chat/sessions` — body `{ title?: string }`. Trims and caps\n * title at 200 chars; defaults to \"New chat\" when blank.\n * Response: `{ session: { id, title, createdAt, updatedAt } }`.\n */\n POST: async (req: Request): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const body = (await req.json().catch(() => ({}))) as { title?: unknown };\n const rawTitle = typeof body.title === 'string' ? body.title.trim() : '';\n const title = rawTitle ? rawTitle.slice(0, TITLE_MAX) : DEFAULT_TITLE;\n const created = await persistence.createSession({ userId: g.userId, title });\n return okJson({ session: serializeSession(created) });\n } catch (err) {\n logger?.error('[chat-sessions] list.POST failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n }\n };\n\n const detail = {\n /**\n * `GET /api/chat/sessions/[id]` — session metadata + ordered messages.\n * 404 when the id doesn't exist or doesn't belong to the caller (we never\n * differentiate the two, to avoid leaking the id space).\n * Response: `{ session: { id, title, createdAt, updatedAt },\n * messages: [{ id, role, question, blocks, prose, errorJson, createdAt }] }`.\n */\n GET: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n const messages = await persistence.listMessagesForSession(id, g.userId);\n return okJson({\n session: serializeSession(meta),\n messages: messages.map((m) => ({\n id: m.id,\n role: m.role,\n question: m.question,\n blocks: m.blocks,\n prose: m.prose,\n errorJson: m.errorJson,\n createdAt: m.createdAt ? m.createdAt.toISOString() : null\n }))\n });\n } catch (err) {\n logger?.error('[chat-sessions] detail.GET failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `PATCH /api/chat/sessions/[id]` — rename. Body `{ title: string }`,\n * trimmed and capped at 200 chars. Response: `{ ok: true }`.\n */\n PATCH: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n\n const body = (await req.json().catch(() => ({}))) as { title?: unknown };\n if (typeof body.title !== 'string') {\n return apiError('VALIDATION_FAILED', 'title must be a string.');\n }\n const trimmed = body.title.trim();\n if (!trimmed) {\n return apiError('VALIDATION_FAILED', 'title must not be empty.');\n }\n await persistence.updateSession(id, g.userId, {\n title: trimmed.slice(0, TITLE_MAX)\n });\n return okJson({ ok: true });\n } catch (err) {\n logger?.error('[chat-sessions] detail.PATCH failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n },\n\n /**\n * `DELETE /api/chat/sessions/[id]` — drop session and its messages.\n * Response: `{ ok: true }`.\n */\n DELETE: async (req: Request, params: { id: string }): Promise<Response> => {\n try {\n const g = await gate(req);\n if ('short' in g) return g.short;\n const id = parseSessionId(params.id);\n if (id === null) return apiError('NOT_FOUND', 'Chat session not found.');\n const meta = await persistence.getSession(id, g.userId);\n if (!meta) return apiError('NOT_FOUND', 'Chat session not found.');\n await persistence.deleteSession(id, g.userId);\n return okJson({ ok: true });\n } catch (err) {\n logger?.error('[chat-sessions] detail.DELETE failed', err);\n const msg = err instanceof Error ? err.message : 'Internal error';\n return apiError('INTERNAL', msg);\n }\n }\n };\n\n return { list, detail };\n}\n","/**\n * `/api/admin/ai-settings` route factory — global AI configuration (super_admin only).\n *\n * Five patchable fields on the singleton settings row:\n * - `tool_provider` — vendor that drives the agent tool loop. Validated\n * against the registered `toolProviders` registry passed in via ctx.\n * - `gcp_location` — the Vertex region every provider call hits. Stays\n * a fixed list ('us-east5', 'global') because those are the only\n * regions Claude/Gemini are published in on Vertex.\n * - `chat_interface` — which chat UI module renders globally. Validated\n * against the `chatInterfaces` registry passed in via ctx (the actual\n * registry lives in `@firstlovecenter/ai-chat/ui` so the host wires it through;\n * the route stays free of UI imports).\n * - `max_output_tokens` — caps the agent loop's per-turn output AND each\n * narrator's prose pass. Bounded `[256, 64000]` — anything below 256 can't\n * fit a useful response, anything above 64000 exceeds the headroom of any\n * model currently routed through Vertex.\n * - `role_prompt` — admin-editable persona string. Empty string and the\n * explicit JSON `null` both clear the override back to the host's static\n * `configureAiChat({ rolePrompt })` fallback; we canonicalise an empty/\n * whitespace-only string to `null` on write so the \"no override\" state has\n * a single representation in storage.\n *\n * Wire format is snake_case to preserve byte-for-byte parity with the\n * host route the package replaces — existing host UIs keep working\n * unmodified.\n */\nimport type { AuthPort, LoggerPort, PersistencePort, AiSettingsPatch } from '../ports/types';\nimport type { RouteHooks } from './agent-custom';\n\nexport type AdminSettingsRouteCtx<S> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n /** Registered tool providers (default: built-in toolProviders array). */\n toolProviders: { id: string; label?: string; description?: string }[];\n /** Registered chat interface ids (host or UI module supplies the list). */\n chatInterfaces: { id: string }[];\n logger?: LoggerPort;\n /**\n * Optional pre-auth / post-auth hooks (e.g. shutdown gate, rate\n * limiting). Streaming-specific hooks are not applicable here.\n */\n hooks?: RouteHooks<S>;\n};\n\nconst VALID_LOCATIONS = ['us-east5', 'global'] as const;\n\n/** Inclusive bounds for `max_output_tokens`. See module-level docblock. */\nconst MIN_MAX_OUTPUT_TOKENS = 256;\nconst MAX_MAX_OUTPUT_TOKENS = 64_000;\n\ntype WireSettings = {\n tool_provider: string;\n gcp_location: string;\n chat_interface: string;\n max_output_tokens: number;\n role_prompt: string | null;\n updated_at: string | null;\n updated_by_user_id: number | null;\n};\n\nfunction isStringRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction jsonResponse(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' }\n });\n}\n\nfunction toWire(settings: {\n toolProvider: string;\n gcpLocation: string;\n chatInterface: string;\n maxOutputTokens: number;\n rolePrompt: string | null;\n updatedAt: Date | null;\n updatedByUserId: number | null;\n}): WireSettings {\n return {\n tool_provider: settings.toolProvider,\n gcp_location: settings.gcpLocation,\n chat_interface: settings.chatInterface,\n max_output_tokens: settings.maxOutputTokens,\n role_prompt: settings.rolePrompt,\n updated_at: settings.updatedAt ? settings.updatedAt.toISOString() : null,\n updated_by_user_id: settings.updatedByUserId\n };\n}\n\nexport function createAdminSettingsRoutes<S>(ctx: AdminSettingsRouteCtx<S>) {\n const { persistence, auth, toolProviders, chatInterfaces, logger, hooks } = ctx;\n\n async function GET(req: Request): Promise<Response> {\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n const result = await auth.requireAuth(req);\n if (!result.ok) return result.response;\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: result.scope,\n userId: result.userId\n });\n if (short) return short;\n }\n if (!auth.isSuperAdmin(result.scope)) {\n return jsonResponse(\n { error: 'forbidden', message: 'Only super admins can read AI settings.' },\n 403\n );\n }\n const settings = await persistence.getAiSettings();\n return jsonResponse(toWire(settings));\n }\n\n async function PATCH(req: Request): Promise<Response> {\n if (hooks?.onRequest) {\n const short = await hooks.onRequest(req);\n if (short) return short;\n }\n const result = await auth.requireAuth(req);\n if (!result.ok) return result.response;\n if (hooks?.onAuthenticated) {\n const short = await hooks.onAuthenticated({\n req,\n scope: result.scope,\n userId: result.userId\n });\n if (short) return short;\n }\n if (!auth.isSuperAdmin(result.scope)) {\n return jsonResponse(\n { error: 'forbidden', message: 'Only super admins can change AI settings.' },\n 403\n );\n }\n\n const body = (await req.json().catch(() => null)) as unknown;\n if (!isStringRecord(body)) {\n return jsonResponse({ error: 'invalid_body', message: 'Body must be JSON.' }, 400);\n }\n\n const patch: AiSettingsPatch = {};\n\n if ('tool_provider' in body) {\n const v = body.tool_provider;\n const validIds = toolProviders.map((p) => p.id);\n if (typeof v !== 'string' || !validIds.includes(v)) {\n return jsonResponse({ error: 'invalid_tool_provider' }, 400);\n }\n patch.toolProvider = v;\n }\n\n if ('gcp_location' in body) {\n const v = body.gcp_location;\n if (typeof v !== 'string' || !VALID_LOCATIONS.includes(v as (typeof VALID_LOCATIONS)[number])) {\n return jsonResponse({ error: 'invalid_gcp_location' }, 400);\n }\n patch.gcpLocation = v;\n }\n\n if ('chat_interface' in body) {\n const v = body.chat_interface;\n const validIds = chatInterfaces.map((i) => i.id);\n if (typeof v !== 'string' || !validIds.includes(v)) {\n return jsonResponse({ error: 'invalid_chat_interface' }, 400);\n }\n patch.chatInterface = v;\n }\n\n if ('max_output_tokens' in body) {\n const v = body.max_output_tokens;\n if (\n typeof v !== 'number' ||\n !Number.isInteger(v) ||\n v < MIN_MAX_OUTPUT_TOKENS ||\n v > MAX_MAX_OUTPUT_TOKENS\n ) {\n return jsonResponse({ error: 'invalid_max_output_tokens' }, 400);\n }\n patch.maxOutputTokens = v;\n }\n\n if ('role_prompt' in body) {\n const v = body.role_prompt;\n if (v === null) {\n patch.rolePrompt = null;\n } else if (typeof v === 'string') {\n const trimmed = v.trim();\n // Canonicalise an empty / whitespace-only string to null so the\n // \"no override\" state has exactly one shape in storage.\n patch.rolePrompt = trimmed === '' ? null : trimmed;\n } else {\n return jsonResponse({ error: 'invalid_role_prompt' }, 400);\n }\n }\n\n if (\n patch.toolProvider === undefined &&\n patch.gcpLocation === undefined &&\n patch.chatInterface === undefined &&\n patch.maxOutputTokens === undefined &&\n !('rolePrompt' in patch)\n ) {\n return jsonResponse(\n {\n error: 'empty_patch',\n message:\n 'Body must set at least one of tool_provider, gcp_location, chat_interface, max_output_tokens, role_prompt.'\n },\n 400\n );\n }\n\n try {\n const updated = await persistence.updateAiSettings(patch, result.userId);\n return jsonResponse(toWire(updated));\n } catch (err) {\n logger?.error('admin-settings PATCH failed', err);\n throw err;\n }\n }\n\n return { GET, PATCH };\n}\n","/**\n * `configureAiChat({...})` — the runtime factory hosts call once at boot.\n *\n * Takes the five injected ports (persistence, auth, scope, tools, vertex)\n * plus a couple of optional bits (logger, narrator resolver, chat-interface\n * registry, extra tool providers) and returns:\n *\n * - `runAgent` — pre-bound agent loop wrapper.\n * - `routes.agentCustom` — Next-compatible POST handler for the SSE chat.\n * - `routes.chatSessions` — list/POST + detail GET/PATCH/DELETE.\n * - `routes.adminSettings`— admin GET/PATCH.\n * - `registries.toolProviders` — built-in (claude, gemini) plus any host extras.\n *\n * The host wires each route in its own `app/api/.../route.ts` as a thin\n * re-export. Nothing in this package reads `process.env` or imports from\n * the host.\n */\nimport { runAgent as runAgentLoop } from './agent';\nimport type { AgentResult, AgentInput } from './agent';\nimport {\n toolProviders as BUILTIN_TOOL_PROVIDERS,\n getToolProvider as builtinGetToolProvider\n} from './providers';\nimport type { ToolProviderDef } from './providers';\nimport type {\n AuthPort,\n LoggerPort,\n PersistencePort,\n ScopePort,\n ToolsPort,\n VertexPort\n} from './ports/types';\nimport type { ToolContext, ToolDefinition } from './tools/types';\nimport { createAgentCustomRoutes } from './routes/agent-custom';\nimport type { AgentCustomHooks } from './routes/agent-custom';\nimport { createAgentVercelRoutes } from './routes/agent-vercel';\nimport { createChatSessionsRoutes } from './routes/chat-sessions';\nimport { createAdminSettingsRoutes } from './routes/admin-settings';\n\n/** Default ids that match the components shipped in `@firstlovecenter/ai-chat/ui`. */\nexport const BUILTIN_CHAT_INTERFACE_IDS = ['custom', 'vercel'] as const;\n\nexport type ChatInterfaceRegistryEntry = { id: string };\n\nexport type ConfigureAiChatOpts<S = unknown> = {\n persistence: PersistencePort;\n auth: AuthPort<S>;\n scope: ScopePort<S>;\n tools: ToolsPort;\n vertex: VertexPort;\n logger?: LoggerPort;\n /**\n * Resolve which narrator drives the prose pass. Defaults to the\n * current `aiSettings.toolProvider` (claude → claude narrator, gemini →\n * gemini narrator). Override when the host stores a per-user choice.\n */\n resolveNarratorId?: (scope: S) => Promise<'claude' | 'gemini' | 'grok'>;\n /**\n * Chat-interface ids the admin route accepts. Defaults to\n * BUILTIN_CHAT_INTERFACE_IDS (custom, vercel). Hosts that ship only one\n * UI can subset; hosts that register a new one extend.\n */\n chatInterfaces?: ChatInterfaceRegistryEntry[];\n /**\n * Additional tool-calling providers beyond the built-in claude/gemini.\n * Merged into the registry the admin route validates against.\n */\n extraToolProviders?: ToolProviderDef[];\n /**\n * Optional lifecycle hooks shared across all three route factories.\n * The full superset (`AgentCustomHooks`) covers the SSE chat route;\n * `chatSessions` and `adminSettings` only consume the\n * `onRequest` / `onAuthenticated` subset.\n *\n * Common host plumbing this enables (without forking the package):\n * - `onRequest` — shutdown gating (503 + Retry-After).\n * - `onAuthenticated` — per-user rate limiting (429 + Retry-After).\n * - `generateSessionId`— project-specific session ids (e.g. SQL view names).\n * - `onSessionStart` — per-request resource setup (e.g. CREATE VIEW).\n * - `onSessionEnd` — cleanup (always-runs, never throws out).\n */\n hooks?: AgentCustomHooks<S>;\n /**\n * Persona / role given to the AI as the very first cached system block\n * on every turn. Use this to give the assistant a consistent voice and\n * domain perspective across all conversations in your app.\n *\n * Accepts:\n * - a `string` for a static org-wide role, or\n * - a `(ctx) => string | Promise<string>` function for per-request\n * variation (different role per scope, per locale, per A/B cohort).\n *\n * Token economics: the role text is sent on every turn (Vertex APIs\n * are stateless), but it is marked `cached: true`. On Claude that\n * becomes an ephemeral `cache_control` marker — first turn pays ~1.25×\n * for the cache write; subsequent turns within ~5 min pay ~0.1× for\n * cache reads. On Gemini the hint is informational; Vertex auto-caches\n * stable prefixes regardless. For a typical 200–500 token role, the\n * per-turn marginal cost after the first is negligible. The package\n * caps total `cache_control` markers at Anthropic's 4-per-request\n * limit; if the host already marks 4 blocks cached, the extras\n * (including this one if last) silently drop the cache hint rather\n * than reject the request.\n *\n * Example (static):\n * rolePrompt: `You are the head pastor of First Love Center, a\n * multinational church operating across multiple countries. Frame\n * answers from the perspective of advancing the gospel through\n * sustainable growth, financial discipline, compliance, and church\n * planting. Be direct, pastoral, and action-oriented.`\n */\n rolePrompt?: string | ((ctx: ToolContext<S>) => string | Promise<string>);\n};\n\nexport type AiChatRuntime<S = unknown> = {\n /**\n * Pre-bound agent loop. Most hosts call routes instead — but the bound\n * runner is exposed for non-HTTP entry points (jobs, eval harnesses).\n */\n runAgent: (input: {\n question: string;\n ctx: ToolContext<S>;\n /** Override the provider id picked from `aiSettings.toolProvider`. */\n providerId?: string;\n /** Override the location picked from `aiSettings.gcpLocation`. */\n location?: string;\n maxToolTurns?: number;\n maxOutputTokens?: number;\n }) => Promise<AgentResult>;\n routes: {\n agentCustom: ReturnType<typeof createAgentCustomRoutes<S>>;\n agentVercel: ReturnType<typeof createAgentVercelRoutes<S>>;\n chatSessions: ReturnType<typeof createChatSessionsRoutes<S>>;\n adminSettings: ReturnType<typeof createAdminSettingsRoutes<S>>;\n };\n registries: {\n toolProviders: ToolProviderDef[];\n chatInterfaces: ChatInterfaceRegistryEntry[];\n };\n};\n\nexport function configureAiChat<S = unknown>(\n opts: ConfigureAiChatOpts<S>\n): AiChatRuntime<S> {\n const toolProviders = [\n ...BUILTIN_TOOL_PROVIDERS,\n ...(opts.extraToolProviders ?? [])\n ];\n const getProvider = (id: string): ToolProviderDef | undefined =>\n toolProviders.find((p) => p.id === id) ?? builtinGetToolProvider(id);\n\n const chatInterfaces: ChatInterfaceRegistryEntry[] =\n opts.chatInterfaces ?? BUILTIN_CHAT_INTERFACE_IDS.map((id) => ({ id }));\n\n // Wrap the host's `buildSystemBlocks` so a role prompt is always\n // prepended as the first (cached) system block. Both the bound\n // runAgent and the agent-custom / agent-vercel routes consume `tools`\n // through this wrapper, so the role is applied uniformly.\n //\n // Resolution order per request:\n // 1. `aiSettings.rolePrompt` (DB) — admin-editable, takes precedence.\n // 2. `opts.rolePrompt` (host static) — string or `(ctx) => string`.\n // 3. None — no role block is prepended.\n //\n // The DB read adds one singleton lookup per turn; cheap (in-buffer\n // pool) and lets admins flip the persona without redeploying.\n const staticRolePrompt = opts.rolePrompt;\n const tools: ToolsPort = {\n tools: opts.tools.tools,\n async buildSystemBlocks(ctx) {\n const inner = await opts.tools.buildSystemBlocks(ctx);\n let role: string | null = null;\n try {\n const settings = await opts.persistence.getAiSettings();\n if (settings.rolePrompt && settings.rolePrompt.trim()) {\n role = settings.rolePrompt;\n }\n } catch {\n // Persistence read failure — fall through to the static fallback.\n }\n if (!role && staticRolePrompt) {\n const resolved =\n typeof staticRolePrompt === 'function'\n ? await staticRolePrompt(ctx as ToolContext<S>)\n : staticRolePrompt;\n if (resolved && resolved.trim()) role = resolved;\n }\n if (!role) return inner;\n return [{ text: role, cached: true }, ...inner];\n }\n };\n\n const runAgentBound: AiChatRuntime<S>['runAgent'] = async ({\n question,\n ctx,\n providerId,\n location,\n maxToolTurns,\n maxOutputTokens\n }) => {\n const settings = await opts.persistence.getAiSettings();\n const def = getProvider(providerId ?? settings.toolProvider);\n if (!def) {\n throw new Error(\n `Unknown tool provider '${providerId ?? settings.toolProvider}'. ` +\n `Registered: ${toolProviders.map((p) => p.id).join(', ')}.`\n );\n }\n const provider = def.createProvider({\n auth: opts.vertex.auth,\n projectId: opts.vertex.projectId,\n defaultLocation: opts.vertex.defaultLocation,\n modelIds: opts.vertex.modelIds,\n location: location ?? settings.gcpLocation\n });\n const systemBlocks = await tools.buildSystemBlocks(ctx);\n const input: AgentInput<S> = {\n question,\n ctx,\n tools: tools.tools as Record<string, ToolDefinition<unknown, S>>,\n systemBlocks,\n provider,\n maxToolTurns,\n maxOutputTokens\n };\n return runAgentLoop(input);\n };\n\n // The non-streaming routes only see the common subset of hooks; the\n // SSE route gets the full superset including session-lifecycle.\n const sharedHooks = opts.hooks\n ? {\n onRequest: opts.hooks.onRequest,\n onAuthenticated: opts.hooks.onAuthenticated\n }\n : undefined;\n\n const agentCustom = createAgentCustomRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n scope: opts.scope,\n tools,\n vertex: opts.vertex,\n logger: opts.logger,\n resolveNarratorId: opts.resolveNarratorId,\n hooks: opts.hooks\n });\n\n // The Vercel AI SDK chat consumes the same wrapped `tools` (so the role\n // prompt applies on both transports) and the same hooks bag. Lifecycle\n // semantics are identical — `AgentVercelHooks` is an alias for\n // `AgentCustomHooks`.\n const agentVercel = createAgentVercelRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n scope: opts.scope,\n tools,\n vertex: opts.vertex,\n logger: opts.logger,\n hooks: opts.hooks\n });\n\n const chatSessions = createChatSessionsRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n logger: opts.logger,\n hooks: sharedHooks\n });\n\n const adminSettings = createAdminSettingsRoutes<S>({\n persistence: opts.persistence,\n auth: opts.auth,\n toolProviders,\n chatInterfaces,\n logger: opts.logger,\n hooks: sharedHooks\n });\n\n return {\n runAgent: runAgentBound,\n routes: { agentCustom, agentVercel, chatSessions, adminSettings },\n registries: { toolProviders, chatInterfaces }\n };\n}\n"]}