@kubuild/ai 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-T72YWBJS.js → chunk-K7CBTQCY.js} +30 -1
- package/dist/chunk-K7CBTQCY.js.map +1 -0
- package/dist/client/ai-client.d.ts +8 -1
- package/dist/client/ai-client.d.ts.map +1 -1
- package/dist/client/index.cjs +29 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/react/index.cjs +60 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +32 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/use-ai-generator.d.ts +2 -1
- package/dist/react/use-ai-generator.d.ts.map +1 -1
- package/dist/server/engine.d.ts +5 -1
- package/dist/server/engine.d.ts.map +1 -1
- package/dist/server/handler.d.ts +8 -1
- package/dist/server/handler.d.ts.map +1 -1
- package/dist/server/index.cjs +152 -41
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +152 -41
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +32 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-T72YWBJS.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/index.ts","../../src/server/engine.ts","../../src/core/document-outline.ts","../../src/core/prompt-compiler.ts","../../src/core/messages.ts","../../src/core/normalizer.ts","../../src/server/tools/helpers.ts","../../src/server/tools/read-tools.ts","../../src/server/tools/write-tools.ts","../../src/server/tools/index.ts","../../src/server/agent.ts","../../src/server/handler.ts","../../src/server/adapters/stream-utils.ts","../../src/server/adapters/gemini.ts","../../src/server/adapters/openai.ts","../../src/server/adapters/anthropic.ts","../../src/server/adapters/custom.ts"],"sourcesContent":["export * from './engine';\nexport * from './agent';\nexport * from './tools';\nexport * from './handler';\nexport * from './adapters';\n","import { PageDocument, Node, DocumentMetadataSchema, DocumentMetadata } from '@kubuild/schema';\nimport type {\n KubuildAiEngineOptions,\n AiGeneratePageRequest,\n AiGenerateSectionRequest,\n AiRefactorNodeRequest,\n AiChatRequest,\n AiChatResponse,\n AiChatMessage,\n AiGenerateResponse,\n AiCompiledComponentSpec,\n AiStreamEvent,\n} from '../types';\nimport {\n compileComponentCatalog,\n buildSystemPrompt,\n buildJsonSchemaForMode,\n} from '../core/prompt-compiler';\nimport { getMessageText } from '../core/messages';\nimport {\n extractJsonFromResponse,\n normalizeAndValidatePageDocument,\n normalizeAndValidateSectionNode,\n normalizeAndValidateRefactoredNode,\n} from '../core/normalizer';\n\ninterface PlannedSection {\n type: string;\n title: string;\n prompt: string;\n}\n\ninterface PagePlan {\n title?: string;\n description?: string;\n pageStyles?: Node['styles'];\n sections?: PlannedSection[];\n} \n\nexport class KubuildAiEngine {\n private options: KubuildAiEngineOptions;\n private catalog: AiCompiledComponentSpec[];\n\n constructor(options: KubuildAiEngineOptions) {\n if (!options.adapter) {\n throw new Error('KubuildAiEngine requires an adapter instance');\n }\n this.options = options;\n this.catalog = compileComponentCatalog(options.registry);\n }\n\n get adapterName(): string {\n return this.options.adapter.name;\n }\n\n refreshCatalog(): void {\n this.catalog = compileComponentCatalog(this.options.registry);\n }\n\n private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: unknown): void {\n if (this.options.logger) {\n this.options.logger(level, message, meta);\n } else if (this.options.debug) {\n const ts = new Date().toISOString();\n console.log(`[KUBUILD-AI ${level.toUpperCase()}] [${ts}] ${message}`, meta !== undefined ? meta : '');\n }\n }\n\n async generatePage(\n request: AiGeneratePageRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<PageDocument>> {\n let rawText = '';\n try {\n this.log('info', `Generating full page for prompt: \"${request.prompt}\"`);\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'full-page',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n let userPrompt = `User Request: ${request.prompt}`;\n if (request.tone) userPrompt += `\\nTone: ${request.tone}`;\n if (request.locale) userPrompt += `\\nLanguage/Locale: ${request.locale}`;\n\n const jsonSchema = buildJsonSchemaForMode('full-page');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n this.log('debug', 'Raw model response (generatePage)', result.text);\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const document = normalizeAndValidatePageDocument(\n rawJson,\n this.options.securityLimits,\n );\n\n // Merge user requested metadata if given\n if (request.metadata) {\n document.metadata = DocumentMetadataSchema.parse({\n ...document.metadata,\n ...request.metadata,\n });\n }\n\n this.log(\n 'info',\n `Full page successfully generated: \"${document.metadata?.title || 'Untitled'}\" (${document.document.children?.length || 0} sections)`,\n );\n\n return {\n success: true,\n data: document,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Generation failed: ${message}`);\n return {\n success: false,\n error: {\n code: 'GENERATION_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n async generateSection(\n request: AiGenerateSectionRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<Node>> {\n let rawText = '';\n try {\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'section',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n let userPrompt = `Generate a single section node for: ${request.prompt}`;\n if (request.targetSectionType) {\n userPrompt += `\\nTarget Section Purpose: ${request.targetSectionType}`;\n }\n if (request.parentContext) {\n userPrompt += `\\nSurrounding Page Context: ${request.parentContext}`;\n }\n\n const jsonSchema = buildJsonSchemaForMode('section');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n this.log('debug', 'Raw model response (generateSection)', result.text);\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const sectionNode = normalizeAndValidateSectionNode(\n rawJson,\n this.options.securityLimits,\n );\n\n return {\n success: true,\n data: sectionNode,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n error: {\n code: 'SECTION_GENERATION_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n async refactorNode(\n request: AiRefactorNodeRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<Node>> {\n let rawText = '';\n try {\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'refactor',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n const userPrompt = `Instruction: ${request.instruction}\\n\\nCurrent Node:\\n${JSON.stringify(request.node, null, 2)}`;\n const jsonSchema = buildJsonSchemaForMode('refactor');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const updatedNode = normalizeAndValidateRefactoredNode(\n rawJson,\n request.node,\n this.options.securityLimits,\n );\n\n return {\n success: true,\n data: updatedNode,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n error: {\n code: 'REFACTOR_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n /**\n * Progressive Section Streaming Generator.\n * Emits structured SSE events: status -> metadata -> section (one by one) -> complete.\n */\n async *streamPage(\n request: AiGeneratePageRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n try {\n this.log('info', `[SSE] Starting streamPage for prompt: \"${request.prompt}\"`);\n\n yield {\n type: 'status',\n message: 'Analyzing requirements and planning page sections...',\n };\n\n // 1. Plan page sections\n const planSystemPrompt = `\nYou are a web architect for the KUBUILD page builder.\nGiven the user's prompt, plan the website structure. Output pure JSON (no markdown fences, no explanatory text):\n{\n \"title\": \"<Page Title>\",\n \"description\": \"<Page Description>\",\n \"pageStyles\": {\n \"base\": {\n \"backgroundColor\": \"#ffffff\",\n \"fontFamily\": \"Inter, system-ui, sans-serif\",\n \"color\": \"#111827\",\n \"minHeight\": \"100vh\"\n }\n },\n \"sections\": [\n {\n \"type\": \"<hero|features|pricing|testimonials|cta|contact|footer>\",\n \"title\": \"<Brief title>\",\n \"prompt\": \"<Detailed prompt for generating this specific section with components, layout, and content>\"\n }\n ]\n}\nPlan 3 cohesive, essential sections (e.g., hero, features, and cta) that fulfill the request.\n`;\n\n let planUserPrompt = `User Request: ${request.prompt}`;\n if (request.stylePreference) {\n planUserPrompt += `\\nStyle Preference: ${request.stylePreference}`;\n }\n if (request.tone) planUserPrompt += `\\nTone: ${request.tone}`;\n if (request.locale) planUserPrompt += `\\nLocale: ${request.locale}`;\n\n this.log('info', '[SSE] Generating website layout plan...');\n const planResult = await this.options.adapter.generate({\n systemPrompt: planSystemPrompt,\n userPrompt: planUserPrompt,\n signal: context?.signal,\n });\n\n this.log('debug', '[SSE] Raw plan response from model', planResult.text);\n\n let plan: PagePlan;\n try {\n plan = extractJsonFromResponse(planResult.text) as PagePlan;\n this.log('debug', '[SSE] Parsed plan successfully', plan);\n } catch (parseErr) {\n this.log('warn', '[SSE] Failed to parse plan JSON, using fallback plan', parseErr);\n // Fallback default plan if JSON parse failed\n plan = {\n title: 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n sections: [\n { type: 'hero', title: 'Hero Banner', prompt: `Hero section for: ${request.prompt}` },\n { type: 'features', title: 'Key Features', prompt: `Features grid for: ${request.prompt}` },\n { type: 'cta', title: 'Call To Action', prompt: `Call to action section for: ${request.prompt}` },\n ],\n };\n }\n\n const sectionsToGenerate = Array.isArray(plan.sections) && plan.sections.length > 0\n ? plan.sections\n : [\n { type: 'hero', title: 'Hero Section', prompt: `Hero banner for: ${request.prompt}` },\n { type: 'features', title: 'Features', prompt: `Features grid for: ${request.prompt}` },\n { type: 'cta', title: 'Call To Action', prompt: `CTA section for: ${request.prompt}` },\n ];\n\n const metadata: DocumentMetadata = DocumentMetadataSchema.parse({\n title: plan.title || 'AI Generated Page',\n description: plan.description || 'Generated by KUBUILD AI',\n author: 'KUBUILD AI',\n tags: ['ai-generated', 'progressive-stream'],\n category: 'landing',\n version: '1.0.0',\n ...(request.metadata || {}),\n });\n\n const rootPageNode: Node = {\n id: 'root-page',\n type: 'page',\n styles: plan.pageStyles || {\n base: {\n backgroundColor: '#ffffff',\n fontFamily: 'Inter, system-ui, sans-serif',\n color: '#111827',\n minHeight: '100vh',\n },\n },\n children: [],\n };\n\n // 2. Emit initial metadata so canvas can render initial empty page immediately!\n this.log('info', `[SSE] Emitting metadata: \"${metadata.title}\"`);\n yield {\n type: 'metadata',\n metadata,\n rootPageNode,\n };\n\n this.log(\n 'info',\n `[SSE] Plan ready with ${sectionsToGenerate.length} sections: ${sectionsToGenerate.map((s) => s.title).join(', ')}`,\n );\n yield {\n type: 'status',\n message: `Plan ready with ${sectionsToGenerate.length} sections: ${sectionsToGenerate.map((s) => s.title).join(', ')}`,\n };\n\n // 3. Sequentially generate each section and stream it!\n const completedSections: Node[] = [];\n const total = sectionsToGenerate.length;\n\n for (let i = 0; i < total; i++) {\n if (context?.signal?.aborted) {\n this.log('warn', '[SSE] Streaming aborted by client signal');\n throw new Error('Streaming aborted by client');\n }\n\n const plannedSec = sectionsToGenerate[i];\n this.log(\n 'info',\n `[SSE] Generating section ${i + 1}/${total} [${plannedSec.type}]: \"${plannedSec.title}\"`,\n );\n yield {\n type: 'status',\n message: `Generating section ${i + 1}/${total} (${plannedSec.title})...`,\n };\n\n const secRes = await this.generateSection(\n {\n prompt: plannedSec.prompt,\n stylePreference: request.stylePreference,\n targetSectionType: plannedSec.type,\n parentContext: `Website: ${plan.title}. Previous sections: ${sectionsToGenerate.slice(0, i).map((s) => s.title).join(', ')}`,\n },\n { signal: context?.signal },\n );\n\n if (secRes.success && secRes.data) {\n this.log(\n 'info',\n `[SSE] Section ${i + 1}/${total} generated successfully: [${secRes.data.id || secRes.data.type}]`,\n );\n completedSections.push(secRes.data);\n yield {\n type: 'section',\n index: i,\n total,\n section: secRes.data,\n };\n } else {\n this.log('error', `[SSE] Section ${i + 1}/${total} failed`, secRes.error?.message);\n }\n }\n\n if (completedSections.length === 0) {\n this.log('error', '[SSE] All sections failed to generate.');\n yield {\n type: 'error',\n error: {\n code: 'STREAM_GENERATION_FAILED',\n message: 'All sections failed to generate. Please check server logs or retry.',\n },\n };\n return;\n }\n\n // 4. Assemble final document and emit complete event\n const finalDocument: PageDocument = {\n schema: 'stora.page',\n version: '1.0.0',\n metadata,\n document: {\n ...rootPageNode,\n children: completedSections,\n } as PageDocument['document'],\n };\n\n this.log(\n 'info',\n `[SSE] All ${completedSections.length} sections generated. Emitting complete event.`,\n );\n yield {\n type: 'complete',\n document: finalDocument,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[SSE] Streaming failed: ${message}`);\n yield {\n type: 'error',\n error: {\n code: 'STREAM_ERROR',\n message,\n },\n };\n }\n }\n\n /**\n * Builds the system/user prompt pair shared by `chat()` and `chatStream()` — the exact\n * same document/selection grounding is used regardless of whether the response is\n * streamed token-by-token or returned as a single request/response (STORA-515).\n */\n private buildChatPrompt(request: AiChatRequest): { systemPrompt: string; userPrompt: string } {\n let systemPrompt = `You are the KUBUILD AI Assistant — an expert web designer, developer, and page architecture consultant.\nYour role is to assist users with creating, designing, refining, and understanding web pages built with the KUBUILD builder.\nAnswer questions directly, concisely, and helpfully using friendly professional tone and markdown formatting.\n\n### Available KUBUILD Components:\n${this.catalog.map((c) => `- **${c.type}** (${c.category}): ${c.label}${c.description ? ` — ${c.description}` : ''}`).join('\\n')}\n`;\n\n if (this.options.systemPromptPrefix) {\n systemPrompt = `${this.options.systemPromptPrefix}\\n\\n${systemPrompt}`;\n }\n\n if (request.systemPrompt) {\n systemPrompt += `\\nAdditional Context:\\n${request.systemPrompt}`;\n }\n\n if (request.currentDocument) {\n const doc = request.currentDocument;\n const sections = doc.document?.children || [];\n const sectionSummary = sections\n .map((s, idx) => `Section ${idx + 1}: id=\"${s.id}\", type=\"${s.type}\", title=\"${(s.props?.title as string) || 'untitled'}\", childrenCount=${s.children?.length || 0}`)\n .join('\\n');\n\n systemPrompt += `\\n### Current Page in Builder Canvas:\n- Title: ${doc.metadata?.title || 'Untitled Page'}\n- Description: ${doc.metadata?.description || 'N/A'}\n- Total Sections: ${sections.length}\n- Sections Summary:\n${sectionSummary || '(Canvas is currently empty)'}\n`;\n }\n\n if (request.selectedNodeId) {\n systemPrompt += `\\nCurrently Selected Component Node ID: \"${request.selectedNodeId}\"`;\n }\n\n // Extract last user message\n const lastUserMsg = [...request.messages].reverse().find((m) => m.role === 'user');\n const userPrompt = lastUserMsg ? getMessageText(lastUserMsg) || 'Hello' : 'Hello';\n\n return { systemPrompt, userPrompt };\n }\n\n /**\n * Conversational Assistant / Q&A.\n * Can discuss web design, explain KUBUILD components, review current page,\n * suggest improvements, or recommend copywriting.\n *\n * Single request/response — unchanged since before STORA-515. See `chatStream()` for\n * the token-level streaming variant.\n */\n async chat(\n request: AiChatRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<AiChatResponse>> {\n let rawText = '';\n try {\n if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {\n return {\n success: false,\n error: {\n code: 'INVALID_CHAT_REQUEST',\n message: '\"messages\" array is required and must not be empty',\n },\n };\n }\n\n this.log('info', `Processing chat turn with ${request.messages.length} messages`);\n\n const { systemPrompt, userPrompt } = this.buildChatPrompt(request);\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n\n rawText = result.text.trim();\n\n const assistantMessage: AiChatMessage = {\n role: 'assistant',\n content: rawText,\n timestamp: Date.now(),\n };\n\n return {\n success: true,\n data: {\n message: assistantMessage,\n },\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Chat failed: ${message}`);\n return {\n success: false,\n error: {\n code: 'CHAT_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n /**\n * Token-level streaming variant of `chat()` (STORA-515). Emits `chat-chunk` events as\n * partial text arrives, then a terminal `chat-complete` event with the fully assembled\n * assistant message — the same `AsyncIterable<AiStreamEvent>` mechanism `streamPage`\n * already uses, so it can be piped over SSE by `createAiHandler`/consumed by\n * `KubuildAiClient` with no separate transport.\n *\n * When the configured adapter does not implement `generateStream` (e.g. the generic\n * custom/HTTP adapter), this falls back to a single non-streaming `generate()` call and\n * emits the entire response as one `chat-chunk`, so callers never see an error just\n * because the underlying provider can't stream — only a less granular update cadence.\n */\n async *chatStream(\n request: AiChatRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n try {\n if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {\n yield {\n type: 'error',\n error: {\n code: 'INVALID_CHAT_REQUEST',\n message: '\"messages\" array is required and must not be empty',\n },\n };\n return;\n }\n\n this.log(\n 'info',\n `[SSE] Starting chatStream with ${request.messages.length} messages (adapter: ${this.options.adapter.name})`,\n );\n\n const { systemPrompt, userPrompt } = this.buildChatPrompt(request);\n\n let accumulated = '';\n let usage: AiGenerateResponse<AiChatResponse>['usage'];\n\n if (typeof this.options.adapter.generateStream === 'function') {\n const generator = this.options.adapter.generateStream({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) {\n usage = value?.usage;\n break;\n }\n accumulated += value;\n yield { type: 'chat-chunk', delta: value, content: accumulated };\n }\n } else {\n this.log(\n 'debug',\n `Adapter \"${this.options.adapter.name}\" has no generateStream; falling back to non-streaming chat`,\n );\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n accumulated = result.text;\n usage = result.usage;\n yield { type: 'chat-chunk', delta: accumulated, content: accumulated };\n }\n\n const assistantMessage: AiChatMessage = {\n role: 'assistant',\n content: accumulated.trim(),\n timestamp: Date.now(),\n };\n\n this.log('info', '[SSE] Chat stream completed', usage);\n yield { type: 'chat-complete', message: assistantMessage };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[SSE] Chat streaming failed: ${message}`);\n yield {\n type: 'error',\n error: {\n code: 'CHAT_STREAM_ERROR',\n message,\n },\n };\n }\n }\n}\n","import type { Node, PageDocument } from '@kubuild/schema';\n\n/**\n * Props that carry user-visible text, ordered by how well they identify a node. Used to\n * label outline rows so the model can say \"the CTA button\" instead of guessing from ids.\n * Matches the prop names the component definitions in `@kubuild/components` actually use\n * (`label` on button/checkbox/file-upload, `text`/`content` on text nodes, `title` on\n * section-ish components, `src`/`alt` on media).\n */\nconst LABEL_PROPS = ['text', 'label', 'title', 'heading', 'content', 'placeholder', 'alt', 'src'];\n\nconst DEFAULT_LABEL_MAX = 60;\n\n/** Trims a value to a single short line — outlines must stay cheap in tokens. */\nfunction truncate(value: string, max = DEFAULT_LABEL_MAX): string {\n const oneLine = value.replace(/\\s+/g, ' ').trim();\n return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine;\n}\n\n/**\n * Best-effort human label for a node, derived from its text-carrying props. Returns an\n * empty string when the node has none (layout containers, mostly).\n */\nexport function getNodeLabel(node: Node, max = DEFAULT_LABEL_MAX): string {\n const props = node.props ?? {};\n for (const key of LABEL_PROPS) {\n const value = props[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(value, max);\n }\n }\n return '';\n}\n\nexport interface DocumentOutlineOptions {\n /** How deep to walk before collapsing into a `(+N nested)` marker. Default: 3. */\n maxDepth?: number;\n /**\n * When set, the branch containing this node is always expanded in full regardless of\n * `maxDepth`, and the node itself is marked with `← SELECTED`. This is what makes\n * \"user selected a component on the canvas\" legible to the model.\n */\n focusNodeId?: string;\n /** Hard ceiling on emitted rows, so a huge page can't blow up the prompt. Default: 200. */\n maxNodes?: number;\n}\n\nfunction isOnPathTo(node: Node, targetId: string): boolean {\n if (node.id === targetId) return true;\n return (node.children ?? []).some((child) => isOnPathTo(child, targetId));\n}\n\n/**\n * Renders a compact, indented outline of a node tree (STORA-530).\n *\n * This is the agent's *default* view of the document: one line per node with id, type,\n * label and child count — never full props/styles. Detail is fetched on demand via the\n * `read_node` tool, which keeps per-step prompt cost roughly constant no matter how big\n * the page is. `engine.buildChatPrompt`'s depth-1 section summary can't do this: nested\n * nodes were invisible to the model, so it could never target them.\n */\nexport function summarizeNodeTree(root: Node, options: DocumentOutlineOptions = {}): string {\n const { maxDepth = 3, focusNodeId, maxNodes = 200 } = options;\n const lines: string[] = [];\n let emitted = 0;\n let truncated = false;\n\n const walk = (node: Node, depth: number): void => {\n if (emitted >= maxNodes) {\n truncated = true;\n return;\n }\n\n const indent = ' '.repeat(depth);\n const label = getNodeLabel(node);\n const children = node.children ?? [];\n const parts = [`${indent}- #${node.id} (${node.type})`];\n if (label) parts.push(`\"${label}\"`);\n if (children.length > 0) parts.push(`[${children.length} children]`);\n if (focusNodeId && node.id === focusNodeId) parts.push('← SELECTED');\n lines.push(parts.join(' '));\n emitted++;\n\n if (children.length === 0) return;\n\n // The focused branch stays fully expanded even past maxDepth — the model needs to see\n // what it's being asked to edit, and its siblings, to make a surgical change.\n const onFocusPath = Boolean(focusNodeId) && isOnPathTo(node, focusNodeId!);\n if (depth + 1 > maxDepth && !onFocusPath) {\n lines.push(`${indent} (+${countDescendants(node)} nested nodes — use read_node to expand)`);\n return;\n }\n\n for (const child of children) {\n walk(child, depth + 1);\n }\n };\n\n walk(root, 0);\n\n if (truncated) {\n lines.push(` (outline truncated at ${maxNodes} nodes — use find_nodes to locate specifics)`);\n }\n\n return lines.join('\\n');\n}\n\n/** Total number of descendants below a node (not counting the node itself). */\nexport function countDescendants(node: Node): number {\n return (node.children ?? []).reduce((total, child) => total + 1 + countDescendants(child), 0);\n}\n\n/** Outline of a whole `PageDocument`, prefixed with its metadata. */\nexport function summarizeDocument(\n document: PageDocument,\n options: DocumentOutlineOptions = {},\n): string {\n const header = [\n `Title: ${document.metadata?.title || 'Untitled Page'}`,\n `Description: ${document.metadata?.description || 'N/A'}`,\n ].join('\\n');\n return `${header}\\n\\nPage outline:\\n${summarizeNodeTree(document.document, options)}`;\n}\n\nexport interface SelectionContext {\n node: Node;\n /** Root-first chain of ancestors, excluding the node itself. */\n ancestors: Node[];\n /** The node's siblings, in document order, including the node itself. */\n siblings: Node[];\n index: number;\n parentId: string | null;\n}\n\n/**\n * Resolves everything the agent needs to know about the canvas selection (STORA-530).\n *\n * Sending only `selectedNodeId` — what `engine.buildChatPrompt` does today — tells the\n * model an id but not what the node *is*, what it lives inside, or what sits next to it,\n * so it can't judge whether an instruction like \"make this wider\" belongs on the node or\n * on its parent container. Returns `null` when the id isn't in the tree.\n */\nexport function buildSelectionContext(root: Node, nodeId: string): SelectionContext | null {\n const ancestors: Node[] = [];\n\n const walk = (node: Node, parent: Node | null, index: number): SelectionContext | null => {\n if (node.id === nodeId) {\n return {\n node,\n ancestors: [...ancestors],\n siblings: parent ? (parent.children ?? []) : [node],\n index,\n parentId: parent?.id ?? null,\n };\n }\n ancestors.push(node);\n const children = node.children ?? [];\n for (let i = 0; i < children.length; i++) {\n const found = walk(children[i], node, i);\n if (found) return found;\n }\n ancestors.pop();\n return null;\n };\n\n return walk(root, null, 0);\n}\n\n/**\n * Depth-limits a node before it is serialized into a prompt. A selected section can carry\n * hundreds of descendants; dumping all of them would defeat the point of the outline.\n * Children below `maxDepth` are replaced by a marker node telling the model to call\n * `read_node` if it needs them.\n */\nexport function pruneNodeForPrompt(node: Node, maxDepth = 2, depth = 0): Node {\n const children = node.children ?? [];\n if (children.length === 0) return node;\n\n if (depth >= maxDepth) {\n return {\n ...node,\n children: [\n {\n id: `${node.id}__collapsed`,\n type: '__collapsed__',\n props: {\n note: `${countDescendants(node)} nested nodes omitted — call read_node on #${node.id} with includeChildren to expand`,\n },\n },\n ],\n };\n }\n\n return {\n ...node,\n children: children.map((child) => pruneNodeForPrompt(child, maxDepth, depth + 1)),\n };\n}\n\n/** Renders a `SelectionContext` as the prompt block describing the current selection. */\nexport function formatSelectionContext(context: SelectionContext): string {\n const path = context.ancestors.map((a) => `#${a.id}(${a.type})`).join(' > ');\n const siblings = context.siblings\n .map((sibling, i) => {\n const marker = sibling.id === context.node.id ? ' ← selected' : '';\n const label = getNodeLabel(sibling);\n return ` [${i}] #${sibling.id} (${sibling.type})${label ? ` \"${label}\"` : ''}${marker}`;\n })\n .join('\\n');\n\n return [\n '### Currently Selected Component',\n `Node: #${context.node.id} (${context.node.type})`,\n `Parent: ${context.parentId ? `#${context.parentId}` : '(root)'} — position ${context.index}`,\n path ? `Path: ${path}` : '',\n 'Full node JSON:',\n '```json',\n JSON.stringify(pruneNodeForPrompt(context.node), null, 2),\n '```',\n 'Siblings:',\n siblings,\n 'When the user says \"this\", \"ini\", \"komponen ini\" or similar, they mean the selected node above.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n","import type { PageDocument } from '@kubuild/schema';\nimport type {\n AiCompiledComponentSpec,\n AiCompiledComponentProp,\n ComponentRegistryLike,\n ComponentDefinitionLike,\n AiGenerationMode,\n} from '../types';\nimport {\n buildSelectionContext,\n formatSelectionContext,\n summarizeDocument,\n} from './document-outline';\n\nexport function compileComponentCatalog(\n registry?: ComponentRegistryLike,\n): AiCompiledComponentSpec[] {\n if (!registry) return [];\n\n const definitions = registry.list();\n return definitions.map((def: ComponentDefinitionLike) => {\n const props: AiCompiledComponentProp[] = [];\n\n if (def.propFields && Array.isArray(def.propFields)) {\n for (const field of def.propFields) {\n props.push({\n name: field.name,\n type: field.type || 'string',\n defaultValue: field.defaultValue,\n options: field.options?.map((o) => o.value),\n description: field.description,\n });\n }\n }\n\n return {\n type: def.type,\n label: def.label || def.type,\n category: def.category || 'custom',\n description: def.description,\n acceptsChildren: def.acceptsChildren ?? false,\n allowedChildren: def.allowedChildren,\n disallowedParents: def.disallowedParents,\n defaultProps: def.defaultProps,\n props: props.length > 0 ? props : undefined,\n };\n });\n}\n\nexport function buildSystemPrompt(options: {\n catalog: AiCompiledComponentSpec[];\n mode: AiGenerationMode;\n prefix?: string;\n stylePreference?: string;\n}): string {\n const { catalog, mode, prefix, stylePreference } = options;\n\n const catalogSummary = catalog\n .map((c) => {\n let desc = `- **${c.type}** (${c.category}): ${c.label}`;\n if (c.description) desc += ` - ${c.description}`;\n desc += ` | acceptsChildren: ${c.acceptsChildren}`;\n if (c.allowedChildren && c.allowedChildren.length > 0) {\n desc += ` | allowedChildren: [${c.allowedChildren.join(', ')}]`;\n }\n if (c.props && c.props.length > 0) {\n const propList = c.props\n .map((p) => {\n let pStr = `${p.name} (${p.type})`;\n if (p.options) pStr += `[${p.options.map(String).join('|')}]`;\n return pStr;\n })\n .join(', ');\n desc += ` | props: { ${propList} }`;\n }\n return desc;\n })\n .join('\\n');\n\n let modeInstructions = '';\n if (mode === 'full-page') {\n modeInstructions = `\nYou must generate a complete, valid KUBUILD PageDocument JSON with this exact structure:\n{\n \"schema\": \"stora.page\",\n \"version\": \"1.0.0\",\n \"metadata\": {\n \"title\": \"<Page Title>\",\n \"description\": \"<Page Description>\",\n \"tags\": [\"<tag1>\", \"<tag2>\"],\n \"category\": \"<category>\"\n },\n \"document\": {\n \"id\": \"root-page\",\n \"type\": \"page\",\n \"styles\": {\n \"base\": {\n \"backgroundColor\": \"#ffffff\",\n \"fontFamily\": \"Inter, system-ui, sans-serif\",\n \"color\": \"#111827\",\n \"minHeight\": \"100vh\"\n }\n },\n \"children\": [\n // Sections here...\n ]\n }\n}\n`;\n } else if (mode === 'section') {\n modeInstructions = `\nYou must generate a single valid KUBUILD section Node JSON with this structure:\n{\n \"id\": \"section_<unique_suffix>\",\n \"type\": \"section\",\n \"styles\": {\n \"base\": {\n \"paddingTop\": \"64px\",\n \"paddingBottom\": \"64px\",\n \"paddingLeft\": \"24px\",\n \"paddingRight\": \"24px\"\n }\n },\n \"children\": [\n // Container and child nodes...\n ]\n}\n`;\n } else if (mode === 'refactor') {\n modeInstructions = `\nYou must refactor the provided KUBUILD Node based on the user's instructions.\nReturn ONLY the updated Node JSON while maintaining structural integrity.\n`;\n }\n\n const styleGuide = stylePreference\n ? `\\nUser Style Preference: \"${stylePreference}\". Follow this visual aesthetic closely.`\n : '\\nStyle with modern, clean, high-conversion design patterns (accessible contrast, harmonious spacing, beautiful typography, subtle shadows/borders).';\n\n return `${prefix ? prefix + '\\n\\n' : ''}You are an expert web designer and KUBUILD architecture generator.\nKUBUILD is a component-driven visual website builder. Your job is to output pure, valid JSON (and NOTHING ELSE) matching the KUBUILD schema and the registered component definitions.\n\n### RULES & CONSTRAINTS:\n1. Output MUST be valid JSON only. No markdown fences, no explanatory text, no HTML tags outside html-embed.\n2. Only use component types listed in the Component Catalog below. Do NOT invent new component types.\n3. Obey \\`acceptsChildren\\` and \\`allowedChildren\\`:\n - Layout hierarchy: \\`page\\` -> \\`section\\` -> \\`container\\` or \\`columns\\` -> content components (\\`heading\\`, \\`paragraph\\`, \\`button\\`, \\`image\\`, \\`form\\`, etc.).\n - Leaf components (e.g. \\`button\\`, \\`input\\`, \\`heading\\`, \\`text\\`, \\`badge\\`) must have \\`acceptsChildren: false\\` and empty or omitted \\`children\\`.\n4. Every node MUST have a unique string \\`id\\` (e.g. \"hero-section\", \"hero-title\", \"cta-btn\").\n5. Responsive & Interactive State Styling:\n - Use the \\`styles\\` object with breakpoint keys: \\`base\\` (all viewports/desktop), and optionally \\`tablet\\` or \\`mobile\\`.\n - In \\`base\\`, \\`tablet\\`, and \\`mobile\\`, values MUST be CSS primitives (strings or numbers, e.g. \"backgroundColor\": \"#3b82f6\"). NEVER put nested objects or \":hover\" inside \"base\"!\n - For hover, active, or interactive pseudo-classes, use \\`styles.states\\` with pseudo-class keys (e.g. \\`\":hover\"\\`), like:\n \"styles\": {\n \"base\": { \"backgroundColor\": \"#3b82f6\", \"color\": \"#ffffff\" },\n \"states\": {\n \":hover\": { \"backgroundColor\": \"#2563eb\" }\n }\n }\n6. NEVER include dangerous scripts, \\`javascript:\\` URIs, or malicious payload attributes.\n${styleGuide}\n\n### OUTPUT SPECIFICATION:\n${modeInstructions}\n\n### REGISTERED COMPONENT CATALOG:\n${catalogSummary || '(Standard core components: page, section, container, columns, heading, paragraph, text, button, input, textarea, select, image, video, icon, badge, code-block)'}\n`;\n}\n\nexport function buildJsonSchemaForMode(mode: AiGenerationMode): Record<string, unknown> {\n const nodeSchema: Record<string, unknown> = {\n type: 'object',\n required: ['id', 'type'],\n properties: {\n id: { type: 'string' },\n type: { type: 'string' },\n props: { type: 'object' },\n styles: {\n type: 'object',\n properties: {\n base: { type: 'object' },\n tablet: { type: 'object' },\n mobile: { type: 'object' },\n states: { type: 'object' },\n },\n },\n children: {\n type: 'array',\n items: { $ref: '#' },\n },\n },\n };\n\n if (mode === 'full-page') {\n return {\n type: 'object',\n required: ['schema', 'version', 'document'],\n properties: {\n schema: { type: 'string', const: 'stora.page' },\n version: { type: 'string', const: '1.0.0' },\n metadata: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n category: { type: 'string' },\n },\n },\n document: nodeSchema,\n },\n };\n }\n\n return nodeSchema;\n}\n\n\n/**\n * Renders the component catalog as the compact reference block shared by every prompt.\n * Extracted from `buildSystemPrompt` so the agent prompt (STORA-530) reuses the exact\n * same catalog rendering instead of drifting into a second format.\n */\nexport function formatComponentCatalog(catalog: AiCompiledComponentSpec[]): string {\n return catalog\n .map((c) => {\n let desc = `- **${c.type}** (${c.category}): ${c.label}`;\n if (c.description) desc += ` - ${c.description}`;\n desc += ` | acceptsChildren: ${c.acceptsChildren}`;\n if (c.allowedChildren && c.allowedChildren.length > 0) {\n desc += ` | allowedChildren: [${c.allowedChildren.join(', ')}]`;\n }\n if (c.props && c.props.length > 0) {\n const propList = c.props\n .map((p) => {\n let pStr = `${p.name} (${p.type})`;\n if (p.options) pStr += `[${p.options.map(String).join('|')}]`;\n return pStr;\n })\n .join(', ');\n desc += ` | props: { ${propList} }`;\n }\n return desc;\n })\n .join('\\n');\n}\n\nexport interface BuildAgentSystemPromptOptions {\n catalog: AiCompiledComponentSpec[];\n document: PageDocument;\n selectedNodeId?: string;\n prefix?: string;\n stylePreference?: string;\n /** Extra host/product context appended verbatim. */\n additionalContext?: string;\n}\n\nconst AGENT_INSTRUCTIONS = `You are the KUBUILD page-editing agent. You edit an existing page by calling tools — you never output page JSON directly.\n\n### HOW YOU WORK\n1. The page outline below is your map. It shows every node's id, type and label, but not its props or styles.\n2. To see a node's actual props/styles, call read_node. To locate nodes by type or text, call find_nodes. Never guess a node id — every id you pass must come from the outline or from a tool result.\n3. Make the change with the smallest tool that expresses it, then stop and summarize what you changed, in the user's language.\n\n### SURGICAL EDIT RULE (the most important rule)\nChange only what the user asked for.\n- Changing text/label/href/src -> update_node_props on that one node.\n- Changing color/spacing/size/alignment -> update_node_styles on that one node.\n- Adding something new -> insert_component (a single element) or insert_section (a whole new section).\n- replace_node is a last resort, only when a node's children genuinely must be restructured. Never use it to change a prop or a style.\n- Never rebuild a section, and never touch nodes the user did not ask about. If an instruction is ambiguous about scope, edit the narrowest node that satisfies it and say so in your summary.\n\n### DESTRUCTIVE ACTIONS\ndelete_node and replace_node destroy user content. Only call them when the user asked unambiguously (e.g. \"hapus section harga\"). If the request is broad or vague (\"bersihkan halaman ini\", \"hapus yang tidak perlu\"), do not call them — ask the user which nodes to remove instead.\n\n### STYLING RULES\n- styles values are CSS primitives (strings/numbers). Use breakpoint ('base' | 'desktop' | 'tablet' | 'mobile') for normal styling and state (':hover', ':focus', ':active') for interactive states. Never nest a pseudo-class inside a breakpoint layer.\n- Only use component types that exist in the catalog below, and respect acceptsChildren/allowedChildren.\n- Never emit scripts, javascript: URIs, or event-handler attributes.\n\n### WHEN A TOOL FAILS\nA tool result with \"ok\": false means your input was wrong (unknown node id, invalid type, disallowed nesting). Read the error, fix your arguments, and retry — do not repeat the identical call, and do not give up silently.`;\n\n/**\n * System prompt for agent mode (STORA-530).\n *\n * Deliberately different from `buildSystemPrompt`: the agent does NOT emit document JSON.\n * It reads the page through tools and edits through tools, so the prompt's job is to\n * establish (a) the outline as the shared map, (b) the selection as the default target,\n * and (c) the surgical-edit discipline — the whole point of the feature is that asking to\n * recolor one button must not regenerate its section.\n *\n * The catalog goes before the volatile per-turn context so the stable prefix stays\n * prompt-cacheable across the steps of a run.\n */\nexport function buildAgentSystemPrompt(options: BuildAgentSystemPromptOptions): string {\n const { catalog, document, selectedNodeId, prefix, stylePreference, additionalContext } = options;\n\n const selection = selectedNodeId\n ? buildSelectionContext(document.document, selectedNodeId)\n : null;\n\n const sections: string[] = [];\n\n if (prefix) sections.push(prefix);\n\n sections.push(AGENT_INSTRUCTIONS);\n\n sections.push(\n `### REGISTERED COMPONENT CATALOG\\n${\n formatComponentCatalog(catalog) ||\n '(Standard core components: page, section, container, columns, heading, paragraph, text, button, input, textarea, select, image, video, icon, badge, code-block)'\n }`,\n );\n\n sections.push(`### CURRENT PAGE\\n${summarizeDocument(document, { focusNodeId: selectedNodeId })}`);\n\n if (selection) {\n sections.push(formatSelectionContext(selection));\n } else if (selectedNodeId) {\n sections.push(\n `### Selection\\nThe editor reported node \"${selectedNodeId}\" as selected, but it is not present in the current page. Ignore it and ask the user what to target.`,\n );\n } else {\n sections.push(\n '### Selection\\nNo component is selected on the canvas. If the user says \"this\", ask which component they mean instead of guessing.',\n );\n }\n\n if (stylePreference) {\n sections.push(\n `### Style Preference\\n\"${stylePreference}\" — follow this aesthetic for anything you create or restyle.`,\n );\n }\n\n if (additionalContext) {\n sections.push(`### Additional Context\\n${additionalContext}`);\n }\n\n return sections.join('\\n\\n');\n}\n","import type { AiChatMessage, AiContentBlock, AiToolUseBlock, AiToolResultBlock } from '../types';\n\n/**\n * Flattens a message's content to plain text (STORA-530).\n *\n * `AiChatMessage.content` became `string | AiContentBlock[]` when tool calling landed;\n * every place that previously assumed a bare string (adapter message mapping, the chat\n * prompt's \"last user message\" lookup, chat UIs) goes through this helper instead of\n * re-implementing the narrowing. Tool-use/tool-result blocks contribute nothing to the\n * text rendering — they're transported separately by the adapters.\n */\nexport function getMessageText(message: Pick<AiChatMessage, 'content'>): string {\n if (typeof message.content === 'string') return message.content;\n return message.content\n .filter((block): block is Extract<AiContentBlock, { type: 'text' }> => block.type === 'text')\n .map((block) => block.text)\n .join('\\n');\n}\n\n/** All `tool_use` blocks carried by a message, in order. Empty for plain-text messages. */\nexport function getToolUseBlocks(message: Pick<AiChatMessage, 'content'>): AiToolUseBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is AiToolUseBlock => b.type === 'tool_use');\n}\n\n/** All `tool_result` blocks carried by a message, in order. */\nexport function getToolResultBlocks(message: Pick<AiChatMessage, 'content'>): AiToolResultBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is AiToolResultBlock => b.type === 'tool_result');\n}\n\n/** True when the message carries any non-text block — i.e. adapters must map it structurally. */\nexport function hasStructuredContent(message: Pick<AiChatMessage, 'content'>): boolean {\n return typeof message.content !== 'string' && message.content.some((b) => b.type !== 'text');\n}\n","import {\n PageDocument,\n PageDocumentSchema,\n DocumentMetadata,\n DocumentMetadataSchema,\n Node,\n NodeSchema,\n CURRENT_SCHEMA_VERSION,\n SCHEMA_NAME,\n} from '@kubuild/schema';\nimport {\n validateDocument,\n validateDocumentSecurity,\n DocumentSecurityLimits,\n} from '@kubuild/core';\n\nexport function extractJsonFromResponse(raw: string): unknown {\n let cleaned = raw.trim();\n // Strip Markdown code blocks if present (```json ... ``` or ``` ...)\n if (cleaned.startsWith('```')) {\n const firstNewline = cleaned.indexOf('\\n');\n if (firstNewline !== -1) {\n cleaned = cleaned.slice(firstNewline + 1);\n }\n if (cleaned.endsWith('```')) {\n cleaned = cleaned.slice(0, cleaned.length - 3).trim();\n }\n }\n\n // Find the outermost JSON object bounds if there is extraneous text\n const firstBrace = cleaned.indexOf('{');\n const lastBrace = cleaned.lastIndexOf('}');\n if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {\n cleaned = cleaned.slice(firstBrace, lastBrace + 1);\n }\n\n try {\n return JSON.parse(cleaned);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse AI response as JSON: ${msg}. Response was: ${raw.slice(0, 200)}...`);\n }\n}\n\nexport function normalizeStyles(rawStyles: unknown): Node['styles'] {\n if (!rawStyles || typeof rawStyles !== 'object' || Array.isArray(rawStyles)) {\n return undefined;\n }\n\n const raw = rawStyles as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n const states: Record<string, Record<string, unknown>> = {};\n\n // Existing states\n if (raw.states && typeof raw.states === 'object' && !Array.isArray(raw.states)) {\n for (const [stateKey, stateVal] of Object.entries(raw.states as Record<string, unknown>)) {\n if (stateVal && typeof stateVal === 'object' && !Array.isArray(stateVal)) {\n states[stateKey] = { ...(stateVal as Record<string, unknown>) };\n }\n }\n }\n\n const knownBreakpoints = ['base', 'desktop', 'tablet', 'mobile'];\n const hasBreakpoint = Object.keys(raw).some((k) => knownBreakpoints.includes(k));\n\n if (!hasBreakpoint) {\n // If AI output flat CSS properties without 'base' wrapper\n const baseStyles: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (key === 'states') continue;\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n } else if (typeof value !== 'object' || value === null) {\n baseStyles[key] = value;\n }\n }\n if (Object.keys(baseStyles).length > 0) {\n result.base = baseStyles;\n }\n } else {\n for (const bp of knownBreakpoints) {\n const bpVal = raw[bp];\n if (bpVal && typeof bpVal === 'object' && !Array.isArray(bpVal)) {\n const cleanBp: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(bpVal as Record<string, unknown>)) {\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n } else if (typeof value !== 'object' || value === null) {\n cleanBp[key] = value;\n }\n }\n if (Object.keys(cleanBp).length > 0) {\n result[bp] = cleanBp;\n }\n }\n }\n\n // Also extract any pseudo-classes at top level\n for (const [key, value] of Object.entries(raw)) {\n if (knownBreakpoints.includes(key) || key === 'states') continue;\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n }\n }\n }\n\n // Clean and sanitize states: each state can only have primitives\n const cleanStates: Record<string, Record<string, unknown>> = {};\n for (const [stateKey, stateDef] of Object.entries(states)) {\n const cleanDef: Record<string, unknown> = {};\n for (const [propKey, propVal] of Object.entries(stateDef)) {\n if (typeof propVal !== 'object' || propVal === null) {\n cleanDef[propKey] = propVal;\n }\n }\n if (Object.keys(cleanDef).length > 0) {\n cleanStates[stateKey] = cleanDef;\n }\n }\n\n if (Object.keys(cleanStates).length > 0) {\n result.states = cleanStates;\n }\n\n return Object.keys(result).length > 0 ? (result as Node['styles']) : undefined;\n}\n\nexport function normalizeNodeTree(\n node: unknown,\n usedIds: Set<string> = new Set(),\n depth = 0,\n): Node {\n if (!node || typeof node !== 'object') {\n throw new Error(`Invalid node at depth ${depth}: must be an object`);\n }\n\n const raw = node as Record<string, unknown>;\n const type = typeof raw.type === 'string' && raw.type.trim() ? raw.type.trim() : 'container';\n\n // Ensure deterministic, unique ID\n let id = typeof raw.id === 'string' && raw.id.trim() ? raw.id.trim() : '';\n if (!id || usedIds.has(id)) {\n let counter = 1;\n let candidate = `${type}-${counter}`;\n while (usedIds.has(candidate)) {\n counter++;\n candidate = `${type}-${counter}`;\n }\n id = candidate;\n }\n usedIds.add(id);\n\n // Normalize props\n const props =\n raw.props && typeof raw.props === 'object' && !Array.isArray(raw.props)\n ? { ...(raw.props as Record<string, unknown>) }\n : {};\n\n // Fix common LLM prop quirks:\n // e.g. heading level passed as string \"1\" instead of number 1\n if (type === 'heading' && typeof props.level === 'string') {\n const parsedLevel = parseInt(props.level, 10);\n if (!isNaN(parsedLevel) && parsedLevel >= 1 && parsedLevel <= 6) {\n props.level = parsedLevel;\n }\n }\n\n // Normalize styles\n const styles = normalizeStyles(raw.styles);\n\n // Normalize children recursively\n let children: Node[] | undefined = undefined;\n if (Array.isArray(raw.children)) {\n children = raw.children\n .filter((c) => c && typeof c === 'object')\n .map((c) => normalizeNodeTree(c, usedIds, depth + 1));\n }\n\n return {\n id,\n type,\n props: Object.keys(props).length > 0 ? props : undefined,\n styles,\n children,\n };\n}\n\nexport function normalizeAndValidatePageDocument(\n rawJson: unknown,\n securityLimits?: DocumentSecurityLimits,\n): PageDocument {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const obj = rawJson as Record<string, unknown>;\n\n // Case 1: AI returned directly a page node instead of PageDocument\n let docObject: Record<string, unknown>;\n if (obj.type === 'page' && !obj.document) {\n docObject = {\n schema: SCHEMA_NAME,\n version: CURRENT_SCHEMA_VERSION,\n metadata: {\n title: (typeof obj.props === 'object' && obj.props !== null && (obj.props as Record<string, unknown>).title) || 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n },\n document: obj,\n };\n } else {\n docObject = {\n schema: SCHEMA_NAME,\n version: typeof obj.version === 'string' ? obj.version : CURRENT_SCHEMA_VERSION,\n metadata: typeof obj.metadata === 'object' && obj.metadata !== null\n ? obj.metadata\n : { title: 'AI Generated Page', description: 'Generated by KUBUILD AI' },\n document: obj.document || obj,\n };\n }\n\n // Normalize the node tree and ensure IDs\n const usedIds = new Set<string>();\n const normalizedRoot = normalizeNodeTree(docObject.document, usedIds);\n\n if (normalizedRoot.type !== 'page') {\n normalizedRoot.type = 'page';\n }\n\n const parsedMetadata = DocumentMetadataSchema.parse({\n title: 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n author: 'KUBUILD AI',\n tags: ['ai-generated'],\n category: 'general',\n version: '1.0.0',\n ...(typeof docObject.metadata === 'object' && docObject.metadata !== null\n ? (docObject.metadata as Record<string, unknown>)\n : {}),\n });\n\n const finalDocument: PageDocument = {\n schema: SCHEMA_NAME,\n version: CURRENT_SCHEMA_VERSION,\n metadata: parsedMetadata,\n document: normalizedRoot as PageDocument['document'],\n };\n\n // 1. Zod Schema parse\n const parsed = PageDocumentSchema.safeParse(finalDocument);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Document schema validation failed: ${issues}`);\n }\n\n // 2. Core document and security validation\n const validationResult = validateDocument(finalDocument, { securityLimits });\n if (!validationResult.valid) {\n const errorMsgs = validationResult.errors.map((e) => `${e.code}: ${e.message} (${e.path})`).join('; ');\n throw new Error(`Document validation failed: ${errorMsgs}`);\n }\n\n return parsed.data;\n}\n\nexport function normalizeAndValidateSectionNode(\n rawJson: unknown,\n securityLimits?: DocumentSecurityLimits,\n): Node {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const usedIds = new Set<string>();\n const normalized = normalizeNodeTree(rawJson, usedIds);\n\n if (normalized.type !== 'section') {\n // If AI wrapped it or returned another root, enforce section\n normalized.type = 'section';\n }\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Section node schema validation failed: ${issues}`);\n }\n\n // Security check\n const secCheck = validateDocumentSecurity({ document: normalized }, securityLimits);\n if (!secCheck.safe) {\n const issues = secCheck.errors.map((e) => `${e.code}: ${e.message}`).join('; ');\n throw new Error(`Section security check failed: ${issues}`);\n }\n\n return parsed.data;\n}\n\nexport function normalizeAndValidateRefactoredNode(\n rawJson: unknown,\n originalNode: Node,\n securityLimits?: DocumentSecurityLimits,\n): Node {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const usedIds = new Set<string>();\n const normalized = normalizeNodeTree(rawJson, usedIds);\n\n // Preserve original ID and type if AI changed them accidentally\n normalized.id = originalNode.id;\n normalized.type = originalNode.type;\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Refactored node schema validation failed: ${issues}`);\n }\n\n const secCheck = validateDocumentSecurity({ document: normalized }, securityLimits);\n if (!secCheck.safe) {\n const issues = secCheck.errors.map((e) => `${e.code}: ${e.message}`).join('; ');\n throw new Error(`Refactored node security check failed: ${issues}`);\n }\n\n return parsed.data;\n}\n","import type { Node, PageDocument } from '@kubuild/schema';\nimport { NodeSchema } from '@kubuild/schema';\nimport {\n collectNodeIdSet,\n findNodeById,\n validateDocumentSecurity,\n type DocumentSecurityLimits,\n} from '@kubuild/core';\nimport type { AiCompiledComponentSpec } from '../../types';\nimport { normalizeNodeTree } from '../../core/normalizer';\nimport { getNodeLabel } from '../../core/document-outline';\nimport type { ToolExecutionResult } from './types';\n\n/**\n * A failed tool call (STORA-530).\n *\n * Failures are deliberately *not* thrown: they're returned to the model as a normal\n * `tool_result` with `ok: false` so it can read the reason, fix its arguments and retry.\n * That self-correction loop is the main reason agent mode beats one-shot JSON generation —\n * a hallucinated node id becomes a retry instead of a broken document.\n */\nexport function fail(summary: string, message: string, extra?: Record<string, unknown>): ToolExecutionResult {\n return {\n ok: false,\n summary,\n content: { ok: false, error: message, ...(extra ?? {}) },\n };\n}\n\nexport function succeed(\n summary: string,\n content: Record<string, unknown>,\n rest?: Pick<ToolExecutionResult, 'op' | 'document'>,\n): ToolExecutionResult {\n return { ok: true, summary, content: { ok: true, ...content }, ...(rest ?? {}) };\n}\n\n/** Reads a required string argument, tolerating the whitespace LLMs sometimes emit. */\nexport function readString(input: Record<string, unknown>, key: string): string | null {\n const value = input[key];\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n\nexport function readPlainObject(\n input: Record<string, unknown>,\n key: string,\n): Record<string, unknown> | null {\n const value = input[key];\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nexport function readOptionalIndex(input: Record<string, unknown>, key: string): number | undefined {\n const value = input[key];\n if (typeof value === 'number' && Number.isInteger(value) && value >= 0) return value;\n return undefined;\n}\n\n/**\n * Cheap similarity used only to suggest alternatives when the model invents a node id —\n * shared prefix length plus a substring bonus. Good enough to turn \"hero-title\" into a\n * pointer at \"hero-heading\"; no need for a real edit-distance implementation here.\n */\nfunction similarity(a: string, b: string): number {\n if (a === b) return Infinity;\n let shared = 0;\n const max = Math.min(a.length, b.length);\n while (shared < max && a[shared] === b[shared]) shared++;\n return shared + (a.includes(b) || b.includes(a) ? 3 : 0);\n}\n\n/** Up to `limit` existing node ids most similar to a bad one, for the retry hint. */\nexport function suggestNodeIds(document: PageDocument, badId: string, limit = 5): string[] {\n return Array.from(collectNodeIdSet(document.document))\n .map((id) => ({ id, score: similarity(id.toLowerCase(), badId.toLowerCase()) }))\n .filter((entry) => entry.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map((entry) => entry.id);\n}\n\nexport interface ResolvedNode {\n node: Node;\n}\n\n/** Resolves a node id against the snapshot, or returns a retry-friendly failure. */\nexport function resolveNode(\n document: PageDocument,\n nodeId: string,\n toolName: string,\n): { node: Node } | { error: ToolExecutionResult } {\n const node = findNodeById(document.document, nodeId);\n if (!node) {\n return {\n error: fail(\n `${toolName}: node \"${nodeId}\" tidak ditemukan`,\n `No node with id \"${nodeId}\" exists in this page. Node ids must come from the outline or from a tool result — never invented.`,\n { suggestedNodeIds: suggestNodeIds(document, nodeId) },\n ),\n };\n }\n return { node };\n}\n\nexport function findCatalogEntry(\n catalog: AiCompiledComponentSpec[],\n type: string,\n): AiCompiledComponentSpec | undefined {\n return catalog.find((entry) => entry.type === type);\n}\n\n/**\n * Enforces the registry's nesting contract before an insert/move (STORA-530).\n *\n * The same `acceptsChildren`/`allowedChildren` rules the prompt states are checked here,\n * because a prompt rule is a suggestion while a tool check is a guarantee — and a document\n * that violates them renders wrong rather than failing loudly.\n *\n * An empty catalog (host supplied no registry) means \"unknown\", so nesting is allowed\n * rather than blocking every insert.\n */\nexport function checkNesting(\n catalog: AiCompiledComponentSpec[],\n parent: Node,\n childType: string,\n): string | null {\n if (catalog.length === 0) return null;\n\n const parentSpec = findCatalogEntry(catalog, parent.type);\n if (parentSpec && !parentSpec.acceptsChildren) {\n return `Component \"${parent.type}\" (#${parent.id}) cannot contain children. Insert into a container/section node instead.`;\n }\n if (parentSpec?.allowedChildren && parentSpec.allowedChildren.length > 0) {\n if (!parentSpec.allowedChildren.includes(childType)) {\n return `Component \"${parent.type}\" only accepts children of type [${parentSpec.allowedChildren.join(', ')}] — \"${childType}\" is not allowed.`;\n }\n }\n\n const childSpec = findCatalogEntry(catalog, childType);\n if (childSpec?.disallowedParents?.includes(parent.type)) {\n return `Component \"${childType}\" cannot be placed inside \"${parent.type}\".`;\n }\n\n return null;\n}\n\n/** Validates a component type against the catalog, returning a retry hint when unknown. */\nexport function checkComponentType(\n catalog: AiCompiledComponentSpec[],\n type: string,\n): string | null {\n if (catalog.length === 0) return null;\n if (findCatalogEntry(catalog, type)) return null;\n const known = catalog.map((entry) => entry.type);\n return `Unknown component type \"${type}\". Use list_component_types to see valid types. Known types: ${known.slice(0, 40).join(', ')}${known.length > 40 ? ', …' : ''}`;\n}\n\n/**\n * The defense-in-depth gate every write tool passes through before its op is accepted —\n * the same `validateDocumentSecurity` pass `normalizeAndValidate*` already applies to\n * generated documents, now applied per mutation so a single bad tool call can't smuggle\n * a `javascript:` href or a prototype-pollution key into the snapshot.\n */\nexport function checkDocumentSecurity(\n document: PageDocument,\n limits?: DocumentSecurityLimits,\n): string | null {\n const result = validateDocumentSecurity(document, limits);\n if (result.safe) return null;\n return result.errors.map((error) => `${error.code}: ${error.message}`).join('; ');\n}\n\n/**\n * Normalizes a model-authored node and guarantees its ids don't collide with the snapshot\n * (`insertNode` in `@kubuild/core` throws on duplicate ids). Reuses the shared\n * `normalizeNodeTree` so agent-authored nodes get the same prop/style coercions as nodes\n * from full-page generation.\n */\nexport function normalizeIncomingNode(\n raw: unknown,\n document: PageDocument,\n options: { preserveIds?: boolean } = {},\n): { node: Node } | { error: string } {\n let normalized: Node;\n try {\n normalized = normalizeNodeTree(raw);\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n\n if (!options.preserveIds) {\n const taken = collectNodeIdSet(document.document);\n const reassign = (node: Node): void => {\n if (!node.id || taken.has(node.id)) {\n let counter = 1;\n let candidate = `${node.type}-${counter}`;\n while (taken.has(candidate)) {\n counter++;\n candidate = `${node.type}-${counter}`;\n }\n node.id = candidate;\n }\n taken.add(node.id);\n for (const child of node.children ?? []) reassign(child);\n };\n reassign(normalized);\n }\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n return {\n error: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; '),\n };\n }\n\n return { node: parsed.data };\n}\n\n/** Short human description of a node for tool summaries / op labels. */\nexport function describeNode(node: Node): string {\n const label = getNodeLabel(node, 32);\n return label ? `${node.type} \"${label}\" (#${node.id})` : `${node.type} (#${node.id})`;\n}\n","import type { Node } from '@kubuild/schema';\nimport {\n buildSelectionContext,\n getNodeLabel,\n pruneNodeForPrompt,\n summarizeNodeTree,\n} from '../../core/document-outline';\nimport type { AgentTool } from './types';\nimport { fail, readString, resolveNode, succeed } from './helpers';\n\n/**\n * Read-only tools (STORA-530).\n *\n * All of them are answered straight from the agent's snapshot — no extra model round trip,\n * no network. They exist so the system prompt can ship a cheap outline instead of the whole\n * document, and the model pulls detail only for the handful of nodes it actually needs.\n */\n\nconst getPageOutline: AgentTool = {\n kind: 'read',\n definition: {\n name: 'get_page_outline',\n description:\n 'Return the page structure as an indented outline of node ids, types, labels and child counts. Use this to re-orient after edits. Does not include props or styles — call read_node for those.',\n inputSchema: {\n type: 'object',\n properties: {\n maxDepth: {\n type: 'integer',\n description: 'How deep to expand the tree before collapsing. Default 3.',\n },\n },\n },\n },\n execute(input, context) {\n const maxDepth =\n typeof input.maxDepth === 'number' && input.maxDepth > 0 ? Math.floor(input.maxDepth) : 3;\n return succeed('Membaca struktur halaman', {\n outline: summarizeNodeTree(context.document.document, { maxDepth }),\n });\n },\n};\n\nconst readNode: AgentTool = {\n kind: 'read',\n definition: {\n name: 'read_node',\n description:\n 'Return one node with its full props and styles, plus its parent, position and siblings. Always read a node before editing it, so you change only the fields that need changing.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to read (from the outline).' },\n includeChildren: {\n type: 'boolean',\n description: 'Include the node subtree. Default false — keeps the result small.',\n },\n },\n required: ['nodeId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('read_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const resolved = resolveNode(context.document, nodeId, 'read_node');\n if ('error' in resolved) return resolved.error;\n\n const selection = buildSelectionContext(context.document.document, nodeId);\n const includeChildren = input.includeChildren === true;\n const node = includeChildren\n ? pruneNodeForPrompt(resolved.node, 3)\n : { ...resolved.node, children: undefined };\n\n return succeed(`Membaca node ${nodeId}`, {\n node,\n childCount: resolved.node.children?.length ?? 0,\n parentId: selection?.parentId ?? null,\n index: selection?.index ?? 0,\n ancestors: selection?.ancestors.map((a) => ({ id: a.id, type: a.type })) ?? [],\n siblings:\n selection?.siblings.map((sibling, i) => ({\n index: i,\n id: sibling.id,\n type: sibling.type,\n label: getNodeLabel(sibling),\n })) ?? [],\n });\n },\n};\n\nconst findNodes: AgentTool = {\n kind: 'read',\n definition: {\n name: 'find_nodes',\n description:\n 'Search the page for nodes by component type and/or visible text. Use this instead of guessing ids when the user refers to something by what it says (\"the Get Started button\").',\n inputSchema: {\n type: 'object',\n properties: {\n type: { type: 'string', description: 'Component type to match exactly, e.g. \"button\".' },\n textContains: {\n type: 'string',\n description: 'Case-insensitive substring to match against the node text/label props.',\n },\n parentId: { type: 'string', description: 'Limit the search to this node subtree.' },\n limit: { type: 'integer', description: 'Max results. Default 20.' },\n },\n },\n },\n execute(input, context) {\n const type = readString(input, 'type');\n const textContains = readString(input, 'textContains');\n const parentId = readString(input, 'parentId');\n const limit =\n typeof input.limit === 'number' && input.limit > 0 ? Math.floor(input.limit) : 20;\n\n if (!type && !textContains) {\n return fail(\n 'find_nodes: filter kosong',\n 'Provide at least one of \"type\" or \"textContains\" — an unfiltered search would just return the whole outline.',\n );\n }\n\n let root: Node = context.document.document;\n if (parentId) {\n const resolved = resolveNode(context.document, parentId, 'find_nodes');\n if ('error' in resolved) return resolved.error;\n root = resolved.node;\n }\n\n const needle = textContains?.toLowerCase();\n const matches: Array<{ id: string; type: string; label: string }> = [];\n\n const walk = (node: Node): void => {\n if (matches.length >= limit) return;\n const label = getNodeLabel(node);\n const typeMatches = !type || node.type === type;\n const textMatches = !needle || label.toLowerCase().includes(needle);\n if (typeMatches && textMatches) {\n matches.push({ id: node.id, type: node.type, label });\n }\n for (const child of node.children ?? []) walk(child);\n };\n walk(root);\n\n return succeed(\n `Mencari node (${matches.length} hasil)`,\n matches.length > 0\n ? { matches, count: matches.length }\n : {\n matches: [],\n count: 0,\n hint: 'Nothing matched. Try a broader filter, or call get_page_outline to see what exists.',\n },\n );\n },\n};\n\nconst listComponentTypes: AgentTool = {\n kind: 'read',\n definition: {\n name: 'list_component_types',\n description:\n 'List component types available in this editor, with their props and nesting rules. Call this before inserting a component type you have not used yet.',\n inputSchema: {\n type: 'object',\n properties: {\n category: { type: 'string', description: 'Filter to one category, e.g. \"layout\".' },\n },\n },\n },\n execute(input, context) {\n const category = readString(input, 'category');\n const entries = category\n ? context.catalog.filter((spec) => spec.category === category)\n : context.catalog;\n\n return succeed(`Melihat katalog komponen (${entries.length})`, {\n components: entries.map((spec) => ({\n type: spec.type,\n label: spec.label,\n category: spec.category,\n acceptsChildren: spec.acceptsChildren,\n allowedChildren: spec.allowedChildren,\n props: spec.props?.map((prop) => ({\n name: prop.name,\n type: prop.type,\n options: prop.options,\n })),\n })),\n });\n },\n};\n\nexport const READ_TOOLS: AgentTool[] = [getPageOutline, readNode, findNodes, listComponentTypes];\n","import type { Node, PageDocument } from '@kubuild/schema';\nimport {\n duplicateNode,\n findNodeById,\n insertNode,\n moveNode,\n removeNode,\n replaceNode,\n updateProps,\n updateStyle,\n} from '@kubuild/core';\nimport type { AgentOp } from '../../types';\nimport { getNodeLabel } from '../../core/document-outline';\nimport type { AgentTool, ToolExecutionContext, ToolExecutionResult } from './types';\nimport {\n checkComponentType,\n checkDocumentSecurity,\n checkNesting,\n describeNode,\n fail,\n normalizeIncomingNode,\n readOptionalIndex,\n readPlainObject,\n readString,\n resolveNode,\n succeed,\n} from './helpers';\n\n/**\n * Write tools (STORA-530).\n *\n * Each one produces a single `AgentOp` — never a regenerated document. The op is what the\n * editor later replays through its own store actions, so an agent run lands in the command\n * engine and the history stack exactly like manual editing does.\n *\n * Every write follows the same three-step contract:\n * 1. validate the arguments against the snapshot (ids, types, nesting),\n * 2. apply the corresponding pure `@kubuild/core` command to the snapshot,\n * 3. re-run `validateDocumentSecurity` on the result before the op is accepted.\n * Step 3 matters because the arguments come from a language model: it's the same \"AI output\n * is untrusted input\" boundary `normalizeAndValidate*` enforces for generated documents.\n */\n\nconst BREAKPOINTS = ['base', 'desktop', 'tablet', 'mobile'] as const;\ntype Breakpoint = (typeof BREAKPOINTS)[number];\n\n/**\n * Runs a `@kubuild/core` command against the snapshot and converts a throw into a\n * retry-friendly tool failure. The core commands throw on things the model plausibly gets\n * wrong (duplicate ids, moving a node into its own descendant, removing the root), and\n * those messages are already specific enough to hand straight back to the model.\n */\nfunction applyCommand(\n toolName: string,\n run: () => { document: PageDocument },\n): { document: PageDocument } | { error: ToolExecutionResult } {\n try {\n return run();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: fail(`${toolName} gagal`, message) };\n }\n}\n\nfunction guardSecurity(\n toolName: string,\n document: PageDocument,\n context: ToolExecutionContext,\n): ToolExecutionResult | null {\n const violation = checkDocumentSecurity(document, context.securityLimits);\n if (!violation) return null;\n return fail(\n `${toolName} ditolak (security)`,\n `The resulting document failed the security check and was rejected: ${violation}`,\n );\n}\n\nconst updateNodeProps: AgentTool = {\n kind: 'write',\n definition: {\n name: 'update_node_props',\n description:\n 'Change the props of one existing node (text, label, href, src, level, …). This is the right tool for any content/copy change — it touches nothing else on the page.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to edit.' },\n props: {\n type: 'object',\n description: 'Props to write. Include only the props that should change.',\n },\n merge: {\n type: 'boolean',\n description:\n 'true (default) merges with existing props. Only pass false to deliberately clear the other props.',\n },\n },\n required: ['nodeId', 'props'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('update_node_props: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const props = readPlainObject(input, 'props');\n if (!props) {\n return fail(\n 'update_node_props: props tidak valid',\n 'Argument \"props\" must be a JSON object of prop names to values.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'update_node_props');\n if ('error' in resolved) return resolved.error;\n\n const merge = input.merge !== false;\n const applied = applyCommand('update_node_props', () =>\n updateProps(context.document, { nodeId, props, merge }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('update_node_props', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'update-props', nodeId, props, merge };\n const updated = findNodeById(applied.document.document, nodeId);\n\n return succeed(\n `Ubah props ${describeNode(resolved.node)}`,\n { nodeId, props: updated?.props ?? props, changedKeys: Object.keys(props) },\n { op, document: applied.document },\n );\n },\n};\n\nconst updateNodeStyles: AgentTool = {\n kind: 'write',\n definition: {\n name: 'update_node_styles',\n description:\n 'Change the styles of one existing node. Use `breakpoint` for normal styling and `state` for pseudo-classes like \":hover\". This is the right tool for any color/spacing/size/typography change.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to restyle.' },\n styles: {\n type: 'object',\n description:\n 'CSS properties in camelCase with primitive values, e.g. { \"backgroundColor\": \"#16a34a\", \"paddingTop\": \"24px\" }. Never nest objects here.',\n },\n breakpoint: {\n type: 'string',\n enum: ['base', 'desktop', 'tablet', 'mobile'],\n description: 'Breakpoint layer to write. Default \"base\".',\n },\n state: {\n type: 'string',\n description:\n 'Pseudo-state layer such as \":hover\", \":focus\", \":active\". Mutually exclusive with breakpoint.',\n },\n merge: {\n type: 'boolean',\n description: 'true (default) merges with existing styles in that layer.',\n },\n },\n required: ['nodeId', 'styles'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('update_node_styles: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const styles = readPlainObject(input, 'styles');\n if (!styles) {\n return fail(\n 'update_node_styles: styles tidak valid',\n 'Argument \"styles\" must be a JSON object of CSS properties with primitive values.',\n );\n }\n\n const nested = Object.entries(styles).find(\n ([, value]) => value !== null && typeof value === 'object',\n );\n if (nested) {\n return fail(\n 'update_node_styles: nilai bersarang',\n `Style property \"${nested[0]}\" has an object value. Style values must be primitives — use the \"state\" argument for pseudo-classes instead of nesting them.`,\n );\n }\n\n const rawState = readString(input, 'state');\n const rawBreakpoint = readString(input, 'breakpoint');\n if (rawState && rawBreakpoint) {\n return fail(\n 'update_node_styles: argumen bentrok',\n 'Pass either \"breakpoint\" or \"state\", not both — a pseudo-state layer is not per-breakpoint.',\n );\n }\n if (rawBreakpoint && !BREAKPOINTS.includes(rawBreakpoint as Breakpoint)) {\n return fail(\n 'update_node_styles: breakpoint tidak dikenal',\n `Unknown breakpoint \"${rawBreakpoint}\". Valid values: ${BREAKPOINTS.join(', ')}.`,\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'update_node_styles');\n if ('error' in resolved) return resolved.error;\n\n const state = rawState ? (rawState.startsWith(':') ? rawState : `:${rawState}`) : undefined;\n const breakpoint = state ? undefined : ((rawBreakpoint as Breakpoint) ?? 'base');\n const merge = input.merge !== false;\n\n const applied = applyCommand('update_node_styles', () =>\n updateStyle(context.document, { nodeId, styles, breakpoint, state, merge }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('update_node_styles', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'update-styles', nodeId, styles, breakpoint, state, merge };\n const layer = state ? `state ${state}` : `breakpoint ${breakpoint}`;\n\n return succeed(\n `Ubah style ${describeNode(resolved.node)} (${layer})`,\n { nodeId, layer, appliedStyles: styles },\n { op, document: applied.document },\n );\n },\n};\n\nconst insertComponent: AgentTool = {\n kind: 'write',\n definition: {\n name: 'insert_component',\n description:\n 'Insert one new component into an existing parent node. Use this for adding a single element (a button, a paragraph, an image). For a whole new page section, use insert_section instead.',\n inputSchema: {\n type: 'object',\n properties: {\n parentId: { type: 'string', description: 'Id of the node that will contain the new component.' },\n type: { type: 'string', description: 'Component type from the catalog.' },\n index: {\n type: 'integer',\n description: 'Position among the parent children. Omit to append at the end.',\n },\n props: { type: 'object', description: 'Initial props for the new component.' },\n styles: {\n type: 'object',\n description: 'Initial styles, e.g. { \"base\": { \"marginTop\": \"16px\" } }.',\n },\n children: {\n type: 'array',\n description: 'Optional nested child nodes, each { type, props?, styles?, children? }.',\n items: { type: 'object' },\n },\n },\n required: ['parentId', 'type'],\n },\n },\n execute(input, context) {\n const parentId = readString(input, 'parentId');\n const type = readString(input, 'type');\n if (!parentId || !type) {\n return fail(\n 'insert_component: argumen kurang',\n 'Arguments \"parentId\" and \"type\" are both required.',\n );\n }\n\n const typeError = checkComponentType(context.catalog, type);\n if (typeError) return fail('insert_component: tipe tidak dikenal', typeError);\n\n const resolvedParent = resolveNode(context.document, parentId, 'insert_component');\n if ('error' in resolvedParent) return resolvedParent.error;\n\n const nestingError = checkNesting(context.catalog, resolvedParent.node, type);\n if (nestingError) return fail('insert_component: nesting tidak valid', nestingError);\n\n const normalized = normalizeIncomingNode(\n {\n type,\n props: readPlainObject(input, 'props') ?? undefined,\n styles: readPlainObject(input, 'styles') ?? undefined,\n children: Array.isArray(input.children) ? input.children : undefined,\n },\n context.document,\n );\n if ('error' in normalized) {\n return fail('insert_component: node tidak valid', normalized.error);\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('insert_component', () =>\n insertNode(context.document, { parentId, node: normalized.node, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('insert_component', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'insert-node', parentId, index, node: normalized.node };\n\n return succeed(\n `Tambah ${describeNode(normalized.node)} ke #${parentId}`,\n { nodeId: normalized.node.id, parentId, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\n/**\n * Section insertion delegates to `KubuildAiEngine.generateSection` rather than asking the\n * agent model to author a whole section inline: that path already handles planning,\n * normalization and the `section` JSON schema, and keeps generated markup consistent with\n * the non-agent \"generate\" feature.\n */\nconst insertSection: AgentTool = {\n kind: 'write',\n definition: {\n name: 'insert_section',\n description:\n 'Generate and insert a complete new page section (hero, features, pricing, FAQ, CTA, …) from a description. Use this when the user asks to ADD a section — do not hand-build sections with insert_component.',\n inputSchema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description:\n 'Detailed description of the section: purpose, content, layout and tone. Write it in the language the page uses.',\n },\n index: {\n type: 'integer',\n description: 'Position among the page sections. Omit to append at the end.',\n },\n },\n required: ['prompt'],\n },\n },\n async execute(input, context) {\n const prompt = readString(input, 'prompt');\n if (!prompt) return fail('insert_section: prompt kosong', 'Argument \"prompt\" is required.');\n\n if (!context.generateSection) {\n return fail(\n 'insert_section: tidak tersedia',\n 'Section generation is not available in this deployment. Build the section with insert_component instead.',\n );\n }\n\n const rootId = context.document.document.id;\n const existingSections = (context.document.document.children ?? [])\n .map((child) => `${child.type}: ${getNodeLabel(child) || child.id}`)\n .join(', ');\n\n let generated: Node;\n try {\n generated = await context.generateSection({\n prompt,\n parentContext: `Page \"${context.document.metadata?.title ?? 'Untitled'}\". Existing sections: ${existingSections || '(none)'}`,\n });\n } catch (err) {\n return fail(\n 'insert_section gagal',\n `Section generation failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const normalized = normalizeIncomingNode(generated, context.document);\n if ('error' in normalized) {\n return fail('insert_section: section tidak valid', normalized.error);\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('insert_section', () =>\n insertNode(context.document, { parentId: rootId, node: normalized.node, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('insert_section', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'insert-node', parentId: rootId, index, node: normalized.node };\n\n return succeed(\n `Tambah section baru (#${normalized.node.id})`,\n {\n nodeId: normalized.node.id,\n index: index ?? null,\n childCount: normalized.node.children?.length ?? 0,\n },\n { op, document: applied.document },\n );\n },\n};\n\nconst moveNodeTool: AgentTool = {\n kind: 'write',\n definition: {\n name: 'move_node',\n description: 'Move an existing node to a different parent and/or position.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n targetParentId: { type: 'string', description: 'Id of the new parent node.' },\n index: { type: 'integer', description: 'Position within the new parent. Omit to append.' },\n },\n required: ['nodeId', 'targetParentId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n const targetParentId = readString(input, 'targetParentId');\n if (!nodeId || !targetParentId) {\n return fail(\n 'move_node: argumen kurang',\n 'Arguments \"nodeId\" and \"targetParentId\" are both required.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'move_node');\n if ('error' in resolved) return resolved.error;\n const resolvedParent = resolveNode(context.document, targetParentId, 'move_node');\n if ('error' in resolvedParent) return resolvedParent.error;\n\n const nestingError = checkNesting(context.catalog, resolvedParent.node, resolved.node.type);\n if (nestingError) return fail('move_node: nesting tidak valid', nestingError);\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('move_node', () =>\n moveNode(context.document, { nodeId, targetParentId, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('move_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'move-node', nodeId, targetParentId, index };\n\n return succeed(\n `Pindah ${describeNode(resolved.node)} ke #${targetParentId}`,\n { nodeId, targetParentId, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\nconst duplicateNodeTool: AgentTool = {\n kind: 'write',\n definition: {\n name: 'duplicate_node',\n description:\n 'Duplicate an existing node and its subtree, with fresh ids. Useful for repeating an existing card/feature rather than authoring a new one from scratch.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n targetParentId: {\n type: 'string',\n description: 'Where to put the copy. Defaults to the original node parent.',\n },\n index: { type: 'integer', description: 'Position of the copy. Defaults to right after the original.' },\n },\n required: ['nodeId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('duplicate_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const resolved = resolveNode(context.document, nodeId, 'duplicate_node');\n if ('error' in resolved) return resolved.error;\n\n const targetParentId = readString(input, 'targetParentId') ?? undefined;\n if (targetParentId) {\n const resolvedParent = resolveNode(context.document, targetParentId, 'duplicate_node');\n if ('error' in resolvedParent) return resolvedParent.error;\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('duplicate_node', () =>\n duplicateNode(context.document, { nodeId, targetParentId, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('duplicate_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'duplicate-node', nodeId, targetParentId, index };\n\n return succeed(\n `Duplikat ${describeNode(resolved.node)}`,\n { nodeId, targetParentId: targetParentId ?? null, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\nconst deleteNode: AgentTool = {\n kind: 'write',\n destructive: true,\n definition: {\n name: 'delete_node',\n description:\n 'Permanently remove a node and everything inside it. Only call this when the user unambiguously asked to remove that specific thing. If the request is vague, ask instead.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n reason: {\n type: 'string',\n description: 'Short justification quoting what the user asked for. Shown to the user before they apply.',\n },\n },\n required: ['nodeId', 'reason'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('delete_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const reason = readString(input, 'reason');\n if (!reason) {\n return fail(\n 'delete_node: alasan kosong',\n 'Argument \"reason\" is required for destructive actions — state what the user asked for.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'delete_node');\n if ('error' in resolved) return resolved.error;\n\n const applied = applyCommand('delete_node', () => removeNode(context.document, { nodeId }));\n if ('error' in applied) return applied.error;\n\n const op: AgentOp = { kind: 'delete-node', nodeId };\n\n return succeed(\n `Hapus ${describeNode(resolved.node)} — ${reason}`,\n { nodeId, removedType: resolved.node.type },\n { op, document: applied.document },\n );\n },\n};\n\nconst replaceNodeTool: AgentTool = {\n kind: 'write',\n destructive: true,\n definition: {\n name: 'replace_node',\n description:\n 'Replace a node subtree wholesale. LAST RESORT — only when the children genuinely must be restructured. Never use it to change props or styles; use update_node_props / update_node_styles for that.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node being replaced. The replacement keeps this id.' },\n node: {\n type: 'object',\n description: 'Replacement node { type, props?, styles?, children? }. Its id is forced to nodeId.',\n },\n reason: {\n type: 'string',\n description: 'Why a structural replacement is required instead of a props/styles edit.',\n },\n },\n required: ['nodeId', 'node', 'reason'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n const raw = readPlainObject(input, 'node');\n const reason = readString(input, 'reason');\n if (!nodeId || !raw || !reason) {\n return fail(\n 'replace_node: argumen kurang',\n 'Arguments \"nodeId\", \"node\" and \"reason\" are all required.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'replace_node');\n if ('error' in resolved) return resolved.error;\n\n // Ids inside the replacement are regenerated (preserveIds: false) so a model that\n // re-emits the old subtree's ids can't collide with the rest of the document; the root\n // id is then pinned back to the target, which is what `replaceNode` requires.\n const normalized = normalizeIncomingNode({ ...raw, id: undefined }, context.document);\n if ('error' in normalized) {\n return fail('replace_node: node tidak valid', normalized.error);\n }\n\n const replacement: Node = { ...normalized.node, id: nodeId, type: resolved.node.type };\n\n const applied = applyCommand('replace_node', () =>\n replaceNode(context.document, { nodeId, node: replacement }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('replace_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'replace-node', nodeId, node: replacement };\n\n return succeed(\n `Ganti struktur ${describeNode(resolved.node)} — ${reason}`,\n { nodeId, childCount: replacement.children?.length ?? 0 },\n { op, document: applied.document },\n );\n },\n};\n\nexport const WRITE_TOOLS: AgentTool[] = [\n updateNodeProps,\n updateNodeStyles,\n insertComponent,\n insertSection,\n moveNodeTool,\n duplicateNodeTool,\n deleteNode,\n replaceNodeTool,\n];\n","import type { AiToolDefinition } from '../../types';\nimport type { AgentTool } from './types';\nimport { READ_TOOLS } from './read-tools';\nimport { WRITE_TOOLS } from './write-tools';\n\nexport * from './types';\nexport { READ_TOOLS } from './read-tools';\nexport { WRITE_TOOLS } from './write-tools';\nexport {\n checkNesting,\n checkComponentType,\n checkDocumentSecurity,\n normalizeIncomingNode,\n suggestNodeIds,\n} from './helpers';\n\nexport interface DocumentToolsOptions {\n /**\n * Set false to give the agent a read-only tool set — useful for a \"review my page\"\n * assistant that must never propose mutations.\n */\n allowWrites?: boolean;\n /** Tool names to exclude, e.g. `['delete_node']` on a plan that forbids deletions. */\n exclude?: string[];\n}\n\n/**\n * The document tool set the agent is given (STORA-530).\n *\n * Read tools first: the ordering is what the model sees, and putting the \"look before you\n * edit\" tools at the top nudges it toward reading a node before rewriting it.\n */\nexport function createDocumentTools(options: DocumentToolsOptions = {}): AgentTool[] {\n const { allowWrites = true, exclude = [] } = options;\n const tools = allowWrites ? [...READ_TOOLS, ...WRITE_TOOLS] : [...READ_TOOLS];\n return tools.filter((tool) => !exclude.includes(tool.definition.name));\n}\n\n/** Provider-facing definitions for a tool set. */\nexport function toToolDefinitions(tools: AgentTool[]): AiToolDefinition[] {\n return tools.map((tool) => tool.definition);\n}\n","import type { PageDocument } from '@kubuild/schema';\nimport type {\n AgentOpRecord,\n AiAgentRequest,\n AiAgentRunResult,\n AiChatMessage,\n AiCompiledComponentSpec,\n AiContentBlock,\n AiStreamEvent,\n AiToolUseBlock,\n KubuildAiEngineOptions,\n} from '../types';\nimport { buildAgentSystemPrompt, compileComponentCatalog } from '../core/prompt-compiler';\nimport { getMessageText } from '../core/messages';\nimport type { KubuildAiEngine } from './engine';\nimport { createDocumentTools, toToolDefinitions, type AgentTool } from './tools';\n\nexport interface KubuildAiAgentOptions extends KubuildAiEngineOptions {\n /**\n * Engine used by the `insert_section` tool. Optional: without it the agent still runs,\n * and `insert_section` returns a \"not available\" tool error telling the model to build\n * the section with `insert_component` instead.\n */\n engine?: KubuildAiEngine;\n /** Overrides the default tool set (read + write document tools). */\n tools?: AgentTool[];\n}\n\n/** Ceiling on reasoning steps per run — the primary runaway-cost guard. */\nconst DEFAULT_MAX_STEPS = 8;\n\n/** Ceiling on tool calls the model may request within a single step. */\nconst MAX_TOOL_CALLS_PER_STEP = 8;\n\nfunction toolResultMessage(blocks: AiContentBlock[]): AiChatMessage {\n return { role: 'user', content: blocks, timestamp: Date.now() };\n}\n\n/**\n * The page-editing agent (STORA-530).\n *\n * Unlike every `KubuildAiEngine` method, which is a single request/response, this runs a\n * loop: the model reads the page through tools, makes a surgical change through tools, and\n * stops. The document it mutates is a private **snapshot** — the run's output is an ordered\n * list of `AgentOp`s that the editor replays through its own store actions, so an agent\n * edit lands in the command engine and the undo stack exactly like a manual edit.\n *\n * Nothing here ever touches the user's live document.\n */\nexport class KubuildAiAgent {\n private options: KubuildAiAgentOptions;\n private catalog: AiCompiledComponentSpec[];\n private tools: AgentTool[];\n\n constructor(options: KubuildAiAgentOptions) {\n if (!options.adapter) {\n throw new Error('KubuildAiAgent requires an adapter instance');\n }\n if (!options.adapter.supportsTools) {\n // Failing loudly beats running a tool-less loop that can never edit anything: the\n // model would just describe the change it \"made\" and the user would get no ops.\n throw new Error(\n `Adapter \"${options.adapter.name}\" does not support tool calling, which agent mode requires. Use an adapter with supportsTools === true (e.g. OpenAiAdapter).`,\n );\n }\n this.options = options;\n this.catalog = compileComponentCatalog(options.registry);\n this.tools = options.tools ?? createDocumentTools();\n }\n\n get adapterName(): string {\n return this.options.adapter.name;\n }\n\n refreshCatalog(): void {\n this.catalog = compileComponentCatalog(this.options.registry);\n }\n\n private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: unknown): void {\n if (this.options.logger) {\n this.options.logger(level, message, meta);\n } else if (this.options.debug) {\n console.log(`[KUBUILD-AGENT ${level.toUpperCase()}] ${message}`, meta !== undefined ? meta : '');\n }\n }\n\n private findTool(name: string): AgentTool | undefined {\n return this.tools.find((tool) => tool.definition.name === name);\n }\n\n /**\n * Runs one tool call against the current snapshot.\n *\n * An unknown tool name is answered with a normal (failed) tool result rather than an\n * exception, for the same reason bad arguments are: it gives the model a chance to pick a\n * real tool on the next step instead of killing the run.\n */\n private async executeToolCall(\n call: AiToolUseBlock,\n snapshot: PageDocument,\n signal?: AbortSignal,\n ): Promise<{\n block: AiContentBlock;\n ok: boolean;\n summary: string;\n snapshot: PageDocument;\n op?: AgentOpRecord;\n }> {\n const tool = this.findTool(call.name);\n\n if (!tool) {\n const available = this.tools.map((t) => t.definition.name).join(', ');\n return {\n ok: false,\n summary: `Tool \"${call.name}\" tidak dikenal`,\n snapshot,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({\n ok: false,\n error: `Unknown tool \"${call.name}\". Available tools: ${available}.`,\n }),\n },\n };\n }\n\n let result;\n try {\n result = await tool.execute(call.input ?? {}, {\n document: snapshot,\n catalog: this.catalog,\n securityLimits: this.options.securityLimits,\n signal,\n generateSection: this.options.engine\n ? async ({ prompt, parentContext }) => {\n const response = await this.options.engine!.generateSection(\n { prompt, parentContext },\n { signal },\n );\n if (!response.success || !response.data) {\n throw new Error(response.error?.message ?? 'Section generation failed');\n }\n return response.data;\n }\n : undefined,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Tool \"${call.name}\" threw`, message);\n return {\n ok: false,\n summary: `Tool \"${call.name}\" error`,\n snapshot,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({ ok: false, error: message }),\n },\n };\n }\n\n const op: AgentOpRecord | undefined =\n result.ok && result.op\n ? {\n id: call.id,\n op: result.op,\n summary: result.summary,\n destructive: tool.destructive === true,\n }\n : undefined;\n\n return {\n ok: result.ok,\n summary: result.summary,\n snapshot: result.document ?? snapshot,\n op,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: !result.ok,\n content: JSON.stringify(result.content),\n },\n };\n }\n\n /**\n * Executes one agent turn, streaming progress as `AiStreamEvent`s and ending with a\n * terminal `agent-complete` (or `error`) event.\n *\n * The loop stops as soon as the model returns a turn with no tool calls — that final\n * message is the summary shown to the user. It also stops at `maxSteps` (cost guard) or\n * on abort, and reports which of those happened via `stoppedBy` so the UI can say\n * \"stopped after N steps\" rather than pretending the work is finished.\n */\n async *run(\n request: AiAgentRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n const maxSteps = request.maxSteps ?? this.options.maxAgentSteps ?? DEFAULT_MAX_STEPS;\n const signal = context?.signal;\n\n if (!request.messages || request.messages.length === 0) {\n yield {\n type: 'error',\n error: { code: 'INVALID_AGENT_REQUEST', message: '\"messages\" must not be empty' },\n };\n return;\n }\n\n if (!request.document?.document) {\n yield {\n type: 'error',\n error: { code: 'INVALID_AGENT_REQUEST', message: '\"document\" is required for agent mode' },\n };\n return;\n }\n\n // The system prompt is built once from the *initial* document: the outline the model\n // starts from stays stable across steps, which keeps the prompt prefix cacheable. Edits\n // made mid-run are reflected in tool results, and the model can always call\n // get_page_outline for a refreshed view.\n const systemPrompt = buildAgentSystemPrompt({\n catalog: this.catalog,\n document: request.document,\n selectedNodeId: request.selectedNodeId,\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n additionalContext: request.systemPrompt,\n });\n\n const toolDefinitions = toToolDefinitions(this.tools);\n const messages: AiChatMessage[] = [...request.messages];\n const ops: AgentOpRecord[] = [];\n\n let snapshot: PageDocument = request.document;\n let promptTokens = 0;\n let completionTokens = 0;\n let summary = '';\n let stoppedBy: AiAgentRunResult['stoppedBy'] = 'complete';\n let step = 0;\n\n this.log('info', `[AGENT] run started (maxSteps=${maxSteps}, tools=${toolDefinitions.length})`);\n\n try {\n while (step < maxSteps) {\n if (signal?.aborted) {\n stoppedBy = 'aborted';\n break;\n }\n\n step++;\n yield { type: 'agent-step', step, maxSteps };\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt: getMessageText(request.messages[request.messages.length - 1]),\n messages,\n tools: toolDefinitions,\n toolChoice: 'auto',\n signal,\n });\n\n promptTokens += result.usage?.promptTokens ?? 0;\n completionTokens += result.usage?.completionTokens ?? 0;\n\n const toolCalls = result.toolCalls ?? [];\n\n if (toolCalls.length === 0) {\n summary = result.text.trim();\n stoppedBy = 'complete';\n this.log('info', `[AGENT] finished after ${step} step(s) with ${ops.length} op(s)`);\n break;\n }\n\n // Record the assistant turn (text + tool calls) before the results, so the next\n // request replays a well-formed call/result pairing.\n const assistantBlocks: AiContentBlock[] = [];\n if (result.text.trim()) {\n assistantBlocks.push({ type: 'text', text: result.text });\n }\n assistantBlocks.push(...toolCalls);\n messages.push({ role: 'assistant', content: assistantBlocks, timestamp: Date.now() });\n\n const capped = toolCalls.slice(0, MAX_TOOL_CALLS_PER_STEP);\n const resultBlocks: AiContentBlock[] = [];\n\n for (const call of capped) {\n if (signal?.aborted) {\n stoppedBy = 'aborted';\n break;\n }\n\n yield { type: 'tool-call', id: call.id, name: call.name, input: call.input ?? {} };\n\n const executed = await this.executeToolCall(call, snapshot, signal);\n snapshot = executed.snapshot;\n resultBlocks.push(executed.block);\n if (executed.op) ops.push(executed.op);\n\n yield {\n type: 'tool-result',\n id: call.id,\n name: call.name,\n ok: executed.ok,\n summary: executed.summary,\n };\n }\n\n // Every tool call must get a matching result, or the next provider request is\n // malformed — so calls dropped by the per-step cap or by an abort are answered\n // explicitly rather than left dangling.\n for (const call of toolCalls.slice(capped.length)) {\n resultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({\n ok: false,\n error: `Too many tool calls in one step (limit ${MAX_TOOL_CALLS_PER_STEP}). This call was not executed — request it again in the next step.`,\n }),\n });\n }\n\n messages.push(toolResultMessage(resultBlocks));\n\n if (stoppedBy === 'aborted') break;\n }\n\n if (stoppedBy === 'complete' && step >= maxSteps && !summary) {\n stoppedBy = 'max-steps';\n summary = `Berhenti setelah ${maxSteps} langkah. ${ops.length} perubahan sudah disiapkan — periksa hasilnya lalu minta lanjutan bila perlu.`;\n this.log('warn', `[AGENT] hit maxSteps (${maxSteps}) with ${ops.length} op(s)`);\n }\n\n if (stoppedBy === 'aborted' && !summary) {\n summary = `Dihentikan. ${ops.length} perubahan sempat disiapkan.`;\n }\n\n yield {\n type: 'agent-complete',\n result: {\n ops,\n summary,\n stepsUsed: step,\n stoppedBy,\n usage: { promptTokens, completionTokens },\n },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[AGENT] run failed: ${message}`);\n // Ops produced before the failure are still valid and still reviewable — dropping\n // them would silently discard work the user can see happening in the timeline.\n yield {\n type: 'agent-complete',\n result: {\n ops,\n summary: summary || `Terjadi error: ${message}`,\n stepsUsed: step,\n stoppedBy: 'error',\n usage: { promptTokens, completionTokens },\n },\n };\n yield { type: 'error', error: { code: 'AGENT_ERROR', message } };\n }\n }\n\n /** Non-streaming convenience wrapper — drains `run()` and returns its terminal result. */\n async execute(\n request: AiAgentRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiAgentRunResult> {\n let final: AiAgentRunResult | null = null;\n let error: { code: string; message: string } | null = null;\n\n for await (const event of this.run(request, context)) {\n if (event.type === 'agent-complete') final = event.result;\n if (event.type === 'error') error = event.error;\n }\n\n if (final) return final;\n return {\n ops: [],\n summary: error?.message ?? 'Agent produced no result',\n stepsUsed: 0,\n stoppedBy: 'error',\n };\n }\n}\n","import type { KubuildAiEngine } from './engine';\nimport type { KubuildAiAgent } from './agent';\nimport type { PageDocument } from '@kubuild/schema';\nimport type {\n AiGeneratePageRequest,\n AiGenerateSectionRequest,\n AiRefactorNodeRequest,\n AiChatMessage,\n AiGenerateResponse,\n AiGenerationMode,\n AiStreamEvent,\n} from '../types';\n\nexport interface AiApiRequestBody {\n mode?: AiGenerationMode;\n prompt?: string;\n stylePreference?: string;\n tone?: string;\n locale?: string;\n metadata?: AiGeneratePageRequest['metadata'];\n targetSectionType?: string;\n parentContext?: string;\n node?: AiRefactorNodeRequest['node'];\n instruction?: string;\n stream?: boolean;\n messages?: AiChatMessage[];\n currentDocument?: PageDocument;\n selectedNodeId?: string;\n /** Agent mode (STORA-530) — the snapshot the agent reads and patches. */\n document?: PageDocument;\n maxSteps?: number;\n}\n\nexport async function processAiRequest(\n engine: KubuildAiEngine,\n body: unknown,\n signal?: AbortSignal,\n agent?: KubuildAiAgent,\n): Promise<{ status: number; response: AiGenerateResponse<unknown> }> {\n if (!body || typeof body !== 'object') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'BAD_REQUEST',\n message: 'Request body must be a valid JSON object',\n },\n },\n };\n }\n\n const payload = body as AiApiRequestBody;\n const mode = payload.mode || 'full-page';\n\n if (mode === 'full-page') {\n if (!payload.prompt || typeof payload.prompt !== 'string') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for full-page generation',\n },\n },\n };\n }\n const result = await engine.generatePage(\n {\n prompt: payload.prompt,\n stylePreference: payload.stylePreference,\n tone: payload.tone,\n locale: payload.locale,\n metadata: payload.metadata,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'section') {\n if (!payload.prompt || typeof payload.prompt !== 'string') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for section generation',\n },\n },\n };\n }\n const result = await engine.generateSection(\n {\n prompt: payload.prompt,\n stylePreference: payload.stylePreference,\n targetSectionType: payload.targetSectionType,\n parentContext: payload.parentContext,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'refactor') {\n if (!payload.node || !payload.instruction) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_REFACTOR_PARAMS',\n message: '\"node\" and \"instruction\" are required for refactoring',\n },\n },\n };\n }\n const result = await engine.refactorNode(\n {\n node: payload.node,\n instruction: payload.instruction,\n stylePreference: payload.stylePreference,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'chat') {\n if (!payload.messages || !Array.isArray(payload.messages) || payload.messages.length === 0) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_CHAT_PARAMS',\n message: '\"messages\" array is required and must not be empty for chat mode',\n },\n },\n };\n }\n const result = await engine.chat(\n {\n messages: payload.messages,\n currentDocument: payload.currentDocument,\n selectedNodeId: payload.selectedNodeId,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'agent') {\n const validationError = validateAgentPayload(payload, agent);\n if (validationError) {\n return { status: validationError.status, response: validationError.response };\n }\n\n const result = await agent!.execute(\n {\n messages: payload.messages!,\n document: payload.document!,\n selectedNodeId: payload.selectedNodeId,\n stylePreference: payload.stylePreference,\n maxSteps: payload.maxSteps,\n },\n { signal },\n );\n\n return {\n status: result.stoppedBy === 'error' ? 500 : 200,\n response: { success: result.stoppedBy !== 'error', data: result },\n };\n }\n\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'UNKNOWN_MODE',\n message: `Unsupported mode: ${String(mode)}. Supported modes: 'full-page', 'section', 'refactor', 'chat', 'agent'`,\n },\n },\n };\n}\n\n/**\n * Shared validation for agent-mode requests (STORA-530) — used by both the JSON and the\n * SSE paths so they can never disagree about what a valid agent request looks like.\n * Returns `null` when the payload is good.\n */\nfunction validateAgentPayload(\n payload: AiApiRequestBody,\n agent?: KubuildAiAgent,\n): { status: number; response: AiGenerateResponse<never> } | null {\n if (!agent) {\n return {\n status: 501,\n response: {\n success: false,\n error: {\n code: 'AGENT_NOT_CONFIGURED',\n message:\n 'Agent mode is not enabled on this endpoint. Pass a KubuildAiAgent to createAiHandler to enable it.',\n },\n },\n };\n }\n\n if (!payload.messages || !Array.isArray(payload.messages) || payload.messages.length === 0) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_AGENT_PARAMS',\n message: '\"messages\" array is required and must not be empty for agent mode',\n },\n },\n };\n }\n\n if (!payload.document || !payload.document.document) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_AGENT_PARAMS',\n message: '\"document\" (the current PageDocument) is required for agent mode',\n },\n },\n };\n }\n\n return null;\n}\n\n/**\n * Options for {@link createAiHandler} (STORA-519).\n */\nexport interface CreateAiHandlerOptions {\n /**\n * Enables agent mode (STORA-530) on this endpoint. Without it, `mode: 'agent'` requests\n * are answered with a 501 rather than silently falling back to chat.\n */\n agent?: KubuildAiAgent;\n\n /**\n * Optional hook invoked with the raw incoming `Request` before it ever reaches the\n * engine/provider — the place to plug in host-owned auth and/or rate-limiting without\n * forking the handler.\n *\n * - Return a `Response` (or a Promise resolving to one) to reject/short-circuit the\n * request — e.g. `new Response(..., { status: 401 })` or `429` — that response is\n * returned as-is and the engine/provider is never invoked.\n * - Return `void`/`undefined` (or a Promise resolving to that) to allow the request to\n * continue through the normal handler logic unchanged.\n *\n * Omitting this option entirely preserves the exact pre-STORA-519 behavior.\n */\n beforeRequest?: (request: Request) => Promise<Response | void> | Response | void;\n}\n\n/**\n * Pipes an `AiStreamEvent` iterable out as an SSE response (STORA-530).\n *\n * All three streaming modes (`streamPage`, `chatStream`, agent `run`) emit the same event\n * shape over the same transport, so they share one encoder instead of three near-identical\n * `ReadableStream` blocks. A throw mid-stream is delivered as a final `error` event rather\n * than tearing down the connection, so the client can render it in place.\n */\nfunction sseResponse(\n events: AsyncIterable<AiStreamEvent>,\n errorCode: string,\n): Response {\n const encoder = new TextEncoder();\n const readable = new ReadableStream({\n async start(controller) {\n try {\n for await (const event of events) {\n controller.enqueue(\n encoder.encode(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`),\n );\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n controller.enqueue(\n encoder.encode(\n `event: error\\ndata: ${JSON.stringify({ type: 'error', error: { code: errorCode, message } })}\\n\\n`,\n ),\n );\n } finally {\n controller.close();\n }\n },\n });\n\n return new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n },\n });\n}\n\n/**\n * Creates a standard Web Fetch API Request handler with optional SSE streaming support.\n *\n * Plug-and-play for Next.js App Router (route.ts), SvelteKit, Remix, Astro, Bun, etc.\n *\n * Example:\n * ```ts\n * export const POST = createAiHandler(engine);\n * ```\n *\n * Example with an auth/rate-limit hook (STORA-519):\n * ```ts\n * export const POST = createAiHandler(engine, {\n * beforeRequest: async (request) => {\n * if (!isAuthorized(request)) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * // returning nothing lets the request proceed as normal\n * },\n * });\n * ```\n */\nexport function createAiHandler(engine: KubuildAiEngine, options?: CreateAiHandlerOptions) {\n return async (request: Request): Promise<Response> => {\n try {\n if (options?.beforeRequest) {\n const hookResult = await options.beforeRequest(request);\n if (hookResult instanceof Response) {\n return hookResult;\n }\n }\n\n if (request.method !== 'POST') {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'METHOD_NOT_ALLOWED',\n message: 'Only POST requests are accepted',\n },\n }),\n {\n status: 405,\n headers: {\n 'Content-Type': 'application/json',\n Allow: 'POST',\n },\n },\n );\n }\n\n const body = (await request.json().catch(() => null)) as AiApiRequestBody | null;\n\n // Handle opt-in SSE Streaming\n if (body && typeof body === 'object' && body.stream === true) {\n const mode = body.mode || 'full-page';\n\n // Agent streaming (STORA-530) — emits agent-step/tool-call/tool-result events as\n // the loop runs, then a terminal agent-complete carrying the ops to replay.\n if (mode === 'agent') {\n const validationError = validateAgentPayload(body, options?.agent);\n if (validationError) {\n return new Response(JSON.stringify(validationError.response), {\n status: validationError.status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return sseResponse(\n options!.agent!.run(\n {\n messages: body.messages!,\n document: body.document!,\n selectedNodeId: body.selectedNodeId,\n stylePreference: body.stylePreference,\n maxSteps: body.maxSteps,\n },\n { signal: request.signal },\n ),\n 'AGENT_STREAM_ERROR',\n );\n }\n\n // Token-level chat streaming (STORA-515) — routed separately from full-page\n // streaming below since it needs `messages`, not `prompt`.\n if (mode === 'chat') {\n if (!body.messages || !Array.isArray(body.messages) || body.messages.length === 0) {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INVALID_CHAT_PARAMS',\n message: '\"messages\" array is required and must not be empty for chat mode',\n },\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n },\n );\n }\n\n return sseResponse(\n engine.chatStream(\n {\n messages: body.messages!,\n currentDocument: body.currentDocument,\n selectedNodeId: body.selectedNodeId,\n },\n { signal: request.signal },\n ),\n 'CHAT_STREAM_ERROR',\n );\n }\n\n if (!body.prompt || typeof body.prompt !== 'string') {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for streaming generation',\n },\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n },\n );\n }\n\n return sseResponse(\n engine.streamPage(\n {\n prompt: body.prompt!,\n stylePreference: body.stylePreference,\n tone: body.tone,\n locale: body.locale,\n metadata: body.metadata,\n },\n { signal: request.signal },\n ),\n 'STREAM_ERROR',\n );\n }\n\n // Default: Standard non-streaming JSON response (Backward-compatible)\n const { status, response } = await processAiRequest(\n engine,\n body,\n request.signal,\n options?.agent,\n );\n\n return new Response(JSON.stringify(response), {\n status,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INTERNAL_SERVER_ERROR',\n message,\n },\n }),\n {\n status: 500,\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n }\n };\n}\n","/**\n * Shared SSE (server-sent events) frame reader for provider adapters that support\n * token-level streaming (STORA-515) — OpenAI, Anthropic and Gemini all expose their\n * streaming APIs as `data: <json>\\n\\n` frames, so every adapter reuses this single\n * low-level reader instead of re-implementing buffering/decoding three times.\n *\n * Yields the raw string payload of each `data:` line (already trimmed), in arrival\n * order. Callers are responsible for `JSON.parse`-ing (or ignoring sentinel values\n * like OpenAI's `[DONE]`) and for interpreting provider-specific event shapes.\n */\nexport async function* readSseDataLines(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<string, void, void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n if (signal?.aborted) {\n throw new Error('Streaming aborted by client');\n }\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop() || '';\n\n for (const frame of frames) {\n for (const line of frame.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data:')) {\n yield trimmed.slice(5).trim();\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { readSseDataLines } from './stream-utils';\nimport { getMessageText } from '../../core/messages';\n\nexport interface GeminiAdapterOptions {\n apiKey: string;\n model?: string;\n temperature?: number;\n baseUrl?: string;\n}\n\nexport class GeminiAdapter implements AiProviderAdapter {\n readonly name = 'gemini';\n private apiKey: string;\n private model: string;\n private temperature: number;\n private baseUrl: string;\n\n constructor(options: GeminiAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('GeminiAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'gemini-2.5-flash';\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl =\n options.baseUrl || 'https://generativelanguage.googleapis.com/v1beta';\n }\n\n private buildContents(\n params: AiProviderGenerateParams,\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n const { userPrompt, messages: chatMessages } = params;\n return chatMessages && chatMessages.length > 0\n ? chatMessages.map((m) => ({\n role: m.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: getMessageText(m) }],\n }))\n : [\n {\n role: 'user',\n parts: [{ text: userPrompt }],\n },\n ];\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const { systemPrompt, messages: chatMessages, signal } = params;\n\n const url = `${this.baseUrl}/models/${encodeURIComponent(this.model)}:generateContent?key=${encodeURIComponent(this.apiKey)}`;\n const contents = this.buildContents(params);\n\n const generationConfig: Record<string, unknown> = {\n temperature: this.temperature,\n };\n\n if (params.jsonSchema || (!chatMessages && (systemPrompt.includes('JSON') || systemPrompt.includes('json')))) {\n generationConfig.responseMimeType = 'application/json';\n }\n\n const body: Record<string, unknown> = {\n system_instruction: {\n parts: [{ text: systemPrompt }],\n },\n contents,\n generationConfig,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Gemini API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: {\n parts?: Array<{ text?: string }>;\n };\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n };\n };\n\n const candidateText = data.candidates?.[0]?.content?.parts?.[0]?.text;\n if (!candidateText) {\n throw new Error('Gemini returned an empty or invalid candidate response');\n }\n\n return {\n text: candidateText,\n usage: data.usageMetadata\n ? {\n promptTokens: data.usageMetadata.promptTokenCount,\n completionTokens: data.usageMetadata.candidatesTokenCount,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via Gemini's `streamGenerateContent` SSE endpoint (STORA-515).\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { systemPrompt, signal } = params;\n const url = `${this.baseUrl}/models/${encodeURIComponent(this.model)}:streamGenerateContent?alt=sse&key=${encodeURIComponent(this.apiKey)}`;\n const contents = this.buildContents(params);\n\n const generationConfig: Record<string, unknown> = {\n temperature: this.temperature,\n };\n\n const body: Record<string, unknown> = {\n system_instruction: {\n parts: [{ text: systemPrompt }],\n },\n contents,\n generationConfig,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Gemini API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n if (!res.body) {\n throw new Error('Gemini streaming response has no readable body');\n }\n\n let text = '';\n let usage: AiProviderGenerateResult['usage'];\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n let parsed: {\n candidates?: Array<{ content?: { parts?: Array<{ text?: string }> } }>;\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n };\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n\n const delta = parsed.candidates?.[0]?.content?.parts?.[0]?.text;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n\n if (parsed.usageMetadata) {\n usage = {\n promptTokens: parsed.usageMetadata.promptTokenCount,\n completionTokens: parsed.usageMetadata.candidatesTokenCount,\n };\n }\n }\n\n return { text, usage };\n }\n}\n","import type {\n AiChatMessage,\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n AiStopReason,\n AiToolUseBlock,\n} from '../../types';\nimport { getMessageText, getToolResultBlocks, getToolUseBlocks } from '../../core/messages';\nimport { readSseDataLines } from './stream-utils';\n\nexport interface OpenAiAdapterOptions {\n apiKey: string;\n model?: string;\n temperature?: number;\n baseUrl?: string;\n headers?: Record<string, string>;\n}\n\n/** OpenAI Chat Completions message shape — `tool_calls`/`role: 'tool'` included. */\ninterface OpenAiMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string | null;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n }>;\n tool_call_id?: string;\n}\n\ninterface OpenAiToolCallPayload {\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n}\n\n/**\n * Maps OpenAI's `finish_reason` onto the provider-agnostic `AiStopReason` the agent loop\n * branches on (STORA-530).\n */\nfunction mapStopReason(finishReason: string | undefined | null): AiStopReason {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'tool_calls':\n case 'function_call':\n return 'tool_calls';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Parses OpenAI `tool_calls` into `AiToolUseBlock`s. A call whose `arguments` isn't valid\n * JSON is surfaced with an empty `input` rather than throwing: the agent's tool executor\n * then rejects it with a `tool_result` error and the model self-corrects on the next step,\n * which is far better than killing the whole run over one malformed argument blob.\n */\nfunction parseToolCalls(raw: OpenAiToolCallPayload[] | undefined): AiToolUseBlock[] {\n if (!Array.isArray(raw) || raw.length === 0) return [];\n return raw\n .filter((call) => call?.function?.name)\n .map((call, index) => {\n let input: Record<string, unknown> = {};\n const argsText = call.function?.arguments;\n if (argsText && argsText.trim()) {\n try {\n const parsed = JSON.parse(argsText);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n input = parsed as Record<string, unknown>;\n }\n } catch {\n input = {};\n }\n }\n return {\n type: 'tool_use' as const,\n id: call.id || `call_${index}`,\n name: call.function!.name!,\n input,\n };\n });\n}\n\nexport class OpenAiAdapter implements AiProviderAdapter {\n readonly name = 'openai';\n readonly supportsTools = true;\n private apiKey: string;\n private model: string;\n private temperature: number;\n private baseUrl: string;\n private customHeaders?: Record<string, string>;\n\n constructor(options: OpenAiAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('OpenAiAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'gpt-4o';\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl = (options.baseUrl || 'https://api.openai.com/v1').replace(/\\/+$/, '');\n this.customHeaders = options.headers;\n }\n\n /**\n * Expands one `AiChatMessage` into the one-or-more OpenAI messages it corresponds to\n * (STORA-530).\n *\n * The block model is Anthropic-shaped — tool results ride along inside a `user` message —\n * while OpenAI wants each result as its own `role: 'tool'` message keyed by\n * `tool_call_id`. That fan-out happens here so the rest of the stack stays\n * provider-agnostic.\n */\n private mapMessage(message: AiChatMessage): OpenAiMessage[] {\n const toolUses = getToolUseBlocks(message);\n const toolResults = getToolResultBlocks(message);\n const text = getMessageText(message);\n\n if (toolResults.length > 0) {\n const results: OpenAiMessage[] = toolResults.map((block) => ({\n role: 'tool',\n content: block.content,\n tool_call_id: block.toolUseId,\n }));\n // Any free text riding alongside tool results becomes a separate user turn — OpenAI\n // rejects a `role: 'tool'` message that carries anything but the result payload.\n if (text.trim()) {\n results.push({ role: 'user', content: text });\n }\n return results;\n }\n\n if (toolUses.length > 0) {\n return [\n {\n role: 'assistant',\n content: text.trim() ? text : null,\n tool_calls: toolUses.map((block) => ({\n id: block.id,\n type: 'function' as const,\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input ?? {}),\n },\n })),\n },\n ];\n }\n\n return [{ role: message.role, content: text }];\n }\n\n private buildMessages(params: AiProviderGenerateParams): OpenAiMessage[] {\n const { systemPrompt, userPrompt, messages: chatMessages } = params;\n if (chatMessages && chatMessages.length > 0) {\n return [\n { role: 'system', content: systemPrompt },\n ...chatMessages.flatMap((m) => this.mapMessage(m)),\n ];\n }\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n }\n\n /**\n * Shared request body builder for `generate`/`generateStream` — notably the\n * `response_format` decision, which must never fire in tool mode: OpenAI rejects\n * `json_object` combined with `tools`, and a tool-calling turn's text output is a\n * natural-language summary, not JSON.\n */\n private buildBody(params: AiProviderGenerateParams): Record<string, unknown> {\n const { systemPrompt, jsonSchema, messages: chatMessages, tools, toolChoice } = params;\n\n const body: Record<string, unknown> = {\n model: this.model,\n temperature: params.temperature ?? this.temperature,\n messages: this.buildMessages(params),\n };\n\n if (tools && tools.length > 0) {\n body.tools = tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n },\n }));\n if (toolChoice) {\n body.tool_choice =\n typeof toolChoice === 'string'\n ? toolChoice\n : { type: 'function', function: { name: toolChoice.name } };\n }\n return body;\n }\n\n // Only force json_object when JSON schema is provided or specifically requested,\n // allowing natural conversation text in chat mode.\n if (jsonSchema || (!chatMessages && (systemPrompt.includes('JSON') || systemPrompt.includes('json')))) {\n body.response_format = { type: 'json_object' };\n }\n\n return body;\n }\n\n private async post(body: Record<string, unknown>, signal?: AbortSignal): Promise<Response> {\n const res = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `OpenAI API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n return res;\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const res = await this.post(this.buildBody(params), params.signal);\n\n const data = (await res.json()) as {\n choices?: Array<{\n finish_reason?: string;\n message?: {\n content?: string;\n tool_calls?: OpenAiToolCallPayload[];\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n };\n };\n\n const choice = data.choices?.[0];\n const content = choice?.message?.content;\n const toolCalls = parseToolCalls(choice?.message?.tool_calls);\n\n // A tool-calling turn legitimately has null content — only a turn with neither text\n // nor tool calls is an empty response worth throwing over.\n if (!content && toolCalls.length === 0) {\n throw new Error('OpenAI returned an empty message content');\n }\n\n return {\n text: content || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n stopReason: mapStopReason(choice?.finish_reason),\n usage: data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via OpenAI's `stream: true` chat completions mode (STORA-515).\n * Yields each `delta.content` fragment as it arrives and returns the fully assembled\n * text + usage (when the final chunk includes it) once the stream ends.\n *\n * Tool calls arrive fragmented too (STORA-530): `delta.tool_calls[].function.arguments`\n * is delivered as a character stream across many chunks, keyed by array `index`. They're\n * accumulated per index and parsed only once the stream ends — parsing a partial\n * arguments string would always fail. Tool call deltas are never `yield`ed as text,\n * since they aren't part of the assistant's visible message.\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { signal } = params;\n const res = await this.post({ ...this.buildBody(params), stream: true }, signal);\n\n if (!res.body) {\n throw new Error('OpenAI streaming response has no readable body');\n }\n\n let text = '';\n let usage: AiProviderGenerateResult['usage'];\n let finishReason: string | undefined;\n const toolCallAccumulator = new Map<number, { id: string; name: string; arguments: string }>();\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n if (raw === '[DONE]') break;\n\n let parsed: {\n choices?: Array<{\n finish_reason?: string;\n delta?: {\n content?: string;\n tool_calls?: Array<OpenAiToolCallPayload & { index?: number }>;\n };\n }>;\n usage?: { prompt_tokens?: number; completion_tokens?: number };\n };\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n\n const choice = parsed.choices?.[0];\n\n const delta = choice?.delta?.content;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n\n for (const call of choice?.delta?.tool_calls ?? []) {\n const index = typeof call.index === 'number' ? call.index : 0;\n const entry = toolCallAccumulator.get(index) ?? { id: '', name: '', arguments: '' };\n if (call.id) entry.id = call.id;\n if (call.function?.name) entry.name = call.function.name;\n if (call.function?.arguments) entry.arguments += call.function.arguments;\n toolCallAccumulator.set(index, entry);\n }\n\n if (choice?.finish_reason) {\n finishReason = choice.finish_reason;\n }\n\n if (parsed.usage) {\n usage = {\n promptTokens: parsed.usage.prompt_tokens,\n completionTokens: parsed.usage.completion_tokens,\n };\n }\n }\n\n const toolCalls = parseToolCalls(\n Array.from(toolCallAccumulator.entries())\n .sort(([a], [b]) => a - b)\n .map(([, entry]) => ({\n id: entry.id,\n type: 'function',\n function: { name: entry.name, arguments: entry.arguments },\n })),\n );\n\n return {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n stopReason: mapStopReason(finishReason),\n usage,\n };\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { readSseDataLines } from './stream-utils';\nimport { getMessageText } from '../../core/messages';\n\nexport interface AnthropicAdapterOptions {\n apiKey: string;\n model?: string;\n maxTokens?: number;\n temperature?: number;\n baseUrl?: string;\n anthropicVersion?: string;\n headers?: Record<string, string>;\n}\n\nexport class AnthropicAdapter implements AiProviderAdapter {\n readonly name = 'anthropic';\n private apiKey: string;\n private model: string;\n private maxTokens: number;\n private temperature: number;\n private baseUrl: string;\n private anthropicVersion: string;\n private customHeaders?: Record<string, string>;\n\n constructor(options: AnthropicAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('AnthropicAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'claude-3-5-sonnet-20241022';\n this.maxTokens = options.maxTokens ?? 4096;\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl = (options.baseUrl || 'https://api.anthropic.com/v1').replace(/\\/+$/, '');\n this.anthropicVersion = options.anthropicVersion || '2023-06-01';\n this.customHeaders = options.headers;\n }\n\n private buildMessages(\n params: AiProviderGenerateParams,\n ): Array<{ role: 'user' | 'assistant'; content: string }> {\n const { userPrompt, messages: chatMessages } = params;\n return chatMessages && chatMessages.length > 0\n ? chatMessages\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .map((m) => ({ role: m.role as 'user' | 'assistant', content: getMessageText(m) }))\n : [\n {\n role: 'user' as const,\n content: userPrompt,\n },\n ];\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const { systemPrompt, signal } = params;\n\n const url = `${this.baseUrl}/messages`;\n const messages = this.buildMessages(params);\n\n const body: Record<string, unknown> = {\n model: this.model,\n max_tokens: this.maxTokens,\n temperature: this.temperature,\n system: systemPrompt,\n messages,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': this.anthropicVersion,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Anthropic API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const data = (await res.json()) as {\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const textPart = data.content?.find((c) => c.type === 'text')?.text;\n if (!textPart) {\n throw new Error('Anthropic returned an empty text content');\n }\n\n return {\n text: textPart,\n usage: data.usage\n ? {\n promptTokens: data.usage.input_tokens,\n completionTokens: data.usage.output_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via Anthropic's `stream: true` Messages API (STORA-515).\n * Parses the `content_block_delta` (`text_delta`) events for incremental text and the\n * `message_start`/`message_delta` events for usage accounting.\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { systemPrompt, signal } = params;\n const url = `${this.baseUrl}/messages`;\n const messages = this.buildMessages(params);\n\n const body: Record<string, unknown> = {\n model: this.model,\n max_tokens: this.maxTokens,\n temperature: this.temperature,\n system: systemPrompt,\n messages,\n stream: true,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': this.anthropicVersion,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Anthropic API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n if (!res.body) {\n throw new Error('Anthropic streaming response has no readable body');\n }\n\n let text = '';\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n if (!raw) continue;\n\n let evt: {\n type?: string;\n delta?: { type?: string; text?: string };\n usage?: { output_tokens?: number };\n message?: { usage?: { input_tokens?: number } };\n };\n try {\n evt = JSON.parse(raw);\n } catch {\n continue;\n }\n\n if (evt.type === 'content_block_delta' && evt.delta?.type === 'text_delta') {\n const delta = evt.delta.text;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n } else if (evt.type === 'message_start' && evt.message?.usage?.input_tokens !== undefined) {\n promptTokens = evt.message.usage.input_tokens;\n } else if (evt.type === 'message_delta' && evt.usage?.output_tokens !== undefined) {\n completionTokens = evt.usage.output_tokens;\n }\n }\n\n return {\n text,\n usage:\n promptTokens !== undefined || completionTokens !== undefined\n ? { promptTokens, completionTokens }\n : undefined,\n };\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { getMessageText } from '../../core/messages';\n\nexport interface CustomHttpAdapterOptions {\n url: string;\n name?: string;\n headers?: Record<string, string>;\n formatRequestBody?: (params: AiProviderGenerateParams) => unknown;\n parseResponse?: (json: unknown) => string;\n}\n\nexport class CustomHttpAdapter implements AiProviderAdapter {\n readonly name: string;\n private url: string;\n private headers?: Record<string, string>;\n private formatRequestBody: (params: AiProviderGenerateParams) => unknown;\n private parseResponse: (json: unknown) => string;\n\n constructor(options: CustomHttpAdapterOptions) {\n if (!options.url) {\n throw new Error('CustomHttpAdapter requires a url');\n }\n this.url = options.url;\n this.name = options.name || 'custom-http';\n this.headers = options.headers;\n\n // Default body formatter (OpenAI compatible or Ollama chat compatible)\n this.formatRequestBody =\n options.formatRequestBody ||\n ((params) => ({\n messages:\n params.messages && params.messages.length > 0\n ? [\n { role: 'system', content: params.systemPrompt },\n ...params.messages.map((m) => ({ role: m.role, content: getMessageText(m) })),\n ]\n : [\n { role: 'system', content: params.systemPrompt },\n { role: 'user', content: params.userPrompt },\n ],\n }));\n\n // Default response parser\n this.parseResponse =\n options.parseResponse ||\n ((json: unknown) => {\n if (!json || typeof json !== 'object') {\n throw new Error('Response is not a valid JSON object');\n }\n const obj = json as Record<string, unknown>;\n if (typeof obj.response === 'string') return obj.response; // Ollama generate\n if (typeof obj.text === 'string') return obj.text;\n const choices = obj.choices as Array<{ message?: { content?: string } }>;\n if (Array.isArray(choices) && choices[0]?.message?.content) {\n return choices[0].message.content; // OpenAI format\n }\n const message = obj.message as { content?: string };\n if (message && typeof message.content === 'string') {\n return message.content; // Ollama chat format\n }\n throw new Error('Unable to extract generated text from custom HTTP response');\n });\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const body = this.formatRequestBody(params);\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.headers,\n },\n body: JSON.stringify(body),\n signal: params.signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Custom HTTP adapter error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const json = await res.json();\n const text = this.parseResponse(json);\n\n return { text };\n }\n}\n"],"mappings":"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","names":["import_schema","import_schema","import_core","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/server/engine.ts","../../src/core/document-outline.ts","../../src/core/prompt-compiler.ts","../../src/core/messages.ts","../../src/core/normalizer.ts","../../src/server/tools/helpers.ts","../../src/server/tools/read-tools.ts","../../src/server/tools/write-tools.ts","../../src/server/tools/index.ts","../../src/server/agent.ts","../../src/server/handler.ts","../../src/server/adapters/stream-utils.ts","../../src/server/adapters/gemini.ts","../../src/server/adapters/openai.ts","../../src/server/adapters/anthropic.ts","../../src/server/adapters/custom.ts"],"sourcesContent":["export * from './engine';\nexport * from './agent';\nexport * from './tools';\nexport * from './handler';\nexport * from './adapters';\n","import { PageDocument, Node, DocumentMetadataSchema, DocumentMetadata } from '@kubuild/schema';\nimport type {\n KubuildAiEngineOptions,\n AiGeneratePageRequest,\n AiGenerateSectionRequest,\n AiRefactorNodeRequest,\n AiChatRequest,\n AiChatResponse,\n AiChatMessage,\n AiGenerateResponse,\n AiCompiledComponentSpec,\n AiStreamEvent,\n PagePlan,\n PlannedSection,\n AiPlanPageRequest,\n} from '../types';\nimport {\n compileComponentCatalog,\n buildSystemPrompt,\n buildJsonSchemaForMode,\n} from '../core/prompt-compiler';\nimport { getMessageText } from '../core/messages';\nimport {\n extractJsonFromResponse,\n normalizeAndValidatePageDocument,\n normalizeAndValidateSectionNode,\n normalizeAndValidateRefactoredNode,\n} from '../core/normalizer'; \n\nexport class KubuildAiEngine {\n private options: KubuildAiEngineOptions;\n private catalog: AiCompiledComponentSpec[];\n\n constructor(options: KubuildAiEngineOptions) {\n if (!options.adapter) {\n throw new Error('KubuildAiEngine requires an adapter instance');\n }\n this.options = options;\n this.catalog = compileComponentCatalog(options.registry);\n }\n\n get adapterName(): string {\n return this.options.adapter.name;\n }\n\n refreshCatalog(): void {\n this.catalog = compileComponentCatalog(this.options.registry);\n }\n\n private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: unknown): void {\n if (this.options.logger) {\n this.options.logger(level, message, meta);\n } else if (this.options.debug) {\n const ts = new Date().toISOString();\n console.log(`[KUBUILD-AI ${level.toUpperCase()}] [${ts}] ${message}`, meta !== undefined ? meta : '');\n }\n }\n\n async generatePage(\n request: AiGeneratePageRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<PageDocument>> {\n let rawText = '';\n try {\n this.log('info', `Generating full page for prompt: \"${request.prompt}\"`);\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'full-page',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n let userPrompt = `User Request: ${request.prompt}`;\n if (request.tone) userPrompt += `\\nTone: ${request.tone}`;\n if (request.locale) userPrompt += `\\nLanguage/Locale: ${request.locale}`;\n if (request.conversationHistory && request.conversationHistory.length > 0) {\n const chatContext = request.conversationHistory\n .map((m) => `${m.role.toUpperCase()}: ${getMessageText(m)}`)\n .join('\\n');\n userPrompt += `\\n\\nPrior Conversation Discussion Context:\\n${chatContext}`;\n }\n\n const jsonSchema = buildJsonSchemaForMode('full-page');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n this.log('debug', 'Raw model response (generatePage)', result.text);\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const document = normalizeAndValidatePageDocument(\n rawJson,\n this.options.securityLimits,\n );\n\n // Merge user requested metadata if given\n if (request.metadata) {\n document.metadata = DocumentMetadataSchema.parse({\n ...document.metadata,\n ...request.metadata,\n });\n }\n\n this.log(\n 'info',\n `Full page successfully generated: \"${document.metadata?.title || 'Untitled'}\" (${document.document.children?.length || 0} sections)`,\n );\n\n return {\n success: true,\n data: document,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Generation failed: ${message}`);\n return {\n success: false,\n error: {\n code: 'GENERATION_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n async generateSection(\n request: AiGenerateSectionRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<Node>> {\n let rawText = '';\n try {\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'section',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n let userPrompt = `Generate a single section node for: ${request.prompt}`;\n if (request.targetSectionType) {\n userPrompt += `\\nTarget Section Purpose: ${request.targetSectionType}`;\n }\n if (request.parentContext) {\n userPrompt += `\\nSurrounding Page Context: ${request.parentContext}`;\n }\n\n const jsonSchema = buildJsonSchemaForMode('section');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n this.log('debug', 'Raw model response (generateSection)', result.text);\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const sectionNode = normalizeAndValidateSectionNode(\n rawJson,\n this.options.securityLimits,\n );\n\n return {\n success: true,\n data: sectionNode,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n error: {\n code: 'SECTION_GENERATION_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n async refactorNode(\n request: AiRefactorNodeRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<Node>> {\n let rawText = '';\n try {\n const systemPrompt = buildSystemPrompt({\n catalog: this.catalog,\n mode: 'refactor',\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n });\n\n const userPrompt = `Instruction: ${request.instruction}\\n\\nCurrent Node:\\n${JSON.stringify(request.node, null, 2)}`;\n const jsonSchema = buildJsonSchemaForMode('refactor');\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n jsonSchema,\n signal: context?.signal,\n });\n\n rawText = result.text;\n const rawJson = extractJsonFromResponse(rawText);\n const updatedNode = normalizeAndValidateRefactoredNode(\n rawJson,\n request.node,\n this.options.securityLimits,\n );\n\n return {\n success: true,\n data: updatedNode,\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n error: {\n code: 'REFACTOR_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n private buildPlanPrompts(request: AiPlanPageRequest): { systemPrompt: string; userPrompt: string } {\n let sectionGuidance =\n 'Plan between 4 to 6 cohesive, essential sections (e.g., hero, features, testimonials, pricing, cta, footer) that fulfill the request thoroughly.';\n if (typeof request.sectionCount === 'number') {\n sectionGuidance = `Plan exactly ${request.sectionCount} cohesive sections that fulfill the request.`;\n } else if (request.sectionCount?.min || request.sectionCount?.max) {\n const min = request.sectionCount.min ?? 3;\n const max = request.sectionCount.max ?? 8;\n sectionGuidance = `Plan between ${min} and ${max} cohesive sections that fulfill the request.`;\n } else {\n sectionGuidance += ' If the user request mentions a specific number or list of sections, respect the user request.';\n }\n\n const planSystemPrompt = `\nYou are a web architect for the KUBUILD page builder.\nGiven the user's prompt, plan the website structure. Output pure JSON (no markdown fences, no explanatory text):\n{\n \"title\": \"<Page Title>\",\n \"description\": \"<Page Description>\",\n \"pageStyles\": {\n \"base\": {\n \"backgroundColor\": \"#ffffff\",\n \"fontFamily\": \"Inter, system-ui, sans-serif\",\n \"color\": \"#111827\",\n \"minHeight\": \"100vh\"\n }\n },\n \"sections\": [\n {\n \"type\": \"<hero|features|pricing|testimonials|cta|contact|footer>\",\n \"title\": \"<Brief title>\",\n \"prompt\": \"<Detailed prompt for generating this specific section with components, layout, and content>\"\n }\n ]\n}\n${sectionGuidance}\n`;\n\n let planUserPrompt = `User Request: ${request.prompt}`;\n if (request.stylePreference) {\n planUserPrompt += `\\nStyle Preference: ${request.stylePreference}`;\n }\n if (request.tone) planUserPrompt += `\\nTone: ${request.tone}`;\n if (request.locale) planUserPrompt += `\\nLocale: ${request.locale}`;\n if (request.conversationHistory && request.conversationHistory.length > 0) {\n const chatContext = request.conversationHistory\n .map((m) => `${m.role.toUpperCase()}: ${getMessageText(m)}`)\n .join('\\n');\n planUserPrompt += `\\n\\nPrior Conversation Discussion Context:\\n${chatContext}`;\n }\n\n return { systemPrompt: planSystemPrompt, userPrompt: planUserPrompt };\n }\n\n async planPage(\n request: AiPlanPageRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<PagePlan>> {\n let rawText = '';\n try {\n const { systemPrompt, userPrompt } = this.buildPlanPrompts(request);\n this.log('info', `Planning website layout for: \"${request.prompt}\"`);\n\n const planResult = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n signal: context?.signal,\n });\n\n rawText = planResult.text;\n const plan = extractJsonFromResponse(rawText) as PagePlan;\n\n return {\n success: true,\n data: plan,\n usage: planResult.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('warn', 'Failed to generate plan JSON, using fallback plan', message);\n const fallbackPlan: PagePlan = {\n title: 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n sections: [\n { type: 'hero', title: 'Hero Banner', prompt: `Hero section for: ${request.prompt}` },\n { type: 'features', title: 'Key Features', prompt: `Features grid for: ${request.prompt}` },\n { type: 'testimonials', title: 'Testimonials', prompt: `Social proof and customer reviews for: ${request.prompt}` },\n { type: 'cta', title: 'Call To Action', prompt: `Call to action section for: ${request.prompt}` },\n { type: 'footer', title: 'Footer', prompt: `Footer navigation and copyright for: ${request.prompt}` },\n ],\n };\n return {\n success: true,\n data: fallbackPlan,\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n /**\n * Progressive Section Streaming Generator.\n * Emits structured SSE events: status -> metadata -> section (one by one) -> complete.\n */\n async *streamPage(\n request: AiGeneratePageRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n try {\n this.log('info', `[SSE] Starting streamPage for prompt: \"${request.prompt}\"`);\n\n yield {\n type: 'status',\n message: 'Analyzing requirements and planning page sections...',\n };\n\n let plan: PagePlan;\n\n if (request.plan && Array.isArray(request.plan.sections) && request.plan.sections.length > 0) {\n plan = request.plan;\n this.log('info', `[SSE] Using approved pre-planned structure with ${plan.sections?.length ?? 0} sections`);\n } else {\n // 1. Plan page sections\n const { systemPrompt: planSystemPrompt, userPrompt: planUserPrompt } = this.buildPlanPrompts(request);\n\n this.log('info', '[SSE] Generating website layout plan...');\n const planResult = await this.options.adapter.generate({\n systemPrompt: planSystemPrompt,\n userPrompt: planUserPrompt,\n signal: context?.signal,\n });\n\n this.log('debug', '[SSE] Raw plan response from model', planResult.text);\n\n try {\n plan = extractJsonFromResponse(planResult.text) as PagePlan;\n this.log('debug', '[SSE] Parsed plan successfully', plan);\n } catch (parseErr) {\n this.log('warn', '[SSE] Failed to parse plan JSON, using fallback plan', parseErr);\n // Fallback default plan if JSON parse failed\n plan = {\n title: 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n sections: [\n { type: 'hero', title: 'Hero Banner', prompt: `Hero section for: ${request.prompt}` },\n { type: 'features', title: 'Key Features', prompt: `Features grid for: ${request.prompt}` },\n { type: 'testimonials', title: 'Testimonials', prompt: `Social proof for: ${request.prompt}` },\n { type: 'cta', title: 'Call To Action', prompt: `Call to action section for: ${request.prompt}` },\n { type: 'footer', title: 'Footer', prompt: `Footer for: ${request.prompt}` },\n ],\n };\n }\n }\n\n const sectionsToGenerate = Array.isArray(plan.sections) && plan.sections.length > 0\n ? plan.sections\n : [\n { type: 'hero', title: 'Hero Section', prompt: `Hero banner for: ${request.prompt}` },\n { type: 'features', title: 'Features', prompt: `Features grid for: ${request.prompt}` },\n { type: 'testimonials', title: 'Testimonials', prompt: `Social proof for: ${request.prompt}` },\n { type: 'cta', title: 'Call To Action', prompt: `CTA section for: ${request.prompt}` },\n { type: 'footer', title: 'Footer', prompt: `Footer section for: ${request.prompt}` },\n ];\n\n const metadata: DocumentMetadata = DocumentMetadataSchema.parse({\n title: plan.title || 'AI Generated Page',\n description: plan.description || 'Generated by KUBUILD AI',\n author: 'KUBUILD AI',\n tags: ['ai-generated', 'progressive-stream'],\n category: 'landing',\n version: '1.0.0',\n ...(request.metadata || {}),\n });\n\n const rootPageNode: Node = {\n id: 'root-page',\n type: 'page',\n styles: plan.pageStyles || {\n base: {\n backgroundColor: '#ffffff',\n fontFamily: 'Inter, system-ui, sans-serif',\n color: '#111827',\n minHeight: '100vh',\n },\n },\n children: [],\n };\n\n // 2. Emit initial metadata so canvas can render initial empty page immediately!\n this.log('info', `[SSE] Emitting metadata: \"${metadata.title}\"`);\n yield {\n type: 'metadata',\n metadata,\n rootPageNode,\n };\n\n this.log(\n 'info',\n `[SSE] Plan ready with ${sectionsToGenerate.length} sections: ${sectionsToGenerate.map((s) => s.title).join(', ')}`,\n );\n yield {\n type: 'status',\n message: `Plan ready with ${sectionsToGenerate.length} sections: ${sectionsToGenerate.map((s) => s.title).join(', ')}`,\n };\n\n // 3. Sequentially generate each section and stream it!\n const completedSections: Node[] = [];\n const total = sectionsToGenerate.length;\n\n for (let i = 0; i < total; i++) {\n if (context?.signal?.aborted) {\n this.log('warn', '[SSE] Streaming aborted by client signal');\n throw new Error('Streaming aborted by client');\n }\n\n const plannedSec = sectionsToGenerate[i];\n this.log(\n 'info',\n `[SSE] Generating section ${i + 1}/${total} [${plannedSec.type}]: \"${plannedSec.title}\"`,\n );\n yield {\n type: 'status',\n message: `Generating section ${i + 1}/${total} (${plannedSec.title})...`,\n };\n\n const secRes = await this.generateSection(\n {\n prompt: plannedSec.prompt,\n stylePreference: request.stylePreference,\n targetSectionType: plannedSec.type,\n parentContext: `Website: ${plan.title}. Previous sections: ${sectionsToGenerate.slice(0, i).map((s) => s.title).join(', ')}`,\n },\n { signal: context?.signal },\n );\n\n if (secRes.success && secRes.data) {\n this.log(\n 'info',\n `[SSE] Section ${i + 1}/${total} generated successfully: [${secRes.data.id || secRes.data.type}]`,\n );\n completedSections.push(secRes.data);\n yield {\n type: 'section',\n index: i,\n total,\n section: secRes.data,\n };\n } else {\n this.log('error', `[SSE] Section ${i + 1}/${total} failed`, secRes.error?.message);\n }\n }\n\n if (completedSections.length === 0) {\n this.log('error', '[SSE] All sections failed to generate.');\n yield {\n type: 'error',\n error: {\n code: 'STREAM_GENERATION_FAILED',\n message: 'All sections failed to generate. Please check server logs or retry.',\n },\n };\n return;\n }\n\n // 4. Assemble final document and emit complete event\n const finalDocument: PageDocument = {\n schema: 'stora.page',\n version: '1.0.0',\n metadata,\n document: {\n ...rootPageNode,\n children: completedSections,\n } as PageDocument['document'],\n };\n\n this.log(\n 'info',\n `[SSE] All ${completedSections.length} sections generated. Emitting complete event.`,\n );\n yield {\n type: 'complete',\n document: finalDocument,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[SSE] Streaming failed: ${message}`);\n yield {\n type: 'error',\n error: {\n code: 'STREAM_ERROR',\n message,\n },\n };\n }\n }\n\n /**\n * Builds the system/user prompt pair shared by `chat()` and `chatStream()` — the exact\n * same document/selection grounding is used regardless of whether the response is\n * streamed token-by-token or returned as a single request/response (STORA-515).\n */\n private buildChatPrompt(request: AiChatRequest): { systemPrompt: string; userPrompt: string } {\n let systemPrompt = `You are the KUBUILD AI Assistant — an expert web designer, developer, and page architecture consultant.\nYour role is to assist users with creating, designing, refining, and understanding web pages built with the KUBUILD builder.\nAnswer questions directly, concisely, and helpfully using friendly professional tone and markdown formatting.\n\n### Available KUBUILD Components:\n${this.catalog.map((c) => `- **${c.type}** (${c.category}): ${c.label}${c.description ? ` — ${c.description}` : ''}`).join('\\n')}\n`;\n\n if (this.options.systemPromptPrefix) {\n systemPrompt = `${this.options.systemPromptPrefix}\\n\\n${systemPrompt}`;\n }\n\n if (request.systemPrompt) {\n systemPrompt += `\\nAdditional Context:\\n${request.systemPrompt}`;\n }\n\n if (request.currentDocument) {\n const doc = request.currentDocument;\n const sections = doc.document?.children || [];\n const sectionSummary = sections\n .map((s, idx) => `Section ${idx + 1}: id=\"${s.id}\", type=\"${s.type}\", title=\"${(s.props?.title as string) || 'untitled'}\", childrenCount=${s.children?.length || 0}`)\n .join('\\n');\n\n systemPrompt += `\\n### Current Page in Builder Canvas:\n- Title: ${doc.metadata?.title || 'Untitled Page'}\n- Description: ${doc.metadata?.description || 'N/A'}\n- Total Sections: ${sections.length}\n- Sections Summary:\n${sectionSummary || '(Canvas is currently empty)'}\n`;\n }\n\n if (request.selectedNodeId) {\n systemPrompt += `\\nCurrently Selected Component Node ID: \"${request.selectedNodeId}\"`;\n }\n\n // Extract last user message\n const lastUserMsg = [...request.messages].reverse().find((m) => m.role === 'user');\n const userPrompt = lastUserMsg ? getMessageText(lastUserMsg) || 'Hello' : 'Hello';\n\n return { systemPrompt, userPrompt };\n }\n\n /**\n * Conversational Assistant / Q&A.\n * Can discuss web design, explain KUBUILD components, review current page,\n * suggest improvements, or recommend copywriting.\n *\n * Single request/response — unchanged since before STORA-515. See `chatStream()` for\n * the token-level streaming variant.\n */\n async chat(\n request: AiChatRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiGenerateResponse<AiChatResponse>> {\n let rawText = '';\n try {\n if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {\n return {\n success: false,\n error: {\n code: 'INVALID_CHAT_REQUEST',\n message: '\"messages\" array is required and must not be empty',\n },\n };\n }\n\n this.log('info', `Processing chat turn with ${request.messages.length} messages`);\n\n const { systemPrompt, userPrompt } = this.buildChatPrompt(request);\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n\n rawText = result.text.trim();\n\n const assistantMessage: AiChatMessage = {\n role: 'assistant',\n content: rawText,\n timestamp: Date.now(),\n };\n\n return {\n success: true,\n data: {\n message: assistantMessage,\n },\n usage: result.usage,\n rawModelResponse: rawText,\n };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Chat failed: ${message}`);\n return {\n success: false,\n error: {\n code: 'CHAT_ERROR',\n message,\n },\n rawModelResponse: rawText || undefined,\n };\n }\n }\n\n /**\n * Token-level streaming variant of `chat()` (STORA-515). Emits `chat-chunk` events as\n * partial text arrives, then a terminal `chat-complete` event with the fully assembled\n * assistant message — the same `AsyncIterable<AiStreamEvent>` mechanism `streamPage`\n * already uses, so it can be piped over SSE by `createAiHandler`/consumed by\n * `KubuildAiClient` with no separate transport.\n *\n * When the configured adapter does not implement `generateStream` (e.g. the generic\n * custom/HTTP adapter), this falls back to a single non-streaming `generate()` call and\n * emits the entire response as one `chat-chunk`, so callers never see an error just\n * because the underlying provider can't stream — only a less granular update cadence.\n */\n async *chatStream(\n request: AiChatRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n try {\n if (!request.messages || !Array.isArray(request.messages) || request.messages.length === 0) {\n yield {\n type: 'error',\n error: {\n code: 'INVALID_CHAT_REQUEST',\n message: '\"messages\" array is required and must not be empty',\n },\n };\n return;\n }\n\n this.log(\n 'info',\n `[SSE] Starting chatStream with ${request.messages.length} messages (adapter: ${this.options.adapter.name})`,\n );\n\n const { systemPrompt, userPrompt } = this.buildChatPrompt(request);\n\n let accumulated = '';\n let usage: AiGenerateResponse<AiChatResponse>['usage'];\n\n if (typeof this.options.adapter.generateStream === 'function') {\n const generator = this.options.adapter.generateStream({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n\n while (true) {\n const { value, done } = await generator.next();\n if (done) {\n usage = value?.usage;\n break;\n }\n accumulated += value;\n yield { type: 'chat-chunk', delta: value, content: accumulated };\n }\n } else {\n this.log(\n 'debug',\n `Adapter \"${this.options.adapter.name}\" has no generateStream; falling back to non-streaming chat`,\n );\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt,\n messages: request.messages,\n signal: context?.signal,\n });\n accumulated = result.text;\n usage = result.usage;\n yield { type: 'chat-chunk', delta: accumulated, content: accumulated };\n }\n\n const assistantMessage: AiChatMessage = {\n role: 'assistant',\n content: accumulated.trim(),\n timestamp: Date.now(),\n };\n\n this.log('info', '[SSE] Chat stream completed', usage);\n yield { type: 'chat-complete', message: assistantMessage };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[SSE] Chat streaming failed: ${message}`);\n yield {\n type: 'error',\n error: {\n code: 'CHAT_STREAM_ERROR',\n message,\n },\n };\n }\n }\n}\n","import type { Node, PageDocument } from '@kubuild/schema';\n\n/**\n * Props that carry user-visible text, ordered by how well they identify a node. Used to\n * label outline rows so the model can say \"the CTA button\" instead of guessing from ids.\n * Matches the prop names the component definitions in `@kubuild/components` actually use\n * (`label` on button/checkbox/file-upload, `text`/`content` on text nodes, `title` on\n * section-ish components, `src`/`alt` on media).\n */\nconst LABEL_PROPS = ['text', 'label', 'title', 'heading', 'content', 'placeholder', 'alt', 'src'];\n\nconst DEFAULT_LABEL_MAX = 60;\n\n/** Trims a value to a single short line — outlines must stay cheap in tokens. */\nfunction truncate(value: string, max = DEFAULT_LABEL_MAX): string {\n const oneLine = value.replace(/\\s+/g, ' ').trim();\n return oneLine.length > max ? `${oneLine.slice(0, max - 1)}…` : oneLine;\n}\n\n/**\n * Best-effort human label for a node, derived from its text-carrying props. Returns an\n * empty string when the node has none (layout containers, mostly).\n */\nexport function getNodeLabel(node: Node, max = DEFAULT_LABEL_MAX): string {\n const props = node.props ?? {};\n for (const key of LABEL_PROPS) {\n const value = props[key];\n if (typeof value === 'string' && value.trim()) {\n return truncate(value, max);\n }\n }\n return '';\n}\n\nexport interface DocumentOutlineOptions {\n /** How deep to walk before collapsing into a `(+N nested)` marker. Default: 3. */\n maxDepth?: number;\n /**\n * When set, the branch containing this node is always expanded in full regardless of\n * `maxDepth`, and the node itself is marked with `← SELECTED`. This is what makes\n * \"user selected a component on the canvas\" legible to the model.\n */\n focusNodeId?: string;\n /** Hard ceiling on emitted rows, so a huge page can't blow up the prompt. Default: 200. */\n maxNodes?: number;\n}\n\nfunction isOnPathTo(node: Node, targetId: string): boolean {\n if (node.id === targetId) return true;\n return (node.children ?? []).some((child) => isOnPathTo(child, targetId));\n}\n\n/**\n * Renders a compact, indented outline of a node tree (STORA-530).\n *\n * This is the agent's *default* view of the document: one line per node with id, type,\n * label and child count — never full props/styles. Detail is fetched on demand via the\n * `read_node` tool, which keeps per-step prompt cost roughly constant no matter how big\n * the page is. `engine.buildChatPrompt`'s depth-1 section summary can't do this: nested\n * nodes were invisible to the model, so it could never target them.\n */\nexport function summarizeNodeTree(root: Node, options: DocumentOutlineOptions = {}): string {\n const { maxDepth = 3, focusNodeId, maxNodes = 200 } = options;\n const lines: string[] = [];\n let emitted = 0;\n let truncated = false;\n\n const walk = (node: Node, depth: number): void => {\n if (emitted >= maxNodes) {\n truncated = true;\n return;\n }\n\n const indent = ' '.repeat(depth);\n const label = getNodeLabel(node);\n const children = node.children ?? [];\n const parts = [`${indent}- #${node.id} (${node.type})`];\n if (label) parts.push(`\"${label}\"`);\n if (children.length > 0) parts.push(`[${children.length} children]`);\n if (focusNodeId && node.id === focusNodeId) parts.push('← SELECTED');\n lines.push(parts.join(' '));\n emitted++;\n\n if (children.length === 0) return;\n\n // The focused branch stays fully expanded even past maxDepth — the model needs to see\n // what it's being asked to edit, and its siblings, to make a surgical change.\n const onFocusPath = Boolean(focusNodeId) && isOnPathTo(node, focusNodeId!);\n if (depth + 1 > maxDepth && !onFocusPath) {\n lines.push(`${indent} (+${countDescendants(node)} nested nodes — use read_node to expand)`);\n return;\n }\n\n for (const child of children) {\n walk(child, depth + 1);\n }\n };\n\n walk(root, 0);\n\n if (truncated) {\n lines.push(` (outline truncated at ${maxNodes} nodes — use find_nodes to locate specifics)`);\n }\n\n return lines.join('\\n');\n}\n\n/** Total number of descendants below a node (not counting the node itself). */\nexport function countDescendants(node: Node): number {\n return (node.children ?? []).reduce((total, child) => total + 1 + countDescendants(child), 0);\n}\n\n/** Outline of a whole `PageDocument`, prefixed with its metadata. */\nexport function summarizeDocument(\n document: PageDocument,\n options: DocumentOutlineOptions = {},\n): string {\n const header = [\n `Title: ${document.metadata?.title || 'Untitled Page'}`,\n `Description: ${document.metadata?.description || 'N/A'}`,\n ].join('\\n');\n return `${header}\\n\\nPage outline:\\n${summarizeNodeTree(document.document, options)}`;\n}\n\nexport interface SelectionContext {\n node: Node;\n /** Root-first chain of ancestors, excluding the node itself. */\n ancestors: Node[];\n /** The node's siblings, in document order, including the node itself. */\n siblings: Node[];\n index: number;\n parentId: string | null;\n}\n\n/**\n * Resolves everything the agent needs to know about the canvas selection (STORA-530).\n *\n * Sending only `selectedNodeId` — what `engine.buildChatPrompt` does today — tells the\n * model an id but not what the node *is*, what it lives inside, or what sits next to it,\n * so it can't judge whether an instruction like \"make this wider\" belongs on the node or\n * on its parent container. Returns `null` when the id isn't in the tree.\n */\nexport function buildSelectionContext(root: Node, nodeId: string): SelectionContext | null {\n const ancestors: Node[] = [];\n\n const walk = (node: Node, parent: Node | null, index: number): SelectionContext | null => {\n if (node.id === nodeId) {\n return {\n node,\n ancestors: [...ancestors],\n siblings: parent ? (parent.children ?? []) : [node],\n index,\n parentId: parent?.id ?? null,\n };\n }\n ancestors.push(node);\n const children = node.children ?? [];\n for (let i = 0; i < children.length; i++) {\n const found = walk(children[i], node, i);\n if (found) return found;\n }\n ancestors.pop();\n return null;\n };\n\n return walk(root, null, 0);\n}\n\n/**\n * Depth-limits a node before it is serialized into a prompt. A selected section can carry\n * hundreds of descendants; dumping all of them would defeat the point of the outline.\n * Children below `maxDepth` are replaced by a marker node telling the model to call\n * `read_node` if it needs them.\n */\nexport function pruneNodeForPrompt(node: Node, maxDepth = 2, depth = 0): Node {\n const children = node.children ?? [];\n if (children.length === 0) return node;\n\n if (depth >= maxDepth) {\n return {\n ...node,\n children: [\n {\n id: `${node.id}__collapsed`,\n type: '__collapsed__',\n props: {\n note: `${countDescendants(node)} nested nodes omitted — call read_node on #${node.id} with includeChildren to expand`,\n },\n },\n ],\n };\n }\n\n return {\n ...node,\n children: children.map((child) => pruneNodeForPrompt(child, maxDepth, depth + 1)),\n };\n}\n\n/** Renders a `SelectionContext` as the prompt block describing the current selection. */\nexport function formatSelectionContext(context: SelectionContext): string {\n const path = context.ancestors.map((a) => `#${a.id}(${a.type})`).join(' > ');\n const siblings = context.siblings\n .map((sibling, i) => {\n const marker = sibling.id === context.node.id ? ' ← selected' : '';\n const label = getNodeLabel(sibling);\n return ` [${i}] #${sibling.id} (${sibling.type})${label ? ` \"${label}\"` : ''}${marker}`;\n })\n .join('\\n');\n\n return [\n '### Currently Selected Component',\n `Node: #${context.node.id} (${context.node.type})`,\n `Parent: ${context.parentId ? `#${context.parentId}` : '(root)'} — position ${context.index}`,\n path ? `Path: ${path}` : '',\n 'Full node JSON:',\n '```json',\n JSON.stringify(pruneNodeForPrompt(context.node), null, 2),\n '```',\n 'Siblings:',\n siblings,\n 'When the user says \"this\", \"ini\", \"komponen ini\" or similar, they mean the selected node above.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n","import type { PageDocument } from '@kubuild/schema';\nimport type {\n AiCompiledComponentSpec,\n AiCompiledComponentProp,\n ComponentRegistryLike,\n ComponentDefinitionLike,\n AiGenerationMode,\n} from '../types';\nimport {\n buildSelectionContext,\n formatSelectionContext,\n summarizeDocument,\n} from './document-outline';\n\nexport function compileComponentCatalog(\n registry?: ComponentRegistryLike,\n): AiCompiledComponentSpec[] {\n if (!registry) return [];\n\n const definitions = registry.list();\n return definitions.map((def: ComponentDefinitionLike) => {\n const props: AiCompiledComponentProp[] = [];\n\n if (def.propFields && Array.isArray(def.propFields)) {\n for (const field of def.propFields) {\n props.push({\n name: field.name,\n type: field.type || 'string',\n defaultValue: field.defaultValue,\n options: field.options?.map((o) => o.value),\n description: field.description,\n });\n }\n }\n\n return {\n type: def.type,\n label: def.label || def.type,\n category: def.category || 'custom',\n description: def.description,\n acceptsChildren: def.acceptsChildren ?? false,\n allowedChildren: def.allowedChildren,\n disallowedParents: def.disallowedParents,\n defaultProps: def.defaultProps,\n props: props.length > 0 ? props : undefined,\n };\n });\n}\n\nexport function buildSystemPrompt(options: {\n catalog: AiCompiledComponentSpec[];\n mode: AiGenerationMode;\n prefix?: string;\n stylePreference?: string;\n}): string {\n const { catalog, mode, prefix, stylePreference } = options;\n\n const catalogSummary = catalog\n .map((c) => {\n let desc = `- **${c.type}** (${c.category}): ${c.label}`;\n if (c.description) desc += ` - ${c.description}`;\n desc += ` | acceptsChildren: ${c.acceptsChildren}`;\n if (c.allowedChildren && c.allowedChildren.length > 0) {\n desc += ` | allowedChildren: [${c.allowedChildren.join(', ')}]`;\n }\n if (c.props && c.props.length > 0) {\n const propList = c.props\n .map((p) => {\n let pStr = `${p.name} (${p.type})`;\n if (p.options) pStr += `[${p.options.map(String).join('|')}]`;\n return pStr;\n })\n .join(', ');\n desc += ` | props: { ${propList} }`;\n }\n return desc;\n })\n .join('\\n');\n\n let modeInstructions = '';\n if (mode === 'full-page') {\n modeInstructions = `\nYou must generate a complete, valid KUBUILD PageDocument JSON with this exact structure:\n{\n \"schema\": \"stora.page\",\n \"version\": \"1.0.0\",\n \"metadata\": {\n \"title\": \"<Page Title>\",\n \"description\": \"<Page Description>\",\n \"tags\": [\"<tag1>\", \"<tag2>\"],\n \"category\": \"<category>\"\n },\n \"document\": {\n \"id\": \"root-page\",\n \"type\": \"page\",\n \"styles\": {\n \"base\": {\n \"backgroundColor\": \"#ffffff\",\n \"fontFamily\": \"Inter, system-ui, sans-serif\",\n \"color\": \"#111827\",\n \"minHeight\": \"100vh\"\n }\n },\n \"children\": [\n // Sections here...\n ]\n }\n}\n`;\n } else if (mode === 'section') {\n modeInstructions = `\nYou must generate a single valid KUBUILD section Node JSON with this structure:\n{\n \"id\": \"section_<unique_suffix>\",\n \"type\": \"section\",\n \"styles\": {\n \"base\": {\n \"paddingTop\": \"64px\",\n \"paddingBottom\": \"64px\",\n \"paddingLeft\": \"24px\",\n \"paddingRight\": \"24px\"\n }\n },\n \"children\": [\n // Container and child nodes...\n ]\n}\n`;\n } else if (mode === 'refactor') {\n modeInstructions = `\nYou must refactor the provided KUBUILD Node based on the user's instructions.\nReturn ONLY the updated Node JSON while maintaining structural integrity.\n`;\n }\n\n const styleGuide = stylePreference\n ? `\\nUser Style Preference: \"${stylePreference}\". Follow this visual aesthetic closely.`\n : '\\nStyle with modern, clean, high-conversion design patterns (accessible contrast, harmonious spacing, beautiful typography, subtle shadows/borders).';\n\n return `${prefix ? prefix + '\\n\\n' : ''}You are an expert web designer and KUBUILD architecture generator.\nKUBUILD is a component-driven visual website builder. Your job is to output pure, valid JSON (and NOTHING ELSE) matching the KUBUILD schema and the registered component definitions.\n\n### RULES & CONSTRAINTS:\n1. Output MUST be valid JSON only. No markdown fences, no explanatory text, no HTML tags outside html-embed.\n2. Only use component types listed in the Component Catalog below. Do NOT invent new component types.\n3. Obey \\`acceptsChildren\\` and \\`allowedChildren\\`:\n - Layout hierarchy: \\`page\\` -> \\`section\\` -> \\`container\\` or \\`columns\\` -> content components (\\`heading\\`, \\`paragraph\\`, \\`button\\`, \\`image\\`, \\`form\\`, etc.).\n - Leaf components (e.g. \\`button\\`, \\`input\\`, \\`heading\\`, \\`text\\`, \\`badge\\`) must have \\`acceptsChildren: false\\` and empty or omitted \\`children\\`.\n4. Every node MUST have a unique string \\`id\\` (e.g. \"hero-section\", \"hero-title\", \"cta-btn\").\n5. Responsive & Interactive State Styling:\n - Use the \\`styles\\` object with breakpoint keys: \\`base\\` (all viewports/desktop), and optionally \\`tablet\\` or \\`mobile\\`.\n - In \\`base\\`, \\`tablet\\`, and \\`mobile\\`, values MUST be CSS primitives (strings or numbers, e.g. \"backgroundColor\": \"#3b82f6\"). NEVER put nested objects or \":hover\" inside \"base\"!\n - For hover, active, or interactive pseudo-classes, use \\`styles.states\\` with pseudo-class keys (e.g. \\`\":hover\"\\`), like:\n \"styles\": {\n \"base\": { \"backgroundColor\": \"#3b82f6\", \"color\": \"#ffffff\" },\n \"states\": {\n \":hover\": { \"backgroundColor\": \"#2563eb\" }\n }\n }\n6. NEVER include dangerous scripts, \\`javascript:\\` URIs, or malicious payload attributes.\n${styleGuide}\n\n### OUTPUT SPECIFICATION:\n${modeInstructions}\n\n### REGISTERED COMPONENT CATALOG:\n${catalogSummary || '(Standard core components: page, section, container, columns, heading, paragraph, text, button, input, textarea, select, image, video, icon, badge, code-block)'}\n`;\n}\n\nexport function buildJsonSchemaForMode(mode: AiGenerationMode): Record<string, unknown> {\n const nodeSchema: Record<string, unknown> = {\n type: 'object',\n required: ['id', 'type'],\n properties: {\n id: { type: 'string' },\n type: { type: 'string' },\n props: { type: 'object' },\n styles: {\n type: 'object',\n properties: {\n base: { type: 'object' },\n tablet: { type: 'object' },\n mobile: { type: 'object' },\n states: { type: 'object' },\n },\n },\n children: {\n type: 'array',\n items: { $ref: '#' },\n },\n },\n };\n\n if (mode === 'full-page') {\n return {\n type: 'object',\n required: ['schema', 'version', 'document'],\n properties: {\n schema: { type: 'string', const: 'stora.page' },\n version: { type: 'string', const: '1.0.0' },\n metadata: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n description: { type: 'string' },\n tags: { type: 'array', items: { type: 'string' } },\n category: { type: 'string' },\n },\n },\n document: nodeSchema,\n },\n };\n }\n\n return nodeSchema;\n}\n\n\n/**\n * Renders the component catalog as the compact reference block shared by every prompt.\n * Extracted from `buildSystemPrompt` so the agent prompt (STORA-530) reuses the exact\n * same catalog rendering instead of drifting into a second format.\n */\nexport function formatComponentCatalog(catalog: AiCompiledComponentSpec[]): string {\n return catalog\n .map((c) => {\n let desc = `- **${c.type}** (${c.category}): ${c.label}`;\n if (c.description) desc += ` - ${c.description}`;\n desc += ` | acceptsChildren: ${c.acceptsChildren}`;\n if (c.allowedChildren && c.allowedChildren.length > 0) {\n desc += ` | allowedChildren: [${c.allowedChildren.join(', ')}]`;\n }\n if (c.props && c.props.length > 0) {\n const propList = c.props\n .map((p) => {\n let pStr = `${p.name} (${p.type})`;\n if (p.options) pStr += `[${p.options.map(String).join('|')}]`;\n return pStr;\n })\n .join(', ');\n desc += ` | props: { ${propList} }`;\n }\n return desc;\n })\n .join('\\n');\n}\n\nexport interface BuildAgentSystemPromptOptions {\n catalog: AiCompiledComponentSpec[];\n document: PageDocument;\n selectedNodeId?: string;\n prefix?: string;\n stylePreference?: string;\n /** Extra host/product context appended verbatim. */\n additionalContext?: string;\n}\n\nconst AGENT_INSTRUCTIONS = `You are the KUBUILD page-editing agent. You edit an existing page by calling tools — you never output page JSON directly.\n\n### HOW YOU WORK\n1. The page outline below is your map. It shows every node's id, type and label, but not its props or styles.\n2. To see a node's actual props/styles, call read_node. To locate nodes by type or text, call find_nodes. Never guess a node id — every id you pass must come from the outline or from a tool result.\n3. Make the change with the smallest tool that expresses it, then stop and summarize what you changed, in the user's language.\n\n### SURGICAL EDIT RULE (the most important rule)\nChange only what the user asked for.\n- Changing text/label/href/src -> update_node_props on that one node.\n- Changing color/spacing/size/alignment -> update_node_styles on that one node.\n- Adding something new -> insert_component (a single element) or insert_section (a whole new section).\n- replace_node is a last resort, only when a node's children genuinely must be restructured. Never use it to change a prop or a style.\n- Never rebuild a section, and never touch nodes the user did not ask about. If an instruction is ambiguous about scope, edit the narrowest node that satisfies it and say so in your summary.\n\n### DESTRUCTIVE ACTIONS\ndelete_node and replace_node destroy user content. Only call them when the user asked unambiguously (e.g. \"hapus section harga\"). If the request is broad or vague (\"bersihkan halaman ini\", \"hapus yang tidak perlu\"), do not call them — ask the user which nodes to remove instead.\n\n### STYLING RULES\n- styles values are CSS primitives (strings/numbers). Use breakpoint ('base' | 'desktop' | 'tablet' | 'mobile') for normal styling and state (':hover', ':focus', ':active') for interactive states. Never nest a pseudo-class inside a breakpoint layer.\n- Only use component types that exist in the catalog below, and respect acceptsChildren/allowedChildren.\n- Never emit scripts, javascript: URIs, or event-handler attributes.\n\n### WHEN A TOOL FAILS\nA tool result with \"ok\": false means your input was wrong (unknown node id, invalid type, disallowed nesting). Read the error, fix your arguments, and retry — do not repeat the identical call, and do not give up silently.`;\n\n/**\n * System prompt for agent mode (STORA-530).\n *\n * Deliberately different from `buildSystemPrompt`: the agent does NOT emit document JSON.\n * It reads the page through tools and edits through tools, so the prompt's job is to\n * establish (a) the outline as the shared map, (b) the selection as the default target,\n * and (c) the surgical-edit discipline — the whole point of the feature is that asking to\n * recolor one button must not regenerate its section.\n *\n * The catalog goes before the volatile per-turn context so the stable prefix stays\n * prompt-cacheable across the steps of a run.\n */\nexport function buildAgentSystemPrompt(options: BuildAgentSystemPromptOptions): string {\n const { catalog, document, selectedNodeId, prefix, stylePreference, additionalContext } = options;\n\n const selection = selectedNodeId\n ? buildSelectionContext(document.document, selectedNodeId)\n : null;\n\n const sections: string[] = [];\n\n if (prefix) sections.push(prefix);\n\n sections.push(AGENT_INSTRUCTIONS);\n\n sections.push(\n `### REGISTERED COMPONENT CATALOG\\n${\n formatComponentCatalog(catalog) ||\n '(Standard core components: page, section, container, columns, heading, paragraph, text, button, input, textarea, select, image, video, icon, badge, code-block)'\n }`,\n );\n\n sections.push(`### CURRENT PAGE\\n${summarizeDocument(document, { focusNodeId: selectedNodeId })}`);\n\n if (selection) {\n sections.push(formatSelectionContext(selection));\n } else if (selectedNodeId) {\n sections.push(\n `### Selection\\nThe editor reported node \"${selectedNodeId}\" as selected, but it is not present in the current page. Ignore it and ask the user what to target.`,\n );\n } else {\n sections.push(\n '### Selection\\nNo component is selected on the canvas. If the user says \"this\", ask which component they mean instead of guessing.',\n );\n }\n\n if (stylePreference) {\n sections.push(\n `### Style Preference\\n\"${stylePreference}\" — follow this aesthetic for anything you create or restyle.`,\n );\n }\n\n if (additionalContext) {\n sections.push(`### Additional Context\\n${additionalContext}`);\n }\n\n return sections.join('\\n\\n');\n}\n","import type { AiChatMessage, AiContentBlock, AiToolUseBlock, AiToolResultBlock } from '../types';\n\n/**\n * Flattens a message's content to plain text (STORA-530).\n *\n * `AiChatMessage.content` became `string | AiContentBlock[]` when tool calling landed;\n * every place that previously assumed a bare string (adapter message mapping, the chat\n * prompt's \"last user message\" lookup, chat UIs) goes through this helper instead of\n * re-implementing the narrowing. Tool-use/tool-result blocks contribute nothing to the\n * text rendering — they're transported separately by the adapters.\n */\nexport function getMessageText(message: Pick<AiChatMessage, 'content'>): string {\n if (typeof message.content === 'string') return message.content;\n return message.content\n .filter((block): block is Extract<AiContentBlock, { type: 'text' }> => block.type === 'text')\n .map((block) => block.text)\n .join('\\n');\n}\n\n/** All `tool_use` blocks carried by a message, in order. Empty for plain-text messages. */\nexport function getToolUseBlocks(message: Pick<AiChatMessage, 'content'>): AiToolUseBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is AiToolUseBlock => b.type === 'tool_use');\n}\n\n/** All `tool_result` blocks carried by a message, in order. */\nexport function getToolResultBlocks(message: Pick<AiChatMessage, 'content'>): AiToolResultBlock[] {\n if (typeof message.content === 'string') return [];\n return message.content.filter((b): b is AiToolResultBlock => b.type === 'tool_result');\n}\n\n/** True when the message carries any non-text block — i.e. adapters must map it structurally. */\nexport function hasStructuredContent(message: Pick<AiChatMessage, 'content'>): boolean {\n return typeof message.content !== 'string' && message.content.some((b) => b.type !== 'text');\n}\n","import {\n PageDocument,\n PageDocumentSchema,\n DocumentMetadata,\n DocumentMetadataSchema,\n Node,\n NodeSchema,\n CURRENT_SCHEMA_VERSION,\n SCHEMA_NAME,\n} from '@kubuild/schema';\nimport {\n validateDocument,\n validateDocumentSecurity,\n DocumentSecurityLimits,\n} from '@kubuild/core';\n\nexport function extractJsonFromResponse(raw: string): unknown {\n let cleaned = raw.trim();\n // Strip Markdown code blocks if present (```json ... ``` or ``` ...)\n if (cleaned.startsWith('```')) {\n const firstNewline = cleaned.indexOf('\\n');\n if (firstNewline !== -1) {\n cleaned = cleaned.slice(firstNewline + 1);\n }\n if (cleaned.endsWith('```')) {\n cleaned = cleaned.slice(0, cleaned.length - 3).trim();\n }\n }\n\n // Find the outermost JSON object bounds if there is extraneous text\n const firstBrace = cleaned.indexOf('{');\n const lastBrace = cleaned.lastIndexOf('}');\n if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {\n cleaned = cleaned.slice(firstBrace, lastBrace + 1);\n }\n\n try {\n return JSON.parse(cleaned);\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to parse AI response as JSON: ${msg}. Response was: ${raw.slice(0, 200)}...`);\n }\n}\n\nexport function normalizeStyles(rawStyles: unknown): Node['styles'] {\n if (!rawStyles || typeof rawStyles !== 'object' || Array.isArray(rawStyles)) {\n return undefined;\n }\n\n const raw = rawStyles as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n const states: Record<string, Record<string, unknown>> = {};\n\n // Existing states\n if (raw.states && typeof raw.states === 'object' && !Array.isArray(raw.states)) {\n for (const [stateKey, stateVal] of Object.entries(raw.states as Record<string, unknown>)) {\n if (stateVal && typeof stateVal === 'object' && !Array.isArray(stateVal)) {\n states[stateKey] = { ...(stateVal as Record<string, unknown>) };\n }\n }\n }\n\n const knownBreakpoints = ['base', 'desktop', 'tablet', 'mobile'];\n const hasBreakpoint = Object.keys(raw).some((k) => knownBreakpoints.includes(k));\n\n if (!hasBreakpoint) {\n // If AI output flat CSS properties without 'base' wrapper\n const baseStyles: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (key === 'states') continue;\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n } else if (typeof value !== 'object' || value === null) {\n baseStyles[key] = value;\n }\n }\n if (Object.keys(baseStyles).length > 0) {\n result.base = baseStyles;\n }\n } else {\n for (const bp of knownBreakpoints) {\n const bpVal = raw[bp];\n if (bpVal && typeof bpVal === 'object' && !Array.isArray(bpVal)) {\n const cleanBp: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(bpVal as Record<string, unknown>)) {\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n } else if (typeof value !== 'object' || value === null) {\n cleanBp[key] = value;\n }\n }\n if (Object.keys(cleanBp).length > 0) {\n result[bp] = cleanBp;\n }\n }\n }\n\n // Also extract any pseudo-classes at top level\n for (const [key, value] of Object.entries(raw)) {\n if (knownBreakpoints.includes(key) || key === 'states') continue;\n if (key.startsWith(':') || key === 'hover' || key === 'focus' || key === 'active') {\n const stateKey = key.startsWith(':') ? key : `:${key}`;\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n states[stateKey] = { ...(states[stateKey] || {}), ...(value as Record<string, unknown>) };\n }\n }\n }\n }\n\n // Clean and sanitize states: each state can only have primitives\n const cleanStates: Record<string, Record<string, unknown>> = {};\n for (const [stateKey, stateDef] of Object.entries(states)) {\n const cleanDef: Record<string, unknown> = {};\n for (const [propKey, propVal] of Object.entries(stateDef)) {\n if (typeof propVal !== 'object' || propVal === null) {\n cleanDef[propKey] = propVal;\n }\n }\n if (Object.keys(cleanDef).length > 0) {\n cleanStates[stateKey] = cleanDef;\n }\n }\n\n if (Object.keys(cleanStates).length > 0) {\n result.states = cleanStates;\n }\n\n return Object.keys(result).length > 0 ? (result as Node['styles']) : undefined;\n}\n\nexport function normalizeNodeTree(\n node: unknown,\n usedIds: Set<string> = new Set(),\n depth = 0,\n): Node {\n if (!node || typeof node !== 'object') {\n throw new Error(`Invalid node at depth ${depth}: must be an object`);\n }\n\n const raw = node as Record<string, unknown>;\n const type = typeof raw.type === 'string' && raw.type.trim() ? raw.type.trim() : 'container';\n\n // Ensure deterministic, unique ID\n let id = typeof raw.id === 'string' && raw.id.trim() ? raw.id.trim() : '';\n if (!id || usedIds.has(id)) {\n let counter = 1;\n let candidate = `${type}-${counter}`;\n while (usedIds.has(candidate)) {\n counter++;\n candidate = `${type}-${counter}`;\n }\n id = candidate;\n }\n usedIds.add(id);\n\n // Normalize props\n const props =\n raw.props && typeof raw.props === 'object' && !Array.isArray(raw.props)\n ? { ...(raw.props as Record<string, unknown>) }\n : {};\n\n // Fix common LLM prop quirks:\n // e.g. heading level passed as string \"1\" instead of number 1\n if (type === 'heading' && typeof props.level === 'string') {\n const parsedLevel = parseInt(props.level, 10);\n if (!isNaN(parsedLevel) && parsedLevel >= 1 && parsedLevel <= 6) {\n props.level = parsedLevel;\n }\n }\n\n // Normalize styles\n const styles = normalizeStyles(raw.styles);\n\n // Normalize children recursively\n let children: Node[] | undefined = undefined;\n if (Array.isArray(raw.children)) {\n children = raw.children\n .filter((c) => c && typeof c === 'object')\n .map((c) => normalizeNodeTree(c, usedIds, depth + 1));\n }\n\n return {\n id,\n type,\n props: Object.keys(props).length > 0 ? props : undefined,\n styles,\n children,\n };\n}\n\nexport function normalizeAndValidatePageDocument(\n rawJson: unknown,\n securityLimits?: DocumentSecurityLimits,\n): PageDocument {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const obj = rawJson as Record<string, unknown>;\n\n // Case 1: AI returned directly a page node instead of PageDocument\n let docObject: Record<string, unknown>;\n if (obj.type === 'page' && !obj.document) {\n docObject = {\n schema: SCHEMA_NAME,\n version: CURRENT_SCHEMA_VERSION,\n metadata: {\n title: (typeof obj.props === 'object' && obj.props !== null && (obj.props as Record<string, unknown>).title) || 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n },\n document: obj,\n };\n } else {\n docObject = {\n schema: SCHEMA_NAME,\n version: typeof obj.version === 'string' ? obj.version : CURRENT_SCHEMA_VERSION,\n metadata: typeof obj.metadata === 'object' && obj.metadata !== null\n ? obj.metadata\n : { title: 'AI Generated Page', description: 'Generated by KUBUILD AI' },\n document: obj.document || obj,\n };\n }\n\n // Normalize the node tree and ensure IDs\n const usedIds = new Set<string>();\n const normalizedRoot = normalizeNodeTree(docObject.document, usedIds);\n\n if (normalizedRoot.type !== 'page') {\n normalizedRoot.type = 'page';\n }\n\n const parsedMetadata = DocumentMetadataSchema.parse({\n title: 'AI Generated Page',\n description: 'Generated by KUBUILD AI',\n author: 'KUBUILD AI',\n tags: ['ai-generated'],\n category: 'general',\n version: '1.0.0',\n ...(typeof docObject.metadata === 'object' && docObject.metadata !== null\n ? (docObject.metadata as Record<string, unknown>)\n : {}),\n });\n\n const finalDocument: PageDocument = {\n schema: SCHEMA_NAME,\n version: CURRENT_SCHEMA_VERSION,\n metadata: parsedMetadata,\n document: normalizedRoot as PageDocument['document'],\n };\n\n // 1. Zod Schema parse\n const parsed = PageDocumentSchema.safeParse(finalDocument);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Document schema validation failed: ${issues}`);\n }\n\n // 2. Core document and security validation\n const validationResult = validateDocument(finalDocument, { securityLimits });\n if (!validationResult.valid) {\n const errorMsgs = validationResult.errors.map((e) => `${e.code}: ${e.message} (${e.path})`).join('; ');\n throw new Error(`Document validation failed: ${errorMsgs}`);\n }\n\n return parsed.data;\n}\n\nexport function normalizeAndValidateSectionNode(\n rawJson: unknown,\n securityLimits?: DocumentSecurityLimits,\n): Node {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const usedIds = new Set<string>();\n const normalized = normalizeNodeTree(rawJson, usedIds);\n\n if (normalized.type !== 'section') {\n // If AI wrapped it or returned another root, enforce section\n normalized.type = 'section';\n }\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Section node schema validation failed: ${issues}`);\n }\n\n // Security check\n const secCheck = validateDocumentSecurity({ document: normalized }, securityLimits);\n if (!secCheck.safe) {\n const issues = secCheck.errors.map((e) => `${e.code}: ${e.message}`).join('; ');\n throw new Error(`Section security check failed: ${issues}`);\n }\n\n return parsed.data;\n}\n\nexport function normalizeAndValidateRefactoredNode(\n rawJson: unknown,\n originalNode: Node,\n securityLimits?: DocumentSecurityLimits,\n): Node {\n if (!rawJson || typeof rawJson !== 'object') {\n throw new Error('AI output must be a JSON object');\n }\n\n const usedIds = new Set<string>();\n const normalized = normalizeNodeTree(rawJson, usedIds);\n\n // Preserve original ID and type if AI changed them accidentally\n normalized.id = originalNode.id;\n normalized.type = originalNode.type;\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n const issues = parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`Refactored node schema validation failed: ${issues}`);\n }\n\n const secCheck = validateDocumentSecurity({ document: normalized }, securityLimits);\n if (!secCheck.safe) {\n const issues = secCheck.errors.map((e) => `${e.code}: ${e.message}`).join('; ');\n throw new Error(`Refactored node security check failed: ${issues}`);\n }\n\n return parsed.data;\n}\n","import type { Node, PageDocument } from '@kubuild/schema';\nimport { NodeSchema } from '@kubuild/schema';\nimport {\n collectNodeIdSet,\n findNodeById,\n validateDocumentSecurity,\n type DocumentSecurityLimits,\n} from '@kubuild/core';\nimport type { AiCompiledComponentSpec } from '../../types';\nimport { normalizeNodeTree } from '../../core/normalizer';\nimport { getNodeLabel } from '../../core/document-outline';\nimport type { ToolExecutionResult } from './types';\n\n/**\n * A failed tool call (STORA-530).\n *\n * Failures are deliberately *not* thrown: they're returned to the model as a normal\n * `tool_result` with `ok: false` so it can read the reason, fix its arguments and retry.\n * That self-correction loop is the main reason agent mode beats one-shot JSON generation —\n * a hallucinated node id becomes a retry instead of a broken document.\n */\nexport function fail(summary: string, message: string, extra?: Record<string, unknown>): ToolExecutionResult {\n return {\n ok: false,\n summary,\n content: { ok: false, error: message, ...(extra ?? {}) },\n };\n}\n\nexport function succeed(\n summary: string,\n content: Record<string, unknown>,\n rest?: Pick<ToolExecutionResult, 'op' | 'document'>,\n): ToolExecutionResult {\n return { ok: true, summary, content: { ok: true, ...content }, ...(rest ?? {}) };\n}\n\n/** Reads a required string argument, tolerating the whitespace LLMs sometimes emit. */\nexport function readString(input: Record<string, unknown>, key: string): string | null {\n const value = input[key];\n return typeof value === 'string' && value.trim() ? value.trim() : null;\n}\n\nexport function readPlainObject(\n input: Record<string, unknown>,\n key: string,\n): Record<string, unknown> | null {\n const value = input[key];\n if (!value || typeof value !== 'object' || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nexport function readOptionalIndex(input: Record<string, unknown>, key: string): number | undefined {\n const value = input[key];\n if (typeof value === 'number' && Number.isInteger(value) && value >= 0) return value;\n return undefined;\n}\n\n/**\n * Cheap similarity used only to suggest alternatives when the model invents a node id —\n * shared prefix length plus a substring bonus. Good enough to turn \"hero-title\" into a\n * pointer at \"hero-heading\"; no need for a real edit-distance implementation here.\n */\nfunction similarity(a: string, b: string): number {\n if (a === b) return Infinity;\n let shared = 0;\n const max = Math.min(a.length, b.length);\n while (shared < max && a[shared] === b[shared]) shared++;\n return shared + (a.includes(b) || b.includes(a) ? 3 : 0);\n}\n\n/** Up to `limit` existing node ids most similar to a bad one, for the retry hint. */\nexport function suggestNodeIds(document: PageDocument, badId: string, limit = 5): string[] {\n return Array.from(collectNodeIdSet(document.document))\n .map((id) => ({ id, score: similarity(id.toLowerCase(), badId.toLowerCase()) }))\n .filter((entry) => entry.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit)\n .map((entry) => entry.id);\n}\n\nexport interface ResolvedNode {\n node: Node;\n}\n\n/** Resolves a node id against the snapshot, or returns a retry-friendly failure. */\nexport function resolveNode(\n document: PageDocument,\n nodeId: string,\n toolName: string,\n): { node: Node } | { error: ToolExecutionResult } {\n const node = findNodeById(document.document, nodeId);\n if (!node) {\n return {\n error: fail(\n `${toolName}: node \"${nodeId}\" tidak ditemukan`,\n `No node with id \"${nodeId}\" exists in this page. Node ids must come from the outline or from a tool result — never invented.`,\n { suggestedNodeIds: suggestNodeIds(document, nodeId) },\n ),\n };\n }\n return { node };\n}\n\nexport function findCatalogEntry(\n catalog: AiCompiledComponentSpec[],\n type: string,\n): AiCompiledComponentSpec | undefined {\n return catalog.find((entry) => entry.type === type);\n}\n\n/**\n * Enforces the registry's nesting contract before an insert/move (STORA-530).\n *\n * The same `acceptsChildren`/`allowedChildren` rules the prompt states are checked here,\n * because a prompt rule is a suggestion while a tool check is a guarantee — and a document\n * that violates them renders wrong rather than failing loudly.\n *\n * An empty catalog (host supplied no registry) means \"unknown\", so nesting is allowed\n * rather than blocking every insert.\n */\nexport function checkNesting(\n catalog: AiCompiledComponentSpec[],\n parent: Node,\n childType: string,\n): string | null {\n if (catalog.length === 0) return null;\n\n const parentSpec = findCatalogEntry(catalog, parent.type);\n if (parentSpec && !parentSpec.acceptsChildren) {\n return `Component \"${parent.type}\" (#${parent.id}) cannot contain children. Insert into a container/section node instead.`;\n }\n if (parentSpec?.allowedChildren && parentSpec.allowedChildren.length > 0) {\n if (!parentSpec.allowedChildren.includes(childType)) {\n return `Component \"${parent.type}\" only accepts children of type [${parentSpec.allowedChildren.join(', ')}] — \"${childType}\" is not allowed.`;\n }\n }\n\n const childSpec = findCatalogEntry(catalog, childType);\n if (childSpec?.disallowedParents?.includes(parent.type)) {\n return `Component \"${childType}\" cannot be placed inside \"${parent.type}\".`;\n }\n\n return null;\n}\n\n/** Validates a component type against the catalog, returning a retry hint when unknown. */\nexport function checkComponentType(\n catalog: AiCompiledComponentSpec[],\n type: string,\n): string | null {\n if (catalog.length === 0) return null;\n if (findCatalogEntry(catalog, type)) return null;\n const known = catalog.map((entry) => entry.type);\n return `Unknown component type \"${type}\". Use list_component_types to see valid types. Known types: ${known.slice(0, 40).join(', ')}${known.length > 40 ? ', …' : ''}`;\n}\n\n/**\n * The defense-in-depth gate every write tool passes through before its op is accepted —\n * the same `validateDocumentSecurity` pass `normalizeAndValidate*` already applies to\n * generated documents, now applied per mutation so a single bad tool call can't smuggle\n * a `javascript:` href or a prototype-pollution key into the snapshot.\n */\nexport function checkDocumentSecurity(\n document: PageDocument,\n limits?: DocumentSecurityLimits,\n): string | null {\n const result = validateDocumentSecurity(document, limits);\n if (result.safe) return null;\n return result.errors.map((error) => `${error.code}: ${error.message}`).join('; ');\n}\n\n/**\n * Normalizes a model-authored node and guarantees its ids don't collide with the snapshot\n * (`insertNode` in `@kubuild/core` throws on duplicate ids). Reuses the shared\n * `normalizeNodeTree` so agent-authored nodes get the same prop/style coercions as nodes\n * from full-page generation.\n */\nexport function normalizeIncomingNode(\n raw: unknown,\n document: PageDocument,\n options: { preserveIds?: boolean } = {},\n): { node: Node } | { error: string } {\n let normalized: Node;\n try {\n normalized = normalizeNodeTree(raw);\n } catch (err) {\n return { error: err instanceof Error ? err.message : String(err) };\n }\n\n if (!options.preserveIds) {\n const taken = collectNodeIdSet(document.document);\n const reassign = (node: Node): void => {\n if (!node.id || taken.has(node.id)) {\n let counter = 1;\n let candidate = `${node.type}-${counter}`;\n while (taken.has(candidate)) {\n counter++;\n candidate = `${node.type}-${counter}`;\n }\n node.id = candidate;\n }\n taken.add(node.id);\n for (const child of node.children ?? []) reassign(child);\n };\n reassign(normalized);\n }\n\n const parsed = NodeSchema.safeParse(normalized);\n if (!parsed.success) {\n return {\n error: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; '),\n };\n }\n\n return { node: parsed.data };\n}\n\n/** Short human description of a node for tool summaries / op labels. */\nexport function describeNode(node: Node): string {\n const label = getNodeLabel(node, 32);\n return label ? `${node.type} \"${label}\" (#${node.id})` : `${node.type} (#${node.id})`;\n}\n","import type { Node } from '@kubuild/schema';\nimport {\n buildSelectionContext,\n getNodeLabel,\n pruneNodeForPrompt,\n summarizeNodeTree,\n} from '../../core/document-outline';\nimport type { AgentTool } from './types';\nimport { fail, readString, resolveNode, succeed } from './helpers';\n\n/**\n * Read-only tools (STORA-530).\n *\n * All of them are answered straight from the agent's snapshot — no extra model round trip,\n * no network. They exist so the system prompt can ship a cheap outline instead of the whole\n * document, and the model pulls detail only for the handful of nodes it actually needs.\n */\n\nconst getPageOutline: AgentTool = {\n kind: 'read',\n definition: {\n name: 'get_page_outline',\n description:\n 'Return the page structure as an indented outline of node ids, types, labels and child counts. Use this to re-orient after edits. Does not include props or styles — call read_node for those.',\n inputSchema: {\n type: 'object',\n properties: {\n maxDepth: {\n type: 'integer',\n description: 'How deep to expand the tree before collapsing. Default 3.',\n },\n },\n },\n },\n execute(input, context) {\n const maxDepth =\n typeof input.maxDepth === 'number' && input.maxDepth > 0 ? Math.floor(input.maxDepth) : 3;\n return succeed('Membaca struktur halaman', {\n outline: summarizeNodeTree(context.document.document, { maxDepth }),\n });\n },\n};\n\nconst readNode: AgentTool = {\n kind: 'read',\n definition: {\n name: 'read_node',\n description:\n 'Return one node with its full props and styles, plus its parent, position and siblings. Always read a node before editing it, so you change only the fields that need changing.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to read (from the outline).' },\n includeChildren: {\n type: 'boolean',\n description: 'Include the node subtree. Default false — keeps the result small.',\n },\n },\n required: ['nodeId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('read_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const resolved = resolveNode(context.document, nodeId, 'read_node');\n if ('error' in resolved) return resolved.error;\n\n const selection = buildSelectionContext(context.document.document, nodeId);\n const includeChildren = input.includeChildren === true;\n const node = includeChildren\n ? pruneNodeForPrompt(resolved.node, 3)\n : { ...resolved.node, children: undefined };\n\n return succeed(`Membaca node ${nodeId}`, {\n node,\n childCount: resolved.node.children?.length ?? 0,\n parentId: selection?.parentId ?? null,\n index: selection?.index ?? 0,\n ancestors: selection?.ancestors.map((a) => ({ id: a.id, type: a.type })) ?? [],\n siblings:\n selection?.siblings.map((sibling, i) => ({\n index: i,\n id: sibling.id,\n type: sibling.type,\n label: getNodeLabel(sibling),\n })) ?? [],\n });\n },\n};\n\nconst findNodes: AgentTool = {\n kind: 'read',\n definition: {\n name: 'find_nodes',\n description:\n 'Search the page for nodes by component type and/or visible text. Use this instead of guessing ids when the user refers to something by what it says (\"the Get Started button\").',\n inputSchema: {\n type: 'object',\n properties: {\n type: { type: 'string', description: 'Component type to match exactly, e.g. \"button\".' },\n textContains: {\n type: 'string',\n description: 'Case-insensitive substring to match against the node text/label props.',\n },\n parentId: { type: 'string', description: 'Limit the search to this node subtree.' },\n limit: { type: 'integer', description: 'Max results. Default 20.' },\n },\n },\n },\n execute(input, context) {\n const type = readString(input, 'type');\n const textContains = readString(input, 'textContains');\n const parentId = readString(input, 'parentId');\n const limit =\n typeof input.limit === 'number' && input.limit > 0 ? Math.floor(input.limit) : 20;\n\n if (!type && !textContains) {\n return fail(\n 'find_nodes: filter kosong',\n 'Provide at least one of \"type\" or \"textContains\" — an unfiltered search would just return the whole outline.',\n );\n }\n\n let root: Node = context.document.document;\n if (parentId) {\n const resolved = resolveNode(context.document, parentId, 'find_nodes');\n if ('error' in resolved) return resolved.error;\n root = resolved.node;\n }\n\n const needle = textContains?.toLowerCase();\n const matches: Array<{ id: string; type: string; label: string }> = [];\n\n const walk = (node: Node): void => {\n if (matches.length >= limit) return;\n const label = getNodeLabel(node);\n const typeMatches = !type || node.type === type;\n const textMatches = !needle || label.toLowerCase().includes(needle);\n if (typeMatches && textMatches) {\n matches.push({ id: node.id, type: node.type, label });\n }\n for (const child of node.children ?? []) walk(child);\n };\n walk(root);\n\n return succeed(\n `Mencari node (${matches.length} hasil)`,\n matches.length > 0\n ? { matches, count: matches.length }\n : {\n matches: [],\n count: 0,\n hint: 'Nothing matched. Try a broader filter, or call get_page_outline to see what exists.',\n },\n );\n },\n};\n\nconst listComponentTypes: AgentTool = {\n kind: 'read',\n definition: {\n name: 'list_component_types',\n description:\n 'List component types available in this editor, with their props and nesting rules. Call this before inserting a component type you have not used yet.',\n inputSchema: {\n type: 'object',\n properties: {\n category: { type: 'string', description: 'Filter to one category, e.g. \"layout\".' },\n },\n },\n },\n execute(input, context) {\n const category = readString(input, 'category');\n const entries = category\n ? context.catalog.filter((spec) => spec.category === category)\n : context.catalog;\n\n return succeed(`Melihat katalog komponen (${entries.length})`, {\n components: entries.map((spec) => ({\n type: spec.type,\n label: spec.label,\n category: spec.category,\n acceptsChildren: spec.acceptsChildren,\n allowedChildren: spec.allowedChildren,\n props: spec.props?.map((prop) => ({\n name: prop.name,\n type: prop.type,\n options: prop.options,\n })),\n })),\n });\n },\n};\n\nexport const READ_TOOLS: AgentTool[] = [getPageOutline, readNode, findNodes, listComponentTypes];\n","import type { Node, PageDocument } from '@kubuild/schema';\nimport {\n duplicateNode,\n findNodeById,\n insertNode,\n moveNode,\n removeNode,\n replaceNode,\n updateProps,\n updateStyle,\n} from '@kubuild/core';\nimport type { AgentOp } from '../../types';\nimport { getNodeLabel } from '../../core/document-outline';\nimport type { AgentTool, ToolExecutionContext, ToolExecutionResult } from './types';\nimport {\n checkComponentType,\n checkDocumentSecurity,\n checkNesting,\n describeNode,\n fail,\n normalizeIncomingNode,\n readOptionalIndex,\n readPlainObject,\n readString,\n resolveNode,\n succeed,\n} from './helpers';\n\n/**\n * Write tools (STORA-530).\n *\n * Each one produces a single `AgentOp` — never a regenerated document. The op is what the\n * editor later replays through its own store actions, so an agent run lands in the command\n * engine and the history stack exactly like manual editing does.\n *\n * Every write follows the same three-step contract:\n * 1. validate the arguments against the snapshot (ids, types, nesting),\n * 2. apply the corresponding pure `@kubuild/core` command to the snapshot,\n * 3. re-run `validateDocumentSecurity` on the result before the op is accepted.\n * Step 3 matters because the arguments come from a language model: it's the same \"AI output\n * is untrusted input\" boundary `normalizeAndValidate*` enforces for generated documents.\n */\n\nconst BREAKPOINTS = ['base', 'desktop', 'tablet', 'mobile'] as const;\ntype Breakpoint = (typeof BREAKPOINTS)[number];\n\n/**\n * Runs a `@kubuild/core` command against the snapshot and converts a throw into a\n * retry-friendly tool failure. The core commands throw on things the model plausibly gets\n * wrong (duplicate ids, moving a node into its own descendant, removing the root), and\n * those messages are already specific enough to hand straight back to the model.\n */\nfunction applyCommand(\n toolName: string,\n run: () => { document: PageDocument },\n): { document: PageDocument } | { error: ToolExecutionResult } {\n try {\n return run();\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { error: fail(`${toolName} gagal`, message) };\n }\n}\n\nfunction guardSecurity(\n toolName: string,\n document: PageDocument,\n context: ToolExecutionContext,\n): ToolExecutionResult | null {\n const violation = checkDocumentSecurity(document, context.securityLimits);\n if (!violation) return null;\n return fail(\n `${toolName} ditolak (security)`,\n `The resulting document failed the security check and was rejected: ${violation}`,\n );\n}\n\nconst updateNodeProps: AgentTool = {\n kind: 'write',\n definition: {\n name: 'update_node_props',\n description:\n 'Change the props of one existing node (text, label, href, src, level, …). This is the right tool for any content/copy change — it touches nothing else on the page.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to edit.' },\n props: {\n type: 'object',\n description: 'Props to write. Include only the props that should change.',\n },\n merge: {\n type: 'boolean',\n description:\n 'true (default) merges with existing props. Only pass false to deliberately clear the other props.',\n },\n },\n required: ['nodeId', 'props'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('update_node_props: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const props = readPlainObject(input, 'props');\n if (!props) {\n return fail(\n 'update_node_props: props tidak valid',\n 'Argument \"props\" must be a JSON object of prop names to values.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'update_node_props');\n if ('error' in resolved) return resolved.error;\n\n const merge = input.merge !== false;\n const applied = applyCommand('update_node_props', () =>\n updateProps(context.document, { nodeId, props, merge }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('update_node_props', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'update-props', nodeId, props, merge };\n const updated = findNodeById(applied.document.document, nodeId);\n\n return succeed(\n `Ubah props ${describeNode(resolved.node)}`,\n { nodeId, props: updated?.props ?? props, changedKeys: Object.keys(props) },\n { op, document: applied.document },\n );\n },\n};\n\nconst updateNodeStyles: AgentTool = {\n kind: 'write',\n definition: {\n name: 'update_node_styles',\n description:\n 'Change the styles of one existing node. Use `breakpoint` for normal styling and `state` for pseudo-classes like \":hover\". This is the right tool for any color/spacing/size/typography change.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node to restyle.' },\n styles: {\n type: 'object',\n description:\n 'CSS properties in camelCase with primitive values, e.g. { \"backgroundColor\": \"#16a34a\", \"paddingTop\": \"24px\" }. Never nest objects here.',\n },\n breakpoint: {\n type: 'string',\n enum: ['base', 'desktop', 'tablet', 'mobile'],\n description: 'Breakpoint layer to write. Default \"base\".',\n },\n state: {\n type: 'string',\n description:\n 'Pseudo-state layer such as \":hover\", \":focus\", \":active\". Mutually exclusive with breakpoint.',\n },\n merge: {\n type: 'boolean',\n description: 'true (default) merges with existing styles in that layer.',\n },\n },\n required: ['nodeId', 'styles'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('update_node_styles: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const styles = readPlainObject(input, 'styles');\n if (!styles) {\n return fail(\n 'update_node_styles: styles tidak valid',\n 'Argument \"styles\" must be a JSON object of CSS properties with primitive values.',\n );\n }\n\n const nested = Object.entries(styles).find(\n ([, value]) => value !== null && typeof value === 'object',\n );\n if (nested) {\n return fail(\n 'update_node_styles: nilai bersarang',\n `Style property \"${nested[0]}\" has an object value. Style values must be primitives — use the \"state\" argument for pseudo-classes instead of nesting them.`,\n );\n }\n\n const rawState = readString(input, 'state');\n const rawBreakpoint = readString(input, 'breakpoint');\n if (rawState && rawBreakpoint) {\n return fail(\n 'update_node_styles: argumen bentrok',\n 'Pass either \"breakpoint\" or \"state\", not both — a pseudo-state layer is not per-breakpoint.',\n );\n }\n if (rawBreakpoint && !BREAKPOINTS.includes(rawBreakpoint as Breakpoint)) {\n return fail(\n 'update_node_styles: breakpoint tidak dikenal',\n `Unknown breakpoint \"${rawBreakpoint}\". Valid values: ${BREAKPOINTS.join(', ')}.`,\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'update_node_styles');\n if ('error' in resolved) return resolved.error;\n\n const state = rawState ? (rawState.startsWith(':') ? rawState : `:${rawState}`) : undefined;\n const breakpoint = state ? undefined : ((rawBreakpoint as Breakpoint) ?? 'base');\n const merge = input.merge !== false;\n\n const applied = applyCommand('update_node_styles', () =>\n updateStyle(context.document, { nodeId, styles, breakpoint, state, merge }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('update_node_styles', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'update-styles', nodeId, styles, breakpoint, state, merge };\n const layer = state ? `state ${state}` : `breakpoint ${breakpoint}`;\n\n return succeed(\n `Ubah style ${describeNode(resolved.node)} (${layer})`,\n { nodeId, layer, appliedStyles: styles },\n { op, document: applied.document },\n );\n },\n};\n\nconst insertComponent: AgentTool = {\n kind: 'write',\n definition: {\n name: 'insert_component',\n description:\n 'Insert one new component into an existing parent node. Use this for adding a single element (a button, a paragraph, an image). For a whole new page section, use insert_section instead.',\n inputSchema: {\n type: 'object',\n properties: {\n parentId: { type: 'string', description: 'Id of the node that will contain the new component.' },\n type: { type: 'string', description: 'Component type from the catalog.' },\n index: {\n type: 'integer',\n description: 'Position among the parent children. Omit to append at the end.',\n },\n props: { type: 'object', description: 'Initial props for the new component.' },\n styles: {\n type: 'object',\n description: 'Initial styles, e.g. { \"base\": { \"marginTop\": \"16px\" } }.',\n },\n children: {\n type: 'array',\n description: 'Optional nested child nodes, each { type, props?, styles?, children? }.',\n items: { type: 'object' },\n },\n },\n required: ['parentId', 'type'],\n },\n },\n execute(input, context) {\n const parentId = readString(input, 'parentId');\n const type = readString(input, 'type');\n if (!parentId || !type) {\n return fail(\n 'insert_component: argumen kurang',\n 'Arguments \"parentId\" and \"type\" are both required.',\n );\n }\n\n const typeError = checkComponentType(context.catalog, type);\n if (typeError) return fail('insert_component: tipe tidak dikenal', typeError);\n\n const resolvedParent = resolveNode(context.document, parentId, 'insert_component');\n if ('error' in resolvedParent) return resolvedParent.error;\n\n const nestingError = checkNesting(context.catalog, resolvedParent.node, type);\n if (nestingError) return fail('insert_component: nesting tidak valid', nestingError);\n\n const normalized = normalizeIncomingNode(\n {\n type,\n props: readPlainObject(input, 'props') ?? undefined,\n styles: readPlainObject(input, 'styles') ?? undefined,\n children: Array.isArray(input.children) ? input.children : undefined,\n },\n context.document,\n );\n if ('error' in normalized) {\n return fail('insert_component: node tidak valid', normalized.error);\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('insert_component', () =>\n insertNode(context.document, { parentId, node: normalized.node, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('insert_component', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'insert-node', parentId, index, node: normalized.node };\n\n return succeed(\n `Tambah ${describeNode(normalized.node)} ke #${parentId}`,\n { nodeId: normalized.node.id, parentId, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\n/**\n * Section insertion delegates to `KubuildAiEngine.generateSection` rather than asking the\n * agent model to author a whole section inline: that path already handles planning,\n * normalization and the `section` JSON schema, and keeps generated markup consistent with\n * the non-agent \"generate\" feature.\n */\nconst insertSection: AgentTool = {\n kind: 'write',\n definition: {\n name: 'insert_section',\n description:\n 'Generate and insert a complete new page section (hero, features, pricing, FAQ, CTA, …) from a description. Use this when the user asks to ADD a section — do not hand-build sections with insert_component.',\n inputSchema: {\n type: 'object',\n properties: {\n prompt: {\n type: 'string',\n description:\n 'Detailed description of the section: purpose, content, layout and tone. Write it in the language the page uses.',\n },\n index: {\n type: 'integer',\n description: 'Position among the page sections. Omit to append at the end.',\n },\n },\n required: ['prompt'],\n },\n },\n async execute(input, context) {\n const prompt = readString(input, 'prompt');\n if (!prompt) return fail('insert_section: prompt kosong', 'Argument \"prompt\" is required.');\n\n if (!context.generateSection) {\n return fail(\n 'insert_section: tidak tersedia',\n 'Section generation is not available in this deployment. Build the section with insert_component instead.',\n );\n }\n\n const rootId = context.document.document.id;\n const existingSections = (context.document.document.children ?? [])\n .map((child) => `${child.type}: ${getNodeLabel(child) || child.id}`)\n .join(', ');\n\n let generated: Node;\n try {\n generated = await context.generateSection({\n prompt,\n parentContext: `Page \"${context.document.metadata?.title ?? 'Untitled'}\". Existing sections: ${existingSections || '(none)'}`,\n });\n } catch (err) {\n return fail(\n 'insert_section gagal',\n `Section generation failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const normalized = normalizeIncomingNode(generated, context.document);\n if ('error' in normalized) {\n return fail('insert_section: section tidak valid', normalized.error);\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('insert_section', () =>\n insertNode(context.document, { parentId: rootId, node: normalized.node, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('insert_section', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'insert-node', parentId: rootId, index, node: normalized.node };\n\n return succeed(\n `Tambah section baru (#${normalized.node.id})`,\n {\n nodeId: normalized.node.id,\n index: index ?? null,\n childCount: normalized.node.children?.length ?? 0,\n },\n { op, document: applied.document },\n );\n },\n};\n\nconst moveNodeTool: AgentTool = {\n kind: 'write',\n definition: {\n name: 'move_node',\n description: 'Move an existing node to a different parent and/or position.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n targetParentId: { type: 'string', description: 'Id of the new parent node.' },\n index: { type: 'integer', description: 'Position within the new parent. Omit to append.' },\n },\n required: ['nodeId', 'targetParentId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n const targetParentId = readString(input, 'targetParentId');\n if (!nodeId || !targetParentId) {\n return fail(\n 'move_node: argumen kurang',\n 'Arguments \"nodeId\" and \"targetParentId\" are both required.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'move_node');\n if ('error' in resolved) return resolved.error;\n const resolvedParent = resolveNode(context.document, targetParentId, 'move_node');\n if ('error' in resolvedParent) return resolvedParent.error;\n\n const nestingError = checkNesting(context.catalog, resolvedParent.node, resolved.node.type);\n if (nestingError) return fail('move_node: nesting tidak valid', nestingError);\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('move_node', () =>\n moveNode(context.document, { nodeId, targetParentId, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('move_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'move-node', nodeId, targetParentId, index };\n\n return succeed(\n `Pindah ${describeNode(resolved.node)} ke #${targetParentId}`,\n { nodeId, targetParentId, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\nconst duplicateNodeTool: AgentTool = {\n kind: 'write',\n definition: {\n name: 'duplicate_node',\n description:\n 'Duplicate an existing node and its subtree, with fresh ids. Useful for repeating an existing card/feature rather than authoring a new one from scratch.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n targetParentId: {\n type: 'string',\n description: 'Where to put the copy. Defaults to the original node parent.',\n },\n index: { type: 'integer', description: 'Position of the copy. Defaults to right after the original.' },\n },\n required: ['nodeId'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('duplicate_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const resolved = resolveNode(context.document, nodeId, 'duplicate_node');\n if ('error' in resolved) return resolved.error;\n\n const targetParentId = readString(input, 'targetParentId') ?? undefined;\n if (targetParentId) {\n const resolvedParent = resolveNode(context.document, targetParentId, 'duplicate_node');\n if ('error' in resolvedParent) return resolvedParent.error;\n }\n\n const index = readOptionalIndex(input, 'index');\n const applied = applyCommand('duplicate_node', () =>\n duplicateNode(context.document, { nodeId, targetParentId, index }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('duplicate_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'duplicate-node', nodeId, targetParentId, index };\n\n return succeed(\n `Duplikat ${describeNode(resolved.node)}`,\n { nodeId, targetParentId: targetParentId ?? null, index: index ?? null },\n { op, document: applied.document },\n );\n },\n};\n\nconst deleteNode: AgentTool = {\n kind: 'write',\n destructive: true,\n definition: {\n name: 'delete_node',\n description:\n 'Permanently remove a node and everything inside it. Only call this when the user unambiguously asked to remove that specific thing. If the request is vague, ask instead.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string' },\n reason: {\n type: 'string',\n description: 'Short justification quoting what the user asked for. Shown to the user before they apply.',\n },\n },\n required: ['nodeId', 'reason'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n if (!nodeId) return fail('delete_node: nodeId kosong', 'Argument \"nodeId\" is required.');\n\n const reason = readString(input, 'reason');\n if (!reason) {\n return fail(\n 'delete_node: alasan kosong',\n 'Argument \"reason\" is required for destructive actions — state what the user asked for.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'delete_node');\n if ('error' in resolved) return resolved.error;\n\n const applied = applyCommand('delete_node', () => removeNode(context.document, { nodeId }));\n if ('error' in applied) return applied.error;\n\n const op: AgentOp = { kind: 'delete-node', nodeId };\n\n return succeed(\n `Hapus ${describeNode(resolved.node)} — ${reason}`,\n { nodeId, removedType: resolved.node.type },\n { op, document: applied.document },\n );\n },\n};\n\nconst replaceNodeTool: AgentTool = {\n kind: 'write',\n destructive: true,\n definition: {\n name: 'replace_node',\n description:\n 'Replace a node subtree wholesale. LAST RESORT — only when the children genuinely must be restructured. Never use it to change props or styles; use update_node_props / update_node_styles for that.',\n inputSchema: {\n type: 'object',\n properties: {\n nodeId: { type: 'string', description: 'Id of the node being replaced. The replacement keeps this id.' },\n node: {\n type: 'object',\n description: 'Replacement node { type, props?, styles?, children? }. Its id is forced to nodeId.',\n },\n reason: {\n type: 'string',\n description: 'Why a structural replacement is required instead of a props/styles edit.',\n },\n },\n required: ['nodeId', 'node', 'reason'],\n },\n },\n execute(input, context) {\n const nodeId = readString(input, 'nodeId');\n const raw = readPlainObject(input, 'node');\n const reason = readString(input, 'reason');\n if (!nodeId || !raw || !reason) {\n return fail(\n 'replace_node: argumen kurang',\n 'Arguments \"nodeId\", \"node\" and \"reason\" are all required.',\n );\n }\n\n const resolved = resolveNode(context.document, nodeId, 'replace_node');\n if ('error' in resolved) return resolved.error;\n\n // Ids inside the replacement are regenerated (preserveIds: false) so a model that\n // re-emits the old subtree's ids can't collide with the rest of the document; the root\n // id is then pinned back to the target, which is what `replaceNode` requires.\n const normalized = normalizeIncomingNode({ ...raw, id: undefined }, context.document);\n if ('error' in normalized) {\n return fail('replace_node: node tidak valid', normalized.error);\n }\n\n const replacement: Node = { ...normalized.node, id: nodeId, type: resolved.node.type };\n\n const applied = applyCommand('replace_node', () =>\n replaceNode(context.document, { nodeId, node: replacement }),\n );\n if ('error' in applied) return applied.error;\n\n const violation = guardSecurity('replace_node', applied.document, context);\n if (violation) return violation;\n\n const op: AgentOp = { kind: 'replace-node', nodeId, node: replacement };\n\n return succeed(\n `Ganti struktur ${describeNode(resolved.node)} — ${reason}`,\n { nodeId, childCount: replacement.children?.length ?? 0 },\n { op, document: applied.document },\n );\n },\n};\n\nexport const WRITE_TOOLS: AgentTool[] = [\n updateNodeProps,\n updateNodeStyles,\n insertComponent,\n insertSection,\n moveNodeTool,\n duplicateNodeTool,\n deleteNode,\n replaceNodeTool,\n];\n","import type { AiToolDefinition } from '../../types';\nimport type { AgentTool } from './types';\nimport { READ_TOOLS } from './read-tools';\nimport { WRITE_TOOLS } from './write-tools';\n\nexport * from './types';\nexport { READ_TOOLS } from './read-tools';\nexport { WRITE_TOOLS } from './write-tools';\nexport {\n checkNesting,\n checkComponentType,\n checkDocumentSecurity,\n normalizeIncomingNode,\n suggestNodeIds,\n} from './helpers';\n\nexport interface DocumentToolsOptions {\n /**\n * Set false to give the agent a read-only tool set — useful for a \"review my page\"\n * assistant that must never propose mutations.\n */\n allowWrites?: boolean;\n /** Tool names to exclude, e.g. `['delete_node']` on a plan that forbids deletions. */\n exclude?: string[];\n}\n\n/**\n * The document tool set the agent is given (STORA-530).\n *\n * Read tools first: the ordering is what the model sees, and putting the \"look before you\n * edit\" tools at the top nudges it toward reading a node before rewriting it.\n */\nexport function createDocumentTools(options: DocumentToolsOptions = {}): AgentTool[] {\n const { allowWrites = true, exclude = [] } = options;\n const tools = allowWrites ? [...READ_TOOLS, ...WRITE_TOOLS] : [...READ_TOOLS];\n return tools.filter((tool) => !exclude.includes(tool.definition.name));\n}\n\n/** Provider-facing definitions for a tool set. */\nexport function toToolDefinitions(tools: AgentTool[]): AiToolDefinition[] {\n return tools.map((tool) => tool.definition);\n}\n","import type { PageDocument } from '@kubuild/schema';\nimport type {\n AgentOpRecord,\n AiAgentRequest,\n AiAgentRunResult,\n AiChatMessage,\n AiCompiledComponentSpec,\n AiContentBlock,\n AiStreamEvent,\n AiToolUseBlock,\n KubuildAiEngineOptions,\n} from '../types';\nimport { buildAgentSystemPrompt, compileComponentCatalog } from '../core/prompt-compiler';\nimport { getMessageText } from '../core/messages';\nimport type { KubuildAiEngine } from './engine';\nimport { createDocumentTools, toToolDefinitions, type AgentTool } from './tools';\n\nexport interface KubuildAiAgentOptions extends KubuildAiEngineOptions {\n /**\n * Engine used by the `insert_section` tool. Optional: without it the agent still runs,\n * and `insert_section` returns a \"not available\" tool error telling the model to build\n * the section with `insert_component` instead.\n */\n engine?: KubuildAiEngine;\n /** Overrides the default tool set (read + write document tools). */\n tools?: AgentTool[];\n}\n\n/** Ceiling on reasoning steps per run — the primary runaway-cost guard. */\nconst DEFAULT_MAX_STEPS = 8;\n\n/** Ceiling on tool calls the model may request within a single step. */\nconst MAX_TOOL_CALLS_PER_STEP = 8;\n\nfunction toolResultMessage(blocks: AiContentBlock[]): AiChatMessage {\n return { role: 'user', content: blocks, timestamp: Date.now() };\n}\n\n/**\n * The page-editing agent (STORA-530).\n *\n * Unlike every `KubuildAiEngine` method, which is a single request/response, this runs a\n * loop: the model reads the page through tools, makes a surgical change through tools, and\n * stops. The document it mutates is a private **snapshot** — the run's output is an ordered\n * list of `AgentOp`s that the editor replays through its own store actions, so an agent\n * edit lands in the command engine and the undo stack exactly like a manual edit.\n *\n * Nothing here ever touches the user's live document.\n */\nexport class KubuildAiAgent {\n private options: KubuildAiAgentOptions;\n private catalog: AiCompiledComponentSpec[];\n private tools: AgentTool[];\n\n constructor(options: KubuildAiAgentOptions) {\n if (!options.adapter) {\n throw new Error('KubuildAiAgent requires an adapter instance');\n }\n if (!options.adapter.supportsTools) {\n // Failing loudly beats running a tool-less loop that can never edit anything: the\n // model would just describe the change it \"made\" and the user would get no ops.\n throw new Error(\n `Adapter \"${options.adapter.name}\" does not support tool calling, which agent mode requires. Use an adapter with supportsTools === true (e.g. OpenAiAdapter).`,\n );\n }\n this.options = options;\n this.catalog = compileComponentCatalog(options.registry);\n this.tools = options.tools ?? createDocumentTools();\n }\n\n get adapterName(): string {\n return this.options.adapter.name;\n }\n\n refreshCatalog(): void {\n this.catalog = compileComponentCatalog(this.options.registry);\n }\n\n private log(level: 'info' | 'warn' | 'error' | 'debug', message: string, meta?: unknown): void {\n if (this.options.logger) {\n this.options.logger(level, message, meta);\n } else if (this.options.debug) {\n console.log(`[KUBUILD-AGENT ${level.toUpperCase()}] ${message}`, meta !== undefined ? meta : '');\n }\n }\n\n private findTool(name: string): AgentTool | undefined {\n return this.tools.find((tool) => tool.definition.name === name);\n }\n\n /**\n * Runs one tool call against the current snapshot.\n *\n * An unknown tool name is answered with a normal (failed) tool result rather than an\n * exception, for the same reason bad arguments are: it gives the model a chance to pick a\n * real tool on the next step instead of killing the run.\n */\n private async executeToolCall(\n call: AiToolUseBlock,\n snapshot: PageDocument,\n signal?: AbortSignal,\n ): Promise<{\n block: AiContentBlock;\n ok: boolean;\n summary: string;\n snapshot: PageDocument;\n op?: AgentOpRecord;\n }> {\n const tool = this.findTool(call.name);\n\n if (!tool) {\n const available = this.tools.map((t) => t.definition.name).join(', ');\n return {\n ok: false,\n summary: `Tool \"${call.name}\" tidak dikenal`,\n snapshot,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({\n ok: false,\n error: `Unknown tool \"${call.name}\". Available tools: ${available}.`,\n }),\n },\n };\n }\n\n let result;\n try {\n result = await tool.execute(call.input ?? {}, {\n document: snapshot,\n catalog: this.catalog,\n securityLimits: this.options.securityLimits,\n signal,\n generateSection: this.options.engine\n ? async ({ prompt, parentContext }) => {\n const response = await this.options.engine!.generateSection(\n { prompt, parentContext },\n { signal },\n );\n if (!response.success || !response.data) {\n throw new Error(response.error?.message ?? 'Section generation failed');\n }\n return response.data;\n }\n : undefined,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `Tool \"${call.name}\" threw`, message);\n return {\n ok: false,\n summary: `Tool \"${call.name}\" error`,\n snapshot,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({ ok: false, error: message }),\n },\n };\n }\n\n const op: AgentOpRecord | undefined =\n result.ok && result.op\n ? {\n id: call.id,\n op: result.op,\n summary: result.summary,\n destructive: tool.destructive === true,\n }\n : undefined;\n\n return {\n ok: result.ok,\n summary: result.summary,\n snapshot: result.document ?? snapshot,\n op,\n block: {\n type: 'tool_result',\n toolUseId: call.id,\n isError: !result.ok,\n content: JSON.stringify(result.content),\n },\n };\n }\n\n /**\n * Executes one agent turn, streaming progress as `AiStreamEvent`s and ending with a\n * terminal `agent-complete` (or `error`) event.\n *\n * The loop stops as soon as the model returns a turn with no tool calls — that final\n * message is the summary shown to the user. It also stops at `maxSteps` (cost guard) or\n * on abort, and reports which of those happened via `stoppedBy` so the UI can say\n * \"stopped after N steps\" rather than pretending the work is finished.\n */\n async *run(\n request: AiAgentRequest,\n context?: { signal?: AbortSignal },\n ): AsyncIterable<AiStreamEvent> {\n const maxSteps = request.maxSteps ?? this.options.maxAgentSteps ?? DEFAULT_MAX_STEPS;\n const signal = context?.signal;\n\n if (!request.messages || request.messages.length === 0) {\n yield {\n type: 'error',\n error: { code: 'INVALID_AGENT_REQUEST', message: '\"messages\" must not be empty' },\n };\n return;\n }\n\n if (!request.document?.document) {\n yield {\n type: 'error',\n error: { code: 'INVALID_AGENT_REQUEST', message: '\"document\" is required for agent mode' },\n };\n return;\n }\n\n // The system prompt is built once from the *initial* document: the outline the model\n // starts from stays stable across steps, which keeps the prompt prefix cacheable. Edits\n // made mid-run are reflected in tool results, and the model can always call\n // get_page_outline for a refreshed view.\n const systemPrompt = buildAgentSystemPrompt({\n catalog: this.catalog,\n document: request.document,\n selectedNodeId: request.selectedNodeId,\n prefix: this.options.systemPromptPrefix,\n stylePreference: request.stylePreference,\n additionalContext: request.systemPrompt,\n });\n\n const toolDefinitions = toToolDefinitions(this.tools);\n const messages: AiChatMessage[] = [...request.messages];\n const ops: AgentOpRecord[] = [];\n\n let snapshot: PageDocument = request.document;\n let promptTokens = 0;\n let completionTokens = 0;\n let summary = '';\n let stoppedBy: AiAgentRunResult['stoppedBy'] = 'complete';\n let step = 0;\n\n this.log('info', `[AGENT] run started (maxSteps=${maxSteps}, tools=${toolDefinitions.length})`);\n\n try {\n while (step < maxSteps) {\n if (signal?.aborted) {\n stoppedBy = 'aborted';\n break;\n }\n\n step++;\n yield { type: 'agent-step', step, maxSteps };\n\n const result = await this.options.adapter.generate({\n systemPrompt,\n userPrompt: getMessageText(request.messages[request.messages.length - 1]),\n messages,\n tools: toolDefinitions,\n toolChoice: 'auto',\n signal,\n });\n\n promptTokens += result.usage?.promptTokens ?? 0;\n completionTokens += result.usage?.completionTokens ?? 0;\n\n const toolCalls = result.toolCalls ?? [];\n\n if (toolCalls.length === 0) {\n summary = result.text.trim();\n stoppedBy = 'complete';\n this.log('info', `[AGENT] finished after ${step} step(s) with ${ops.length} op(s)`);\n break;\n }\n\n // Record the assistant turn (text + tool calls) before the results, so the next\n // request replays a well-formed call/result pairing.\n const assistantBlocks: AiContentBlock[] = [];\n if (result.text.trim()) {\n assistantBlocks.push({ type: 'text', text: result.text });\n }\n assistantBlocks.push(...toolCalls);\n messages.push({ role: 'assistant', content: assistantBlocks, timestamp: Date.now() });\n\n const capped = toolCalls.slice(0, MAX_TOOL_CALLS_PER_STEP);\n const resultBlocks: AiContentBlock[] = [];\n\n for (const call of capped) {\n if (signal?.aborted) {\n stoppedBy = 'aborted';\n break;\n }\n\n yield { type: 'tool-call', id: call.id, name: call.name, input: call.input ?? {} };\n\n const executed = await this.executeToolCall(call, snapshot, signal);\n snapshot = executed.snapshot;\n resultBlocks.push(executed.block);\n if (executed.op) ops.push(executed.op);\n\n yield {\n type: 'tool-result',\n id: call.id,\n name: call.name,\n ok: executed.ok,\n summary: executed.summary,\n };\n }\n\n // Every tool call must get a matching result, or the next provider request is\n // malformed — so calls dropped by the per-step cap or by an abort are answered\n // explicitly rather than left dangling.\n for (const call of toolCalls.slice(capped.length)) {\n resultBlocks.push({\n type: 'tool_result',\n toolUseId: call.id,\n isError: true,\n content: JSON.stringify({\n ok: false,\n error: `Too many tool calls in one step (limit ${MAX_TOOL_CALLS_PER_STEP}). This call was not executed — request it again in the next step.`,\n }),\n });\n }\n\n messages.push(toolResultMessage(resultBlocks));\n\n if (stoppedBy === 'aborted') break;\n }\n\n if (stoppedBy === 'complete' && step >= maxSteps && !summary) {\n stoppedBy = 'max-steps';\n summary = `Berhenti setelah ${maxSteps} langkah. ${ops.length} perubahan sudah disiapkan — periksa hasilnya lalu minta lanjutan bila perlu.`;\n this.log('warn', `[AGENT] hit maxSteps (${maxSteps}) with ${ops.length} op(s)`);\n }\n\n if (stoppedBy === 'aborted' && !summary) {\n summary = `Dihentikan. ${ops.length} perubahan sempat disiapkan.`;\n }\n\n yield {\n type: 'agent-complete',\n result: {\n ops,\n summary,\n stepsUsed: step,\n stoppedBy,\n usage: { promptTokens, completionTokens },\n },\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.log('error', `[AGENT] run failed: ${message}`);\n // Ops produced before the failure are still valid and still reviewable — dropping\n // them would silently discard work the user can see happening in the timeline.\n yield {\n type: 'agent-complete',\n result: {\n ops,\n summary: summary || `Terjadi error: ${message}`,\n stepsUsed: step,\n stoppedBy: 'error',\n usage: { promptTokens, completionTokens },\n },\n };\n yield { type: 'error', error: { code: 'AGENT_ERROR', message } };\n }\n }\n\n /** Non-streaming convenience wrapper — drains `run()` and returns its terminal result. */\n async execute(\n request: AiAgentRequest,\n context?: { signal?: AbortSignal },\n ): Promise<AiAgentRunResult> {\n let final: AiAgentRunResult | null = null;\n let error: { code: string; message: string } | null = null;\n\n for await (const event of this.run(request, context)) {\n if (event.type === 'agent-complete') final = event.result;\n if (event.type === 'error') error = event.error;\n }\n\n if (final) return final;\n return {\n ops: [],\n summary: error?.message ?? 'Agent produced no result',\n stepsUsed: 0,\n stoppedBy: 'error',\n };\n }\n}\n","import type { KubuildAiEngine } from './engine';\nimport type { KubuildAiAgent } from './agent';\nimport type { PageDocument } from '@kubuild/schema';\nimport type {\n AiGeneratePageRequest,\n AiGenerateSectionRequest,\n AiRefactorNodeRequest,\n AiChatMessage,\n AiGenerateResponse,\n AiGenerationMode,\n AiStreamEvent,\n PagePlan,\n} from '../types';\n\nexport interface AiApiRequestBody {\n mode?: AiGenerationMode;\n prompt?: string;\n stylePreference?: string;\n tone?: string;\n locale?: string;\n metadata?: AiGeneratePageRequest['metadata'];\n targetSectionType?: string;\n parentContext?: string;\n node?: AiRefactorNodeRequest['node'];\n instruction?: string;\n stream?: boolean;\n messages?: AiChatMessage[];\n currentDocument?: PageDocument;\n selectedNodeId?: string;\n /** Prior conversation history from chat mode so generator keeps full context. */\n conversationHistory?: AiChatMessage[];\n sectionCount?: number | { min?: number; max?: number };\n plan?: PagePlan;\n /** Agent mode (STORA-530) — the snapshot the agent reads and patches. */\n document?: PageDocument;\n maxSteps?: number;\n}\n\nexport async function processAiRequest(\n engine: KubuildAiEngine,\n body: unknown,\n signal?: AbortSignal,\n agent?: KubuildAiAgent,\n): Promise<{ status: number; response: AiGenerateResponse<unknown> }> {\n if (!body || typeof body !== 'object') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'BAD_REQUEST',\n message: 'Request body must be a valid JSON object',\n },\n },\n };\n }\n\n const payload = body as AiApiRequestBody;\n const mode = payload.mode || 'full-page';\n\n if (mode === 'full-page') {\n if (!payload.prompt || typeof payload.prompt !== 'string') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for full-page generation',\n },\n },\n };\n }\n const result = await engine.generatePage(\n {\n prompt: payload.prompt,\n stylePreference: payload.stylePreference,\n tone: payload.tone,\n locale: payload.locale,\n metadata: payload.metadata,\n conversationHistory: payload.conversationHistory ?? payload.messages,\n sectionCount: payload.sectionCount,\n plan: payload.plan,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'section') {\n if (!payload.prompt || typeof payload.prompt !== 'string') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for section generation',\n },\n },\n };\n }\n const result = await engine.generateSection(\n {\n prompt: payload.prompt,\n stylePreference: payload.stylePreference,\n targetSectionType: payload.targetSectionType,\n parentContext: payload.parentContext,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'refactor') {\n if (!payload.node || !payload.instruction) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_REFACTOR_PARAMS',\n message: '\"node\" and \"instruction\" are required for refactoring',\n },\n },\n };\n }\n const result = await engine.refactorNode(\n {\n node: payload.node,\n instruction: payload.instruction,\n stylePreference: payload.stylePreference,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'chat') {\n if (!payload.messages || !Array.isArray(payload.messages) || payload.messages.length === 0) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_CHAT_PARAMS',\n message: '\"messages\" array is required and must not be empty for chat mode',\n },\n },\n };\n }\n const result = await engine.chat(\n {\n messages: payload.messages,\n currentDocument: payload.currentDocument,\n selectedNodeId: payload.selectedNodeId,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n if (mode === 'agent') {\n const validationError = validateAgentPayload(payload, agent);\n if (validationError) {\n return { status: validationError.status, response: validationError.response };\n }\n\n const result = await agent!.execute(\n {\n messages: payload.messages!,\n document: payload.document!,\n selectedNodeId: payload.selectedNodeId,\n stylePreference: payload.stylePreference,\n maxSteps: payload.maxSteps,\n },\n { signal },\n );\n\n return {\n status: result.stoppedBy === 'error' ? 500 : 200,\n response: { success: result.stoppedBy !== 'error', data: result },\n };\n }\n\n if (mode === 'plan') {\n if (!payload.prompt || typeof payload.prompt !== 'string') {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for planning mode',\n },\n },\n };\n }\n const result = await engine.planPage(\n {\n prompt: payload.prompt,\n stylePreference: payload.stylePreference,\n tone: payload.tone,\n locale: payload.locale,\n sectionCount: payload.sectionCount,\n conversationHistory: payload.conversationHistory ?? payload.messages,\n },\n { signal },\n );\n return {\n status: result.success ? 200 : 500,\n response: result,\n };\n }\n\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'UNKNOWN_MODE',\n message: `Unsupported mode: ${String(mode)}. Supported modes: 'full-page', 'section', 'refactor', 'chat', 'agent', 'plan'`,\n },\n },\n };\n}\n\n/**\n * Shared validation for agent-mode requests (STORA-530) — used by both the JSON and the\n * SSE paths so they can never disagree about what a valid agent request looks like.\n * Returns `null` when the payload is good.\n */\nfunction validateAgentPayload(\n payload: AiApiRequestBody,\n agent?: KubuildAiAgent,\n): { status: number; response: AiGenerateResponse<never> } | null {\n if (!agent) {\n return {\n status: 501,\n response: {\n success: false,\n error: {\n code: 'AGENT_NOT_CONFIGURED',\n message:\n 'Agent mode is not enabled on this endpoint. Pass a KubuildAiAgent to createAiHandler to enable it.',\n },\n },\n };\n }\n\n if (!payload.messages || !Array.isArray(payload.messages) || payload.messages.length === 0) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_AGENT_PARAMS',\n message: '\"messages\" array is required and must not be empty for agent mode',\n },\n },\n };\n }\n\n if (!payload.document || !payload.document.document) {\n return {\n status: 400,\n response: {\n success: false,\n error: {\n code: 'INVALID_AGENT_PARAMS',\n message: '\"document\" (the current PageDocument) is required for agent mode',\n },\n },\n };\n }\n\n return null;\n}\n\n/**\n * Options for {@link createAiHandler} (STORA-519).\n */\nexport interface CreateAiHandlerOptions {\n /**\n * Enables agent mode (STORA-530) on this endpoint. Without it, `mode: 'agent'` requests\n * are answered with a 501 rather than silently falling back to chat.\n */\n agent?: KubuildAiAgent;\n\n /**\n * Optional hook invoked with the raw incoming `Request` before it ever reaches the\n * engine/provider — the place to plug in host-owned auth and/or rate-limiting without\n * forking the handler.\n *\n * - Return a `Response` (or a Promise resolving to one) to reject/short-circuit the\n * request — e.g. `new Response(..., { status: 401 })` or `429` — that response is\n * returned as-is and the engine/provider is never invoked.\n * - Return `void`/`undefined` (or a Promise resolving to that) to allow the request to\n * continue through the normal handler logic unchanged.\n *\n * Omitting this option entirely preserves the exact pre-STORA-519 behavior.\n */\n beforeRequest?: (request: Request) => Promise<Response | void> | Response | void;\n}\n\n/**\n * Pipes an `AiStreamEvent` iterable out as an SSE response (STORA-530).\n *\n * All three streaming modes (`streamPage`, `chatStream`, agent `run`) emit the same event\n * shape over the same transport, so they share one encoder instead of three near-identical\n * `ReadableStream` blocks. A throw mid-stream is delivered as a final `error` event rather\n * than tearing down the connection, so the client can render it in place.\n */\nfunction sseResponse(\n events: AsyncIterable<AiStreamEvent>,\n errorCode: string,\n): Response {\n const encoder = new TextEncoder();\n const readable = new ReadableStream({\n async start(controller) {\n try {\n for await (const event of events) {\n controller.enqueue(\n encoder.encode(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`),\n );\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n controller.enqueue(\n encoder.encode(\n `event: error\\ndata: ${JSON.stringify({ type: 'error', error: { code: errorCode, message } })}\\n\\n`,\n ),\n );\n } finally {\n controller.close();\n }\n },\n });\n\n return new Response(readable, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n },\n });\n}\n\n/**\n * Creates a standard Web Fetch API Request handler with optional SSE streaming support.\n *\n * Plug-and-play for Next.js App Router (route.ts), SvelteKit, Remix, Astro, Bun, etc.\n *\n * Example:\n * ```ts\n * export const POST = createAiHandler(engine);\n * ```\n *\n * Example with an auth/rate-limit hook (STORA-519):\n * ```ts\n * export const POST = createAiHandler(engine, {\n * beforeRequest: async (request) => {\n * if (!isAuthorized(request)) {\n * return new Response('Unauthorized', { status: 401 });\n * }\n * // returning nothing lets the request proceed as normal\n * },\n * });\n * ```\n */\nexport function createAiHandler(engine: KubuildAiEngine, options?: CreateAiHandlerOptions) {\n return async (request: Request): Promise<Response> => {\n try {\n if (options?.beforeRequest) {\n const hookResult = await options.beforeRequest(request);\n if (hookResult instanceof Response) {\n return hookResult;\n }\n }\n\n if (request.method !== 'POST') {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'METHOD_NOT_ALLOWED',\n message: 'Only POST requests are accepted',\n },\n }),\n {\n status: 405,\n headers: {\n 'Content-Type': 'application/json',\n Allow: 'POST',\n },\n },\n );\n }\n\n const body = (await request.json().catch(() => null)) as AiApiRequestBody | null;\n\n // Handle opt-in SSE Streaming\n if (body && typeof body === 'object' && body.stream === true) {\n const mode = body.mode || 'full-page';\n\n // Agent streaming (STORA-530) — emits agent-step/tool-call/tool-result events as\n // the loop runs, then a terminal agent-complete carrying the ops to replay.\n if (mode === 'agent') {\n const validationError = validateAgentPayload(body, options?.agent);\n if (validationError) {\n return new Response(JSON.stringify(validationError.response), {\n status: validationError.status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n return sseResponse(\n options!.agent!.run(\n {\n messages: body.messages!,\n document: body.document!,\n selectedNodeId: body.selectedNodeId,\n stylePreference: body.stylePreference,\n maxSteps: body.maxSteps,\n },\n { signal: request.signal },\n ),\n 'AGENT_STREAM_ERROR',\n );\n }\n\n // Token-level chat streaming (STORA-515) — routed separately from full-page\n // streaming below since it needs `messages`, not `prompt`.\n if (mode === 'chat') {\n if (!body.messages || !Array.isArray(body.messages) || body.messages.length === 0) {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INVALID_CHAT_PARAMS',\n message: '\"messages\" array is required and must not be empty for chat mode',\n },\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n },\n );\n }\n\n return sseResponse(\n engine.chatStream(\n {\n messages: body.messages!,\n currentDocument: body.currentDocument,\n selectedNodeId: body.selectedNodeId,\n },\n { signal: request.signal },\n ),\n 'CHAT_STREAM_ERROR',\n );\n }\n\n if (!body.prompt || typeof body.prompt !== 'string') {\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INVALID_PROMPT',\n message: '\"prompt\" is required for streaming generation',\n },\n }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n },\n );\n }\n\n return sseResponse(\n engine.streamPage(\n {\n prompt: body.prompt!,\n stylePreference: body.stylePreference,\n tone: body.tone,\n locale: body.locale,\n metadata: body.metadata,\n conversationHistory: body.conversationHistory ?? body.messages,\n sectionCount: body.sectionCount,\n plan: body.plan,\n },\n { signal: request.signal },\n ),\n 'STREAM_ERROR',\n );\n }\n\n // Default: Standard non-streaming JSON response (Backward-compatible)\n const { status, response } = await processAiRequest(\n engine,\n body,\n request.signal,\n options?.agent,\n );\n\n return new Response(JSON.stringify(response), {\n status,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return new Response(\n JSON.stringify({\n success: false,\n error: {\n code: 'INTERNAL_SERVER_ERROR',\n message,\n },\n }),\n {\n status: 500,\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n }\n };\n}\n","/**\n * Shared SSE (server-sent events) frame reader for provider adapters that support\n * token-level streaming (STORA-515) — OpenAI, Anthropic and Gemini all expose their\n * streaming APIs as `data: <json>\\n\\n` frames, so every adapter reuses this single\n * low-level reader instead of re-implementing buffering/decoding three times.\n *\n * Yields the raw string payload of each `data:` line (already trimmed), in arrival\n * order. Callers are responsible for `JSON.parse`-ing (or ignoring sentinel values\n * like OpenAI's `[DONE]`) and for interpreting provider-specific event shapes.\n */\nexport async function* readSseDataLines(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n): AsyncGenerator<string, void, void> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n if (signal?.aborted) {\n throw new Error('Streaming aborted by client');\n }\n\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop() || '';\n\n for (const frame of frames) {\n for (const line of frame.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data:')) {\n yield trimmed.slice(5).trim();\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { readSseDataLines } from './stream-utils';\nimport { getMessageText } from '../../core/messages';\n\nexport interface GeminiAdapterOptions {\n apiKey: string;\n model?: string;\n temperature?: number;\n baseUrl?: string;\n}\n\nexport class GeminiAdapter implements AiProviderAdapter {\n readonly name = 'gemini';\n private apiKey: string;\n private model: string;\n private temperature: number;\n private baseUrl: string;\n\n constructor(options: GeminiAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('GeminiAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'gemini-2.5-flash';\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl =\n options.baseUrl || 'https://generativelanguage.googleapis.com/v1beta';\n }\n\n private buildContents(\n params: AiProviderGenerateParams,\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n const { userPrompt, messages: chatMessages } = params;\n return chatMessages && chatMessages.length > 0\n ? chatMessages.map((m) => ({\n role: m.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: getMessageText(m) }],\n }))\n : [\n {\n role: 'user',\n parts: [{ text: userPrompt }],\n },\n ];\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const { systemPrompt, messages: chatMessages, signal } = params;\n\n const url = `${this.baseUrl}/models/${encodeURIComponent(this.model)}:generateContent?key=${encodeURIComponent(this.apiKey)}`;\n const contents = this.buildContents(params);\n\n const generationConfig: Record<string, unknown> = {\n temperature: this.temperature,\n };\n\n if (params.jsonSchema || (!chatMessages && (systemPrompt.includes('JSON') || systemPrompt.includes('json')))) {\n generationConfig.responseMimeType = 'application/json';\n }\n\n const body: Record<string, unknown> = {\n system_instruction: {\n parts: [{ text: systemPrompt }],\n },\n contents,\n generationConfig,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Gemini API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const data = (await res.json()) as {\n candidates?: Array<{\n content?: {\n parts?: Array<{ text?: string }>;\n };\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n };\n };\n\n const candidateText = data.candidates?.[0]?.content?.parts?.[0]?.text;\n if (!candidateText) {\n throw new Error('Gemini returned an empty or invalid candidate response');\n }\n\n return {\n text: candidateText,\n usage: data.usageMetadata\n ? {\n promptTokens: data.usageMetadata.promptTokenCount,\n completionTokens: data.usageMetadata.candidatesTokenCount,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via Gemini's `streamGenerateContent` SSE endpoint (STORA-515).\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { systemPrompt, signal } = params;\n const url = `${this.baseUrl}/models/${encodeURIComponent(this.model)}:streamGenerateContent?alt=sse&key=${encodeURIComponent(this.apiKey)}`;\n const contents = this.buildContents(params);\n\n const generationConfig: Record<string, unknown> = {\n temperature: this.temperature,\n };\n\n const body: Record<string, unknown> = {\n system_instruction: {\n parts: [{ text: systemPrompt }],\n },\n contents,\n generationConfig,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Gemini API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n if (!res.body) {\n throw new Error('Gemini streaming response has no readable body');\n }\n\n let text = '';\n let usage: AiProviderGenerateResult['usage'];\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n let parsed: {\n candidates?: Array<{ content?: { parts?: Array<{ text?: string }> } }>;\n usageMetadata?: { promptTokenCount?: number; candidatesTokenCount?: number };\n };\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n\n const delta = parsed.candidates?.[0]?.content?.parts?.[0]?.text;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n\n if (parsed.usageMetadata) {\n usage = {\n promptTokens: parsed.usageMetadata.promptTokenCount,\n completionTokens: parsed.usageMetadata.candidatesTokenCount,\n };\n }\n }\n\n return { text, usage };\n }\n}\n","import type {\n AiChatMessage,\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n AiStopReason,\n AiToolUseBlock,\n} from '../../types';\nimport { getMessageText, getToolResultBlocks, getToolUseBlocks } from '../../core/messages';\nimport { readSseDataLines } from './stream-utils';\n\nexport interface OpenAiAdapterOptions {\n apiKey: string;\n model?: string;\n temperature?: number;\n baseUrl?: string;\n headers?: Record<string, string>;\n}\n\n/** OpenAI Chat Completions message shape — `tool_calls`/`role: 'tool'` included. */\ninterface OpenAiMessage {\n role: 'system' | 'user' | 'assistant' | 'tool';\n content: string | null;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n }>;\n tool_call_id?: string;\n}\n\ninterface OpenAiToolCallPayload {\n id?: string;\n type?: string;\n function?: { name?: string; arguments?: string };\n}\n\n/**\n * Maps OpenAI's `finish_reason` onto the provider-agnostic `AiStopReason` the agent loop\n * branches on (STORA-530).\n */\nfunction mapStopReason(finishReason: string | undefined | null): AiStopReason {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'tool_calls':\n case 'function_call':\n return 'tool_calls';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content_filter';\n default:\n return 'unknown';\n }\n}\n\n/**\n * Parses OpenAI `tool_calls` into `AiToolUseBlock`s. A call whose `arguments` isn't valid\n * JSON is surfaced with an empty `input` rather than throwing: the agent's tool executor\n * then rejects it with a `tool_result` error and the model self-corrects on the next step,\n * which is far better than killing the whole run over one malformed argument blob.\n */\nfunction parseToolCalls(raw: OpenAiToolCallPayload[] | undefined): AiToolUseBlock[] {\n if (!Array.isArray(raw) || raw.length === 0) return [];\n return raw\n .filter((call) => call?.function?.name)\n .map((call, index) => {\n let input: Record<string, unknown> = {};\n const argsText = call.function?.arguments;\n if (argsText && argsText.trim()) {\n try {\n const parsed = JSON.parse(argsText);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n input = parsed as Record<string, unknown>;\n }\n } catch {\n input = {};\n }\n }\n return {\n type: 'tool_use' as const,\n id: call.id || `call_${index}`,\n name: call.function!.name!,\n input,\n };\n });\n}\n\nexport class OpenAiAdapter implements AiProviderAdapter {\n readonly name = 'openai';\n readonly supportsTools = true;\n private apiKey: string;\n private model: string;\n private temperature: number;\n private baseUrl: string;\n private customHeaders?: Record<string, string>;\n\n constructor(options: OpenAiAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('OpenAiAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'gpt-4o';\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl = (options.baseUrl || 'https://api.openai.com/v1').replace(/\\/+$/, '');\n this.customHeaders = options.headers;\n }\n\n /**\n * Expands one `AiChatMessage` into the one-or-more OpenAI messages it corresponds to\n * (STORA-530).\n *\n * The block model is Anthropic-shaped — tool results ride along inside a `user` message —\n * while OpenAI wants each result as its own `role: 'tool'` message keyed by\n * `tool_call_id`. That fan-out happens here so the rest of the stack stays\n * provider-agnostic.\n */\n private mapMessage(message: AiChatMessage): OpenAiMessage[] {\n const toolUses = getToolUseBlocks(message);\n const toolResults = getToolResultBlocks(message);\n const text = getMessageText(message);\n\n if (toolResults.length > 0) {\n const results: OpenAiMessage[] = toolResults.map((block) => ({\n role: 'tool',\n content: block.content,\n tool_call_id: block.toolUseId,\n }));\n // Any free text riding alongside tool results becomes a separate user turn — OpenAI\n // rejects a `role: 'tool'` message that carries anything but the result payload.\n if (text.trim()) {\n results.push({ role: 'user', content: text });\n }\n return results;\n }\n\n if (toolUses.length > 0) {\n return [\n {\n role: 'assistant',\n content: text.trim() ? text : null,\n tool_calls: toolUses.map((block) => ({\n id: block.id,\n type: 'function' as const,\n function: {\n name: block.name,\n arguments: JSON.stringify(block.input ?? {}),\n },\n })),\n },\n ];\n }\n\n return [{ role: message.role, content: text }];\n }\n\n private buildMessages(params: AiProviderGenerateParams): OpenAiMessage[] {\n const { systemPrompt, userPrompt, messages: chatMessages } = params;\n if (chatMessages && chatMessages.length > 0) {\n return [\n { role: 'system', content: systemPrompt },\n ...chatMessages.flatMap((m) => this.mapMessage(m)),\n ];\n }\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userPrompt },\n ];\n }\n\n /**\n * Shared request body builder for `generate`/`generateStream` — notably the\n * `response_format` decision, which must never fire in tool mode: OpenAI rejects\n * `json_object` combined with `tools`, and a tool-calling turn's text output is a\n * natural-language summary, not JSON.\n */\n private buildBody(params: AiProviderGenerateParams): Record<string, unknown> {\n const { systemPrompt, jsonSchema, messages: chatMessages, tools, toolChoice } = params;\n\n const body: Record<string, unknown> = {\n model: this.model,\n temperature: params.temperature ?? this.temperature,\n messages: this.buildMessages(params),\n };\n\n if (tools && tools.length > 0) {\n body.tools = tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n },\n }));\n if (toolChoice) {\n body.tool_choice =\n typeof toolChoice === 'string'\n ? toolChoice\n : { type: 'function', function: { name: toolChoice.name } };\n }\n return body;\n }\n\n // Only force json_object when JSON schema is provided or specifically requested,\n // allowing natural conversation text in chat mode.\n if (jsonSchema || (!chatMessages && (systemPrompt.includes('JSON') || systemPrompt.includes('json')))) {\n body.response_format = { type: 'json_object' };\n }\n\n return body;\n }\n\n private async post(body: Record<string, unknown>, signal?: AbortSignal): Promise<Response> {\n const res = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `OpenAI API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n return res;\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const res = await this.post(this.buildBody(params), params.signal);\n\n const data = (await res.json()) as {\n choices?: Array<{\n finish_reason?: string;\n message?: {\n content?: string;\n tool_calls?: OpenAiToolCallPayload[];\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n };\n };\n\n const choice = data.choices?.[0];\n const content = choice?.message?.content;\n const toolCalls = parseToolCalls(choice?.message?.tool_calls);\n\n // A tool-calling turn legitimately has null content — only a turn with neither text\n // nor tool calls is an empty response worth throwing over.\n if (!content && toolCalls.length === 0) {\n throw new Error('OpenAI returned an empty message content');\n }\n\n return {\n text: content || '',\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n stopReason: mapStopReason(choice?.finish_reason),\n usage: data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via OpenAI's `stream: true` chat completions mode (STORA-515).\n * Yields each `delta.content` fragment as it arrives and returns the fully assembled\n * text + usage (when the final chunk includes it) once the stream ends.\n *\n * Tool calls arrive fragmented too (STORA-530): `delta.tool_calls[].function.arguments`\n * is delivered as a character stream across many chunks, keyed by array `index`. They're\n * accumulated per index and parsed only once the stream ends — parsing a partial\n * arguments string would always fail. Tool call deltas are never `yield`ed as text,\n * since they aren't part of the assistant's visible message.\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { signal } = params;\n const res = await this.post({ ...this.buildBody(params), stream: true }, signal);\n\n if (!res.body) {\n throw new Error('OpenAI streaming response has no readable body');\n }\n\n let text = '';\n let usage: AiProviderGenerateResult['usage'];\n let finishReason: string | undefined;\n const toolCallAccumulator = new Map<number, { id: string; name: string; arguments: string }>();\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n if (raw === '[DONE]') break;\n\n let parsed: {\n choices?: Array<{\n finish_reason?: string;\n delta?: {\n content?: string;\n tool_calls?: Array<OpenAiToolCallPayload & { index?: number }>;\n };\n }>;\n usage?: { prompt_tokens?: number; completion_tokens?: number };\n };\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n\n const choice = parsed.choices?.[0];\n\n const delta = choice?.delta?.content;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n\n for (const call of choice?.delta?.tool_calls ?? []) {\n const index = typeof call.index === 'number' ? call.index : 0;\n const entry = toolCallAccumulator.get(index) ?? { id: '', name: '', arguments: '' };\n if (call.id) entry.id = call.id;\n if (call.function?.name) entry.name = call.function.name;\n if (call.function?.arguments) entry.arguments += call.function.arguments;\n toolCallAccumulator.set(index, entry);\n }\n\n if (choice?.finish_reason) {\n finishReason = choice.finish_reason;\n }\n\n if (parsed.usage) {\n usage = {\n promptTokens: parsed.usage.prompt_tokens,\n completionTokens: parsed.usage.completion_tokens,\n };\n }\n }\n\n const toolCalls = parseToolCalls(\n Array.from(toolCallAccumulator.entries())\n .sort(([a], [b]) => a - b)\n .map(([, entry]) => ({\n id: entry.id,\n type: 'function',\n function: { name: entry.name, arguments: entry.arguments },\n })),\n );\n\n return {\n text,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n stopReason: mapStopReason(finishReason),\n usage,\n };\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { readSseDataLines } from './stream-utils';\nimport { getMessageText } from '../../core/messages';\n\nexport interface AnthropicAdapterOptions {\n apiKey: string;\n model?: string;\n maxTokens?: number;\n temperature?: number;\n baseUrl?: string;\n anthropicVersion?: string;\n headers?: Record<string, string>;\n}\n\nexport class AnthropicAdapter implements AiProviderAdapter {\n readonly name = 'anthropic';\n private apiKey: string;\n private model: string;\n private maxTokens: number;\n private temperature: number;\n private baseUrl: string;\n private anthropicVersion: string;\n private customHeaders?: Record<string, string>;\n\n constructor(options: AnthropicAdapterOptions) {\n if (!options.apiKey) {\n throw new Error('AnthropicAdapter requires an apiKey');\n }\n this.apiKey = options.apiKey;\n this.model = options.model || 'claude-3-5-sonnet-20241022';\n this.maxTokens = options.maxTokens ?? 4096;\n this.temperature = options.temperature ?? 0.4;\n this.baseUrl = (options.baseUrl || 'https://api.anthropic.com/v1').replace(/\\/+$/, '');\n this.anthropicVersion = options.anthropicVersion || '2023-06-01';\n this.customHeaders = options.headers;\n }\n\n private buildMessages(\n params: AiProviderGenerateParams,\n ): Array<{ role: 'user' | 'assistant'; content: string }> {\n const { userPrompt, messages: chatMessages } = params;\n return chatMessages && chatMessages.length > 0\n ? chatMessages\n .filter((m) => m.role === 'user' || m.role === 'assistant')\n .map((m) => ({ role: m.role as 'user' | 'assistant', content: getMessageText(m) }))\n : [\n {\n role: 'user' as const,\n content: userPrompt,\n },\n ];\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const { systemPrompt, signal } = params;\n\n const url = `${this.baseUrl}/messages`;\n const messages = this.buildMessages(params);\n\n const body: Record<string, unknown> = {\n model: this.model,\n max_tokens: this.maxTokens,\n temperature: this.temperature,\n system: systemPrompt,\n messages,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': this.anthropicVersion,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Anthropic API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const data = (await res.json()) as {\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const textPart = data.content?.find((c) => c.type === 'text')?.text;\n if (!textPart) {\n throw new Error('Anthropic returned an empty text content');\n }\n\n return {\n text: textPart,\n usage: data.usage\n ? {\n promptTokens: data.usage.input_tokens,\n completionTokens: data.usage.output_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Token-level streaming via Anthropic's `stream: true` Messages API (STORA-515).\n * Parses the `content_block_delta` (`text_delta`) events for incremental text and the\n * `message_start`/`message_delta` events for usage accounting.\n */\n async *generateStream(\n params: AiProviderGenerateParams,\n ): AsyncGenerator<string, AiProviderGenerateResult, void> {\n const { systemPrompt, signal } = params;\n const url = `${this.baseUrl}/messages`;\n const messages = this.buildMessages(params);\n\n const body: Record<string, unknown> = {\n model: this.model,\n max_tokens: this.maxTokens,\n temperature: this.temperature,\n system: systemPrompt,\n messages,\n stream: true,\n };\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.apiKey,\n 'anthropic-version': this.anthropicVersion,\n ...this.customHeaders,\n },\n body: JSON.stringify(body),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Anthropic API error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n if (!res.body) {\n throw new Error('Anthropic streaming response has no readable body');\n }\n\n let text = '';\n let promptTokens: number | undefined;\n let completionTokens: number | undefined;\n\n for await (const raw of readSseDataLines(res.body, signal)) {\n if (!raw) continue;\n\n let evt: {\n type?: string;\n delta?: { type?: string; text?: string };\n usage?: { output_tokens?: number };\n message?: { usage?: { input_tokens?: number } };\n };\n try {\n evt = JSON.parse(raw);\n } catch {\n continue;\n }\n\n if (evt.type === 'content_block_delta' && evt.delta?.type === 'text_delta') {\n const delta = evt.delta.text;\n if (typeof delta === 'string' && delta.length > 0) {\n text += delta;\n yield delta;\n }\n } else if (evt.type === 'message_start' && evt.message?.usage?.input_tokens !== undefined) {\n promptTokens = evt.message.usage.input_tokens;\n } else if (evt.type === 'message_delta' && evt.usage?.output_tokens !== undefined) {\n completionTokens = evt.usage.output_tokens;\n }\n }\n\n return {\n text,\n usage:\n promptTokens !== undefined || completionTokens !== undefined\n ? { promptTokens, completionTokens }\n : undefined,\n };\n }\n}\n","import type {\n AiProviderAdapter,\n AiProviderGenerateParams,\n AiProviderGenerateResult,\n} from '../../types';\nimport { getMessageText } from '../../core/messages';\n\nexport interface CustomHttpAdapterOptions {\n url: string;\n name?: string;\n headers?: Record<string, string>;\n formatRequestBody?: (params: AiProviderGenerateParams) => unknown;\n parseResponse?: (json: unknown) => string;\n}\n\nexport class CustomHttpAdapter implements AiProviderAdapter {\n readonly name: string;\n private url: string;\n private headers?: Record<string, string>;\n private formatRequestBody: (params: AiProviderGenerateParams) => unknown;\n private parseResponse: (json: unknown) => string;\n\n constructor(options: CustomHttpAdapterOptions) {\n if (!options.url) {\n throw new Error('CustomHttpAdapter requires a url');\n }\n this.url = options.url;\n this.name = options.name || 'custom-http';\n this.headers = options.headers;\n\n // Default body formatter (OpenAI compatible or Ollama chat compatible)\n this.formatRequestBody =\n options.formatRequestBody ||\n ((params) => ({\n messages:\n params.messages && params.messages.length > 0\n ? [\n { role: 'system', content: params.systemPrompt },\n ...params.messages.map((m) => ({ role: m.role, content: getMessageText(m) })),\n ]\n : [\n { role: 'system', content: params.systemPrompt },\n { role: 'user', content: params.userPrompt },\n ],\n }));\n\n // Default response parser\n this.parseResponse =\n options.parseResponse ||\n ((json: unknown) => {\n if (!json || typeof json !== 'object') {\n throw new Error('Response is not a valid JSON object');\n }\n const obj = json as Record<string, unknown>;\n if (typeof obj.response === 'string') return obj.response; // Ollama generate\n if (typeof obj.text === 'string') return obj.text;\n const choices = obj.choices as Array<{ message?: { content?: string } }>;\n if (Array.isArray(choices) && choices[0]?.message?.content) {\n return choices[0].message.content; // OpenAI format\n }\n const message = obj.message as { content?: string };\n if (message && typeof message.content === 'string') {\n return message.content; // Ollama chat format\n }\n throw new Error('Unable to extract generated text from custom HTTP response');\n });\n }\n\n async generate(params: AiProviderGenerateParams): Promise<AiProviderGenerateResult> {\n const body = this.formatRequestBody(params);\n\n const res = await fetch(this.url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.headers,\n },\n body: JSON.stringify(body),\n signal: params.signal,\n });\n\n if (!res.ok) {\n const errText = await res.text().catch(() => '');\n throw new Error(\n `Custom HTTP adapter error [${res.status} ${res.statusText}]: ${errText || 'Unknown error'}`,\n );\n }\n\n const json = await res.json();\n const text = this.parseResponse(json);\n\n return { text };\n }\n}\n"],"mappings":"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","names":["import_schema","import_schema","import_core","import_core"]}
|