theokit 0.30.0 → 0.30.2
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/LICENSE +201 -0
- package/dist/{actions-virtual-module-PBLLMJY4.js → actions-virtual-module-XHVLBFNN.js} +7 -7
- package/dist/actions-virtual-module-Z2IXNF72.js +0 -0
- package/dist/add-W6FNTAFS.js +0 -0
- package/dist/agent-I5QEOMCN.js +0 -0
- package/dist/agents-typed-client-5DCGDWFZ.js +0 -0
- package/dist/{app-typed-client-EXHUWPOI.js → app-typed-client-4PAUHTO6.js} +7 -7
- package/dist/app-typed-client-YCQC3MZ7.js +0 -0
- package/dist/aws-lambda-7GSCNLPY.js +0 -0
- package/dist/body-parser-web-FV5HWCY3.js +0 -0
- package/dist/boot/index.js +3 -3
- package/dist/broadcast-LUMOJIJT.js +0 -0
- package/dist/build-V2QEBE7I.js +0 -0
- package/dist/build-request-body-preview-QMWD2IXK.js +0 -0
- package/dist/bun-KP2KES6S.js +0 -0
- package/dist/check-PD2FTKMM.js +0 -0
- package/dist/chunk-2CVV6CNN.js +0 -0
- package/dist/chunk-45C3WUQ7.js +0 -0
- package/dist/{chunk-UYFZ6DDW.js → chunk-4MTCKE5I.js} +1 -189
- package/dist/chunk-4MTCKE5I.js.map +1 -0
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/chunk-63BUBV5L.js +64 -0
- package/dist/chunk-63BUBV5L.js.map +1 -0
- package/dist/chunk-AFVTEAES.js +0 -0
- package/dist/chunk-FOZIR3TG.js +0 -0
- package/dist/chunk-FRUEDJFX.js +0 -0
- package/dist/chunk-GDN3PXFH.js +0 -0
- package/dist/chunk-GEQJAFSV.js +0 -0
- package/dist/chunk-GSO77FSM.js +0 -0
- package/dist/{chunk-EHUT4FMG.js → chunk-HAOPVC47.js} +29 -27
- package/dist/{chunk-EHUT4FMG.js.map → chunk-HAOPVC47.js.map} +1 -1
- package/dist/chunk-HGZL5EOI.js +0 -0
- package/dist/chunk-HNBWZKIQ.js +0 -0
- package/dist/chunk-HZ6USUHC.js +191 -0
- package/dist/chunk-HZ6USUHC.js.map +1 -0
- package/dist/chunk-IEES3CHD.js +0 -0
- package/dist/chunk-JAIKGP3Q.js +0 -0
- package/dist/chunk-KXA37ONC.js +0 -0
- package/dist/chunk-M6NMS5LR.js +0 -0
- package/dist/chunk-P37RZRFV.js +0 -0
- package/dist/chunk-S7L6H3KP.js +0 -0
- package/dist/chunk-SPFMJAFW.js +326 -0
- package/dist/chunk-SPFMJAFW.js.map +1 -0
- package/dist/chunk-TERFLG67.js +0 -0
- package/dist/{chunk-DMGVH3VG.js → chunk-V3X5FWJA.js} +5 -62
- package/dist/chunk-V3X5FWJA.js.map +1 -0
- package/dist/chunk-VRVNM3QL.js +0 -0
- package/dist/chunk-WR4F4EEZ.js +0 -0
- package/dist/chunk-Y4TOVMNC.js +0 -0
- package/dist/chunk-YJWEADAW.js +0 -0
- package/dist/cloudflare-C6E5SPAE.js +0 -0
- package/dist/configure-agent-registry-ZOBVU3MV.js +0 -0
- package/dist/db-3UNAMSFK.js +0 -0
- package/dist/define-agent-tool-ChaGymol.d.ts +88 -0
- package/dist/deno-deploy-RFZN56X4.js +0 -0
- package/dist/dev-5ZQMWVFC.js +0 -0
- package/dist/dev-emit-EFQRBVYS.js +0 -0
- package/dist/dispatcher-EJHL6JMJ.js +0 -0
- package/dist/docker-LZZB4D5E.js +0 -0
- package/dist/generate-373DALPY.js +0 -0
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/info-2OOXFTJX.js +0 -0
- package/dist/{internal-api-JIR3HRKF.js → internal-api-QSP2HCUU.js} +20 -20
- package/dist/internal-api-Y5REPVUS.js +0 -0
- package/dist/load-config-3EAQTXPH.js +0 -0
- package/dist/mcp-VMKWB2BY.js +0 -0
- package/dist/netlify-PMLHVPN4.js +0 -0
- package/dist/node-BPJ3Z4DT.js +0 -0
- package/dist/openapi-ERYWAT3A.js +0 -0
- package/dist/registry-3NB7KOUI.js +0 -0
- package/dist/router-TLEAOFID.js +0 -0
- package/dist/routes-XNS3UM3B.js +0 -0
- package/dist/scan-7MJC6PYU.js +0 -0
- package/dist/schema-LYOLNHZ7.js +0 -0
- package/dist/server/agent/index.d.ts +387 -0
- package/dist/server/agent/index.js +43 -0
- package/dist/server/agent/index.js.map +1 -0
- package/dist/server/auth/index.js +1 -1
- package/dist/server/define/index.d.ts +3 -86
- package/dist/server/define/index.js +4 -2
- package/dist/server/index.d.ts +10 -387
- package/dist/server/index.js +112 -398
- package/dist/server/index.js.map +1 -1
- package/dist/server/jobs/index.js +4 -4
- package/dist/server/scan/index.js +1 -1
- package/dist/server/webhook/index.d.ts +4 -45
- package/dist/server-error-to-envelope-UUXDSLAZ.js +0 -0
- package/dist/server-routes-hmr-VZXOP5YT.js +0 -0
- package/dist/services-json-Y3XODNB5.js +0 -0
- package/dist/services-typed-client-32KMTTXR.js +0 -0
- package/dist/start-IFTLTEPZ.js +0 -0
- package/dist/static-MB2CD5Y3.js +0 -0
- package/dist/storage-manager-ZSQFLEYT.js +0 -0
- package/dist/theo-cloud-DQRP6S6M.js +0 -0
- package/dist/upgrade-readiness-ACGW44JC.js +0 -0
- package/dist/vercel-J6G7ZHYQ.js +0 -0
- package/dist/vite-plugin/index.js +11 -10
- package/dist/vite-plugin-BNI7YLCD.js +0 -0
- package/dist/webhook-types-CNUZY7o1.d.ts +45 -0
- package/package.json +14 -10
- package/dist/chunk-DMGVH3VG.js.map +0 -1
- package/dist/chunk-UYFZ6DDW.js.map +0 -1
- /package/dist/{actions-virtual-module-PBLLMJY4.js.map → actions-virtual-module-XHVLBFNN.js.map} +0 -0
- /package/dist/{app-typed-client-EXHUWPOI.js.map → app-typed-client-4PAUHTO6.js.map} +0 -0
- /package/dist/{internal-api-JIR3HRKF.js.map → internal-api-QSP2HCUU.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/agent/workflow-tool.ts","../src/server/agent/acp-tool.ts","../src/server/agent/vendor-agent-tool.ts","../src/server/agent/code-mode.ts","../src/server/agent/channel-webhook.ts","../src/server/agent/stream-agent-turn-in-process.ts","../src/server/agent/mcp-stdio.ts"],"sourcesContent":["/**\n * M26 (ADR-0041) — `createWorkflowTool`: wrap an SDK `Workflow` as a `CustomTool`.\n *\n * THIN adapter. `packages/workflows/` stays G13-forbidden — the workflow ENGINE is the SDK's\n * (`Workflow.create(...).run(input)`). This exposes an already-built `Workflow` to an agent as one\n * callable tool: it validates the tool input, delegates to `workflow.run(input)`, and shapes the\n * result for the model. It calls no LLM, dispatches no tool, and runs no orchestration of its own —\n * the SDK owns all of that (sdk-runtime.md / G2).\n */\nimport { z } from 'zod'\n\nimport { defineAgentTool, type CustomTool } from '../define/define-agent-tool.js'\n\n/**\n * Structural stand-in for the SDK `Workflow` (the adapter never imports the SDK type — keeps the\n * SDK an optional peer). Any object with a `run(input)` resolving to `{ status, output }` matches.\n */\nexport interface WorkflowLike {\n run(input: unknown): Promise<{ status: string; output: unknown; runId?: string }>\n}\n\n/** Config for {@link createWorkflowTool}. `inputSchema` defaults to an open object. */\nexport interface WorkflowToolConfig {\n /** Tool name surfaced to the LLM. */\n name: string\n /** Tool description surfaced to the LLM. */\n description: string\n /** Zod schema for the workflow input (defaults to `z.object({}).passthrough()`). */\n inputSchema?: z.ZodType\n}\n\n/** Statuses `Workflow.run` reports as a non-success terminal state. */\nconst FAILURE_STATUSES = new Set(['failed', 'error', 'cancelled', 'canceled'])\n\n/**\n * Wrap an SDK `Workflow` as a {@link CustomTool}. Fails fast if `workflow` does not expose a\n * `run()` method (the SDK Workflow contract), so a mis-wired call is caught at definition time, not\n * at the first invocation (error-handling.md).\n */\nexport function createWorkflowTool(workflow: WorkflowLike, config: WorkflowToolConfig): CustomTool {\n const runFn = (workflow as { run?: unknown } | null | undefined)?.run\n if (typeof runFn !== 'function') {\n throw new Error(\n 'createWorkflowTool: the SDK does not expose a Workflow (expected an object with a run() method). ' +\n 'Pass a `Workflow.create(...).…build()` instance from @theokit/sdk.',\n )\n }\n // Open object by default so arbitrary workflow inputs pass through un-stripped.\n const inputSchema = config.inputSchema ?? z.looseObject({})\n\n return defineAgentTool({\n name: config.name,\n description: config.description,\n inputSchema: inputSchema as z.ZodObject<z.ZodRawShape>,\n handler: async (input: unknown): Promise<string> => {\n const run = await workflow.run(input)\n if (FAILURE_STATUSES.has(run.status)) {\n throw new Error(\n `createWorkflowTool(${JSON.stringify(config.name)}): workflow run ${\n run.runId ? `'${run.runId}' ` : ''\n }failed with status '${run.status}'.`,\n )\n }\n return typeof run.output === 'string' ? run.output : JSON.stringify(run.output)\n },\n })\n}\n","/**\n * M17 (theokit-ai-first) — createACPTool: wrap a coding agent (Claude Code, Amp, Codex) as a tool.\n *\n * Spawns the agent as a subprocess (Node `child_process` — an adapter concern per G8), drives it\n * with the transport-agnostic {@link AcpClient} over newline-delimited JSON-RPC, and returns a\n * `CustomTool`. `onPermissionRequest` is REQUIRED — security by default (no default-allow for file/\n * shell operations). The transport is injectable for tests.\n */\nimport { spawn, type ChildProcessByStdio } from 'node:child_process'\nimport type { Readable, Writable } from 'node:stream'\n\nimport { AcpClient, type AcpTransport } from '@theokit/agents'\nimport { encodeAcpMessage } from '@theokit/agents'\nimport type { CustomTool } from '@theokit/sdk'\n\n/** Stdio transport backed by a spawned subprocess (the default for {@link createACPTool}). */\nexport class NodeAcpTransport implements AcpTransport {\n // stdin=pipe, stdout=pipe, stderr=inherit → the third stream is null.\n private readonly proc: ChildProcessByStdio<Writable, Readable, null>\n\n constructor(command: string, args: string[] = [], cwd?: string) {\n this.proc = spawn(command, args, { cwd, stdio: ['pipe', 'pipe', 'inherit'] })\n }\n\n send(line: string): void {\n this.proc.stdin.write(line)\n }\n\n subscribe(onData: (chunk: string) => void): void {\n this.proc.stdout.on('data', (buf: Buffer) => {\n onData(buf.toString('utf8'))\n })\n }\n\n close(): void {\n this.proc.kill()\n }\n}\n\nexport interface AcpToolConfig {\n /** Executable for the coding agent (e.g. `claude`, `amp`, `codex`). */\n command: string\n /** Command-line arguments. */\n args?: string[]\n /** Working directory for the spawned agent. */\n cwd?: string\n /** Tool name the model calls. */\n name: string\n /** Tool description surfaced to the model. */\n description: string\n /**\n * REQUIRED — decide file/shell permission requests from the coding agent. Security by default:\n * there is NO default-allow. Return `{ granted: boolean }` (may be async).\n */\n onPermissionRequest: (params: unknown) => { granted: boolean } | Promise<{ granted: boolean }>\n /** Injected transport factory (defaults to spawning via {@link NodeAcpTransport}) — for tests. */\n transportFactory?: (config: AcpToolConfig) => AcpTransport\n}\n\nfunction defaultTransport(config: AcpToolConfig): AcpTransport {\n return new NodeAcpTransport(config.command, config.args, config.cwd)\n}\n\n/** Wrap a coding agent as a `CustomTool`. Fails fast if `onPermissionRequest` is missing. */\nexport function createACPTool(config: AcpToolConfig): CustomTool {\n if (typeof config.onPermissionRequest !== 'function') {\n throw new Error('[theokit] createACPTool requires onPermissionRequest (security by default — no default-allow)')\n }\n const makeTransport = config.transportFactory ?? defaultTransport\n return {\n name: config.name,\n description: config.description,\n inputSchema: {\n type: 'object',\n properties: { message: { type: 'string', description: 'The task/prompt for the coding agent.' } },\n required: ['message'],\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const message = typeof input.message === 'string' ? input.message : ''\n const client = new AcpClient(makeTransport(config))\n client.onRequest('session/request_permission', (params) => config.onPermissionRequest(params))\n const result = (await client.request('session/prompt', { message })) as { text?: string }\n return result.text ?? ''\n },\n }\n}\n\n// `encodeAcpMessage` is re-exported for callers building custom transports/handshakes.\nexport { encodeAcpMessage }\n","/**\n * M28 (ADR-0041) — `createVendorAgentTool`: expose a third-party agent SDK (Claude Agent SDK,\n * OpenAI, Cursor) behind a uniform `CustomTool`, mirroring the M17 ACP pattern.\n *\n * The vendor RUNTIME stays theirs — TheoKit only wires. The vendor client is INJECTED (the real\n * vendor SDK client in prod, a fake in tests), so no vendor dependency enters core; vendor-specific\n * client packages belong under `@theokit/agent-*`, never here. This calls no LLM of its own and runs\n * no loop — it delegates each prompt to `client.query(...)` (sdk-runtime.md / G2). Resume is threaded\n * via the vendor's own session id.\n */\nimport type { CustomTool } from '../define/define-agent-tool.js'\n\n/**\n * Structural contract a vendor agent client must satisfy (the adapter never imports a vendor type).\n * `query` runs one turn; `resumeSessionId` continues a prior vendor session; the returned\n * `sessionId` identifies the session to resume next.\n */\nexport interface VendorAgentClient {\n query(\n prompt: string,\n opts?: { resumeSessionId?: string },\n ): Promise<{ text: string; sessionId?: string }>\n}\n\n/** Config for {@link createVendorAgentTool}. */\nexport interface VendorAgentToolConfig {\n /** Vendor label (e.g. `claude`, `openai`, `cursor`). Drives the default tool name. */\n vendor: string\n /** The injected vendor client (real SDK client in prod, a fake in tests). */\n client: VendorAgentClient\n /** Tool name the model calls (defaults to `<vendor>_agent`). */\n name?: string\n /** Tool description surfaced to the model (defaults to a one-line delegate hint). */\n description?: string\n /**\n * Side-channel callback invoked with the vendor session id after each turn — lets the app capture\n * it for a later resume WITHOUT leaking session bookkeeping into the model's view of the result.\n */\n onSession?: (sessionId: string) => void\n}\n\n/**\n * Wrap a vendor agent SDK as a {@link CustomTool}. Fails fast if `vendor` is empty or the client\n * does not expose `query()` (error-handling.md) — a mis-wired call is caught at definition time.\n */\nexport function createVendorAgentTool(config: VendorAgentToolConfig): CustomTool {\n if (!config.vendor || config.vendor.length === 0) {\n throw new Error('createVendorAgentTool: `vendor` is required (e.g. \"claude\", \"openai\").')\n }\n const queryFn = (config.client as { query?: unknown } | null | undefined)?.query\n if (typeof queryFn !== 'function') {\n throw new Error(\n `createVendorAgentTool(${JSON.stringify(config.vendor)}): the vendor client does not expose a query() method. ` +\n 'Pass the vendor SDK client (or a @theokit/agent-* wrapper).',\n )\n }\n\n const name = config.name ?? `${config.vendor}_agent`\n const description =\n config.description ?? `Delegate a task to the ${config.vendor} agent and return its answer.`\n\n return {\n name,\n description,\n inputSchema: {\n type: 'object',\n properties: {\n prompt: { type: 'string', description: 'The task/prompt for the vendor agent.' },\n resumeSessionId: {\n type: 'string',\n description: 'Optional vendor session id to resume a prior conversation.',\n },\n },\n required: ['prompt'],\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const prompt = typeof input.prompt === 'string' ? input.prompt : ''\n const resumeSessionId =\n typeof input.resumeSessionId === 'string' ? input.resumeSessionId : undefined\n const result = await config.client.query(\n prompt,\n resumeSessionId !== undefined ? { resumeSessionId } : undefined,\n )\n if (result.sessionId !== undefined && config.onSession) config.onSession(result.sessionId)\n return result.text\n },\n }\n}\n","/**\n * M29 (ADR-0041) — `createCodeMode`: expose a set of tools to agent-authored code run inside an\n * ISOLATION boundary, so the agent composes tools programmatically instead of one call at a time.\n *\n * Security posture (the whole point of this feature):\n * - The isolation boundary (`sandbox`) is **injected**, never hand-rolled here (Top-risk 1). The app\n * supplies a vetted sandbox — isolated-vm, QuickJS-WASM, or a locked-down worker. TheoKit core\n * ships no VM and adds no sandbox dependency (same posture as the injected deploy adapter / the\n * M17 transport). `node:vm` is NOT a security boundary and MUST NOT be used as the sandbox.\n * - TheoKit owns the **restricted API** (only the declared tools are reachable from the code — no\n * `fs`, `process`, `require`, or network unless a declared, permission-gated tool provides it) and\n * the **mandatory permission gate**: every tool call from the code passes `onPermissionRequest`\n * first, and there is NO default-allow (mirrors M17 `onPermissionRequest`).\n *\n * Threat model (summary): a malicious model could author code that (a) calls a dangerous tool, or\n * (b) tries to reach a host capability. (a) is stopped by the permission gate (deny → the API call\n * throws). (b) is stopped by the injected sandbox (the restricted API is the ONLY surface the code\n * sees). If the app injects a weak sandbox, (b) is on the app — hence the vetted-sandbox requirement.\n */\nimport type { CustomTool } from '../define/define-agent-tool.js'\n\n/** The restricted API handed to sandboxed code: declared tool names → permission-gated callables. */\nexport type CodeModeApi = Record<string, (args: unknown) => Promise<unknown>>\n\n/** The injected isolation boundary. The app supplies a vetted implementation. */\nexport interface Sandbox {\n /** Run `code` with access to ONLY `api` (the restricted tool surface). Resolve the code's result. */\n run(code: string, api: CodeModeApi): Promise<unknown>\n}\n\n/** A permission decision for one tool call from sandboxed code. */\nexport interface CodeModePermission {\n granted: boolean\n /** Optional reason surfaced to the model on denial. */\n reason?: string\n}\n\nexport interface CodeModeConfig {\n /** The tools reachable from the code (the restricted API). */\n tools: CustomTool[]\n /** The injected isolation boundary (vetted sandbox — NEVER node:vm). */\n sandbox: Sandbox\n /**\n * REQUIRED — decide each tool call the code attempts. Security by default: NO default-allow.\n * Return `{ granted }` (may be async). Mirrors M17 `onPermissionRequest`.\n */\n onPermissionRequest: (req: {\n tool: string\n args: unknown\n }) => CodeModePermission | Promise<CodeModePermission>\n /** Tool name the model calls (default `run_code`). */\n name?: string\n /** Tool description surfaced to the model. */\n description?: string\n}\n\n/** Thrown when the permission gate denies a tool call from sandboxed code. */\nexport class CodeModePermissionDeniedError extends Error {\n constructor(tool: string, reason?: string) {\n const suffix = reason ? `: ${reason}` : ''\n super(`code-mode: tool '${tool}' denied by permission gate${suffix}`)\n this.name = 'CodeModePermissionDeniedError'\n }\n}\n\n/** M40 (ADR-0049) — render a tool's JSON-Schema input as a readable arg shape, e.g. `{ limit: number, region?: string }`. */\nfunction describeToolInput(inputSchema: Record<string, unknown>): string {\n const props = (inputSchema.properties as Record<string, { type?: unknown }> | undefined) ?? {}\n const required = new Set((inputSchema.required as string[] | undefined) ?? [])\n const entries = Object.entries(props).map(([key, spec]) => {\n // Complex Zod types (union/intersection/enum) may emit no top-level `type` → 'unknown' (safe).\n const type = typeof spec.type === 'string' ? spec.type : 'unknown'\n return `${key}${required.has(key) ? '' : '?'}: ${type}`\n })\n return entries.length > 0 ? `{ ${entries.join(', ')} }` : '{}'\n}\n\n/**\n * M40 (ADR-0049) — generate the model-facing instructions from the SAME `tools` allow-list\n * `createCodeMode` captures (DRY — cannot drift from the api surface it describes). Teaches the model\n * that its code runs in a sandbox, the available `api.<name>(input)` calls (ONLY this allow-list —\n * least-privilege scoping), and the return contract. Add it to the agent's system prompt.\n */\nfunction generateCodeModeInstructions(tools: CustomTool[], toolName: string): string {\n const calls = tools\n .map((t) => `- \\`await api.${t.name}(${describeToolInput(t.inputSchema)})\\` — ${t.description}`)\n .join('\\n')\n return [\n `The \\`${toolName}\\` tool runs your code in a sandbox. Your code may call ONLY these functions (each bridges to a real, validated tool on the host):`,\n calls,\n 'Write an async function body that composes these calls and return exactly ONE structured result. Prefer `Promise.all` for independent calls; do arithmetic and aggregation in code, not in prose.',\n ].join('\\n\\n')\n}\n\n/**\n * Build a code-mode tool + its generated model instructions (M40 / ADR-0049). Fails fast if\n * `onPermissionRequest` or `sandbox` is missing (security by default). `tool` takes `{ code }`,\n * assembles the permission-gated restricted API from `tools`, runs the code in the injected sandbox,\n * and returns the code's result. `instructions` (add it to the agent's system prompt) teaches the\n * model the sandboxed-code contract + the available `api.<name>(input)` calls.\n */\nexport function createCodeMode(config: CodeModeConfig): { tool: CustomTool; instructions: string } {\n if (typeof config.onPermissionRequest !== 'function') {\n throw new Error(\n 'createCodeMode requires onPermissionRequest (security by default — no default-allow for any tool).',\n )\n }\n const sandboxRun = (config.sandbox as { run?: unknown } | null | undefined)?.run\n if (typeof sandboxRun !== 'function') {\n throw new Error(\n 'createCodeMode requires an injected `sandbox` with a run() method (a vetted isolation boundary — never node:vm).',\n )\n }\n // M40 — an empty allow-list is a config mistake: the restricted API (and the generated\n // instructions) would be empty, and the code could call nothing. Fail fast.\n if (config.tools.length === 0) {\n throw new Error(\n 'createCodeMode requires a non-empty tools[] — the restricted API would be empty.',\n )\n }\n\n // Assemble the restricted API: each declared tool becomes a permission-gated callable.\n const api: CodeModeApi = {}\n for (const tool of config.tools) {\n api[tool.name] = async (args: unknown): Promise<unknown> => {\n const decision = await config.onPermissionRequest({ tool: tool.name, args })\n if (!decision.granted) throw new CodeModePermissionDeniedError(tool.name, decision.reason)\n return tool.handler(args as Record<string, unknown>)\n }\n }\n\n const name = config.name ?? 'run_code'\n const tool: CustomTool = {\n name,\n description:\n config.description ??\n 'Run code that composes the available tools. Only the declared tools are callable.',\n inputSchema: {\n type: 'object',\n properties: { code: { type: 'string', description: 'The code to run in the sandbox.' } },\n required: ['code'],\n },\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const code = typeof input.code === 'string' ? input.code : ''\n const result = await config.sandbox.run(code, api)\n return typeof result === 'string' ? result : JSON.stringify(result)\n },\n }\n return { tool, instructions: generateCodeModeInstructions(config.tools, name) }\n}\n","/**\n * M27 (ADR-0041) — channel webhook routes: `POST /api/agents/<name>/channels/<platform>/webhook`.\n *\n * Auto-generates a per-platform inbound webhook endpoint that VALIDATES the platform signature\n * (reusing the existing webhook `VerifyFn` providers — Slack/Telegram/Discord — never a hand-rolled\n * scheme) and hands the parsed payload to an injected `onMessage` seam. The seam is where an app\n * wires the SDK gateway package (`@theokit/gateway-*`) that translates the payload into an agent\n * turn — TheoKit provides the route + signature gate, NOT the gateway's parsing (G2 / it does not\n * reimplement the gateway).\n */\nimport type { VerifyFn } from '../webhook/webhook-types.js'\n\nconst CHANNEL_PATH = /^\\/api\\/agents\\/([^/]+)\\/channels\\/([^/]+)\\/webhook$/\n\n/** Parsed `{ agent, platform }` from a channel webhook path, or `null` when it doesn't match. */\nexport function parseChannelPath(urlPath: string): { agent: string; platform: string } | null {\n const match = CHANNEL_PATH.exec(urlPath)\n if (!match) return null\n return { agent: decodeURIComponent(match[1]), platform: decodeURIComponent(match[2]) }\n}\n\n/** True when `urlPath` targets a channel webhook (dev/prod routing branches on this). */\nexport function isChannelPath(urlPath: string): boolean {\n return CHANNEL_PATH.test(urlPath)\n}\n\n/** The inbound message handed to the app after signature validation passes. */\nexport interface ChannelMessage {\n agent: string\n platform: string\n /** The parsed JSON payload from the platform (the gateway translates this to an agent turn). */\n payload: unknown\n}\n\nexport interface ChannelWebhookConfig {\n /** Per-platform signature validators (e.g. `{ slack: slack({...}), telegram: telegram({...}) }`). */\n validators: Record<string, VerifyFn>\n /** Handoff seam — wire the SDK gateway / agent here. Invoked only after signature validation. */\n onMessage: (message: ChannelMessage) => void | Promise<void>\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/**\n * Handle one channel webhook request. Returns:\n * 404 UNKNOWN_PLATFORM — no validator configured for `<platform>`\n * 400 BAD_REQUEST — path is not a channel webhook, or the body is not JSON\n * 401 INVALID_SIGNATURE — the platform signature check failed (negative case)\n * 200 { ok: true } — validated + handed to `onMessage`\n */\nexport async function handleChannelWebhook(\n request: Request,\n urlPath: string,\n config: ChannelWebhookConfig,\n): Promise<Response> {\n const parsed = parseChannelPath(urlPath)\n if (parsed === null) {\n return jsonError(\n 400,\n 'BAD_REQUEST',\n 'Path must be /api/agents/<name>/channels/<platform>/webhook.',\n )\n }\n if (!Object.hasOwn(config.validators, parsed.platform)) {\n return jsonError(\n 404,\n 'UNKNOWN_PLATFORM',\n `No validator configured for platform '${parsed.platform}'.`,\n )\n }\n const verify = config.validators[parsed.platform]\n\n // Validate the signature against a CLONE so the body stays readable for the payload parse.\n const verifyResult = await verify(request.clone())\n if (!verifyResult.ok) {\n return jsonError(\n 401,\n 'INVALID_SIGNATURE',\n `Signature validation failed: ${verifyResult.reason}`,\n )\n }\n\n let payload: unknown\n try {\n payload = await request.json()\n } catch {\n return jsonError(400, 'BAD_REQUEST', 'Request body must be JSON.')\n }\n\n await config.onMessage({ agent: parsed.agent, platform: parsed.platform, payload })\n return new Response(JSON.stringify({ ok: true }), {\n status: 200,\n headers: { 'content-type': 'application/json' },\n })\n}\n","/**\n * M35 (multi-surface) — the in-process agent-turn seam (Model A).\n *\n * The FRAMEWORK-owned sibling of the HTTP `mountAgent` and the stdout `runAgentInTerminal`: it runs a\n * compiled agent with the SAME `compileAgentModule` + SAME `streamAgentUIMessages` (G2 — reuses the\n * SDK runtime, reimplements nothing), but returns the raw `UIMessageChunk` generator so ANY consumer\n * drives it directly — the Ink TUI (M35), a Tauri window (M36), or a test — in a SINGLE process with\n * NO HTTP loopback, NO port, and NO CSRF (there is no network boundary to defend).\n *\n * The ONLY difference from the HTTP mount is HITL resolution: the mount pauses the run and resolves\n * the approval via a SECOND HTTP request to `/approve/:id` (the approval registry). In-process there\n * is no second request — the caller resolves the approval INLINE via `awaitApproval` (e.g. the Ink\n * TUI's y/n prompt). The gated-tool map is `compiled.hitl` verbatim, so the pause semantics are\n * byte-identical to the HTTP path; only the resolver differs. Parity with the mount is by\n * construction: both compile the module, resolve function-form skills, and call `streamAgentUIMessages`\n * with the same `{ message, sessionId, hitl }`.\n *\n * Consumers WILL still receive `tool-approval-request` chunks from the returned generator — they are\n * INFORMATIONAL (render them or ignore them). The authoritative human gate is `awaitApproval`, which\n * the SDK awaits BEFORE the gated tool runs; the chunk is not the gate.\n */\nimport {\n compileAgentModule,\n resolveEnabledSkills,\n streamAgentUIMessages,\n type HitlDecision,\n type HumanInTheLoopOptions,\n} from '@theokit/agents'\nimport type { UIMessageChunk } from 'ai'\n\n/** An inline approval request handed to the caller's `awaitApproval` (the Ink/Tauri prompt). */\nexport interface InProcessApprovalRequest {\n approvalId: string\n toolName: string\n opts: HumanInTheLoopOptions\n}\n\n/** Resolve one gated-tool approval inline (approve/deny, or a structured {@link HitlDecision}). */\nexport type InProcessAwaitApproval = (\n req: InProcessApprovalRequest,\n) => Promise<boolean | HitlDecision>\n\nexport interface StreamAgentTurnInProcessInput {\n message: string\n /** Resume key; a fresh id per run when omitted. */\n sessionId?: string\n /**\n * Inline HITL resolver — required IFF the agent has `@HumanInTheLoop`-gated tools. Omitting it for a\n * gated agent is a fail-fast error, never a silent bypass (Rule 8, the #99 lesson).\n */\n awaitApproval?: InProcessAwaitApproval\n /** Labels a fail-fast `AgentDefinitionError` (the file path). */\n source?: string\n /** Abort signal forwarded to the SDK stream (client disconnect / window close). */\n signal?: AbortSignal\n}\n\n/** Injectable stream fn (defaults to the real SDK bridge) — lets tests drive a deterministic stream. */\nexport interface StreamAgentTurnDeps {\n stream: typeof streamAgentUIMessages\n}\n\n/**\n * Thrown when a gated agent is run in-process without an `awaitApproval` resolver. Refusing loudly is\n * the correct posture: silently running a `@HumanInTheLoop`-gated tool with no human gate is exactly\n * the #99 class of bug. Typed so callers can catch it distinctly.\n */\nexport class InProcessApprovalRequiredError extends Error {\n constructor(toolNames: readonly string[]) {\n super(\n `Agent has HITL-gated tool(s) [${toolNames.join(', ')}] but no \\`awaitApproval\\` resolver was ` +\n `supplied to streamAgentTurnInProcess. In-process runs must resolve approvals inline — pass ` +\n `awaitApproval, or remove the gate. Refused (fail-closed).`,\n )\n this.name = 'InProcessApprovalRequiredError'\n }\n}\n\n/**\n * Run a compiled agent in-process and return its `UIMessageChunk` stream. `apiKey` is resolved by the\n * caller (same contract as the HTTP mount). Validation + compile happen SYNCHRONOUSLY (so a gated\n * agent without a resolver throws at call time, not lazily on first iteration); the returned value is\n * the SDK's `streamAgentUIMessages` generator.\n */\nexport function streamAgentTurnInProcess(\n mod: unknown,\n apiKey: string,\n input: StreamAgentTurnInProcessInput,\n deps: StreamAgentTurnDeps = { stream: streamAgentUIMessages },\n): AsyncGenerator<UIMessageChunk> {\n const compiled = compileAgentModule(mod, input.source)\n const gated = compiled.hitl\n\n // Fail-fast BEFORE building the stream: a gated agent with no inline resolver would silently bypass\n // the human gate (the #99 class of bug). Refuse loudly (Rule 8, fail-closed).\n if (gated && gated.size > 0 && !input.awaitApproval) {\n throw new InProcessApprovalRequiredError([...gated.keys()])\n }\n const resolve = input.awaitApproval\n\n // Mirror mount-agent's HITL wiring cast-free (structural inference); absent gate ⇒ the non-HITL\n // stream path (M2), unchanged. The SDK calls (approvalId, opts, toolName); route to the caller.\n const hitl =\n gated && gated.size > 0 && resolve\n ? {\n gated,\n awaitApproval: (approvalId: string, opts: HumanInTheLoopOptions, toolName: string) =>\n resolve({ approvalId, toolName, opts }),\n }\n : undefined\n\n const sessionId = input.sessionId ?? crypto.randomUUID()\n\n // Resolve function-form skills (`defineAgent({ skills: (ctx) => [...] })`) BEFORE streaming — exact\n // parity with mount-agent. Done INSIDE the returned generator so the synchronous fail-fast above is\n // preserved (the caller still gets a plain `AsyncGenerator`, no `await` at the call site). A static\n // skill list leaves `skillsResolver` undefined and this is a no-op.\n return (async function* () {\n if (compiled.skillsResolver) {\n const enabled = await resolveEnabledSkills(compiled.skillsResolver, compiled.runContext ?? {})\n if (enabled !== undefined) compiled.skills = { enabled, autoInject: true }\n }\n yield* deps.stream(compiled, apiKey, {\n message: input.message,\n sessionId,\n hitl,\n signal: input.signal,\n })\n })()\n}\n","/**\n * MCP stdio transport (M16 follow-up) — expose a TheoKit agent as an MCP server over stdin/stdout,\n * the sibling of the M16 HTTP route (`POST /api/agents/<name>/mcp`). A desktop MCP client (e.g.\n * Claude Desktop) spawns `theokit mcp <agent>` and speaks newline-delimited JSON-RPC over the pipe.\n *\n * This is a TRANSPORT over the framework's OWN {@link handleMcpJsonRpc} — it reuses the exact handler\n * the HTTP route uses; it calls no LLM, spawns no MCP client, and reimplements no runtime (G2 /\n * sdk-runtime.md). Distinct from the SDK's MCP CLIENT stdio (which spawns external MCP servers via\n * `mcpServers` command/args) — that stays SDK-side. Here TheoKit is the SERVER. The framework-side\n * placement of this server-exposure transport is recorded in ADR-0042 (refining ADR-0040's M16 note).\n */\nimport type { AppResource } from './mcp-app-resources.js'\nimport { handleMcpJsonRpc } from './mcp-handler.js'\n\n/**\n * Handle one newline-delimited JSON-RPC line. Returns the response line to write to stdout, or\n * `null` for a blank line (nothing to emit). A malformed JSON line yields a `-32700` (Parse error)\n * envelope — never throws, so the stdio loop never dies on bad input.\n */\nexport async function handleMcpStdioLine(\n line: string,\n mod: unknown,\n name: string,\n appResources: readonly AppResource[] = [],\n): Promise<string | null> {\n const trimmed = line.trim()\n if (trimmed.length === 0) return null\n let body: unknown\n try {\n body = JSON.parse(trimmed)\n } catch {\n return JSON.stringify({\n jsonrpc: '2.0',\n id: null,\n error: { code: -32700, message: 'Parse error' },\n })\n }\n const response = await handleMcpJsonRpc(mod, name, body, appResources)\n const payload: unknown = await response.json()\n return JSON.stringify(payload)\n}\n\n/** A minimal readable line source (an async iterable of lines) + a writable sink. */\nexport interface StdioStreams {\n /** Async iterable of newline-delimited input lines (e.g. `readline.createInterface({ input })`). */\n lines: AsyncIterable<string>\n /** Write a response line (the caller appends no newline). */\n write: (line: string) => void\n}\n\n/**\n * Drive the MCP stdio server loop: for each input line, dispatch via {@link handleMcpStdioLine} and\n * write the response line (with a trailing `\\n`). Returns when the input stream ends (EOF).\n */\nexport async function serveMcpStdio(\n mod: unknown,\n name: string,\n appResources: readonly AppResource[],\n streams: StdioStreams,\n): Promise<void> {\n for await (const line of streams.lines) {\n const out = await handleMcpStdioLine(line, mod, name, appResources)\n if (out !== null) streams.write(`${out}\\n`)\n }\n}\n"],"mappings":"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","names":["tool"]}
|
package/dist/chunk-TERFLG67.js
CHANGED
|
File without changes
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineAgentTool
|
|
3
|
+
} from "./chunk-63BUBV5L.js";
|
|
4
|
+
|
|
1
5
|
// src/server/define/define-route.ts
|
|
2
6
|
function defineRoute(config) {
|
|
3
7
|
return config;
|
|
@@ -111,65 +115,6 @@ function middleware() {
|
|
|
111
115
|
return makeMiddlewareBuilder(void 0);
|
|
112
116
|
}
|
|
113
117
|
|
|
114
|
-
// src/server/define/define-agent-tool.ts
|
|
115
|
-
import { z } from "zod";
|
|
116
|
-
var TOOL_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
|
|
117
|
-
function isZodObject(schema) {
|
|
118
|
-
let current = schema;
|
|
119
|
-
for (let depth = 0; depth < 10; depth++) {
|
|
120
|
-
if (current instanceof z.ZodObject) return true;
|
|
121
|
-
const z4 = current.def;
|
|
122
|
-
if (z4?.type === "object") return true;
|
|
123
|
-
const z3 = current._def;
|
|
124
|
-
if (z3?.typeName === "ZodObject") return true;
|
|
125
|
-
const next = z4?.innerType ?? z4?.in ?? z3?.schema ?? z3?.innerType;
|
|
126
|
-
if (next !== void 0) {
|
|
127
|
-
current = next;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
function defineAgentTool(spec) {
|
|
135
|
-
if (!TOOL_NAME_REGEX.test(spec.name)) {
|
|
136
|
-
throw new Error(
|
|
137
|
-
`defineAgentTool: name must match ${TOOL_NAME_REGEX.source}. Got: ${JSON.stringify(spec.name)}`
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
if (!isZodObject(spec.inputSchema)) {
|
|
141
|
-
throw new Error("defineAgentTool: inputSchema must be a ZodObject (z.object({...}))");
|
|
142
|
-
}
|
|
143
|
-
if (spec.description.length === 0) {
|
|
144
|
-
console.warn(
|
|
145
|
-
`defineAgentTool(${JSON.stringify(spec.name)}): empty description degrades LLM tool selection \u2014 provide a one-sentence summary.`
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
const { $schema: _$schema, ...inputSchema } = z.toJSONSchema(spec.inputSchema);
|
|
149
|
-
return {
|
|
150
|
-
name: spec.name,
|
|
151
|
-
description: spec.description,
|
|
152
|
-
inputSchema,
|
|
153
|
-
handler: async (input, ctx) => {
|
|
154
|
-
const parsed = spec.inputSchema.parse(input);
|
|
155
|
-
const result = await spec.handler(parsed, ctx);
|
|
156
|
-
if (spec.toModelOutput) return spec.toModelOutput(result);
|
|
157
|
-
if (typeof result !== "string") {
|
|
158
|
-
throw new Error(
|
|
159
|
-
`defineAgentTool(${JSON.stringify(spec.name)}): handler returned a non-string; provide toModelOutput to map it to a string for the model.`
|
|
160
|
-
);
|
|
161
|
-
}
|
|
162
|
-
return result;
|
|
163
|
-
},
|
|
164
|
-
// M18 — carry the per-target formatters for the app (ignored by the SDK wire).
|
|
165
|
-
...spec.transform !== void 0 ? { transform: spec.transform } : {}
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function applyTransform(tool2, result, target) {
|
|
169
|
-
const fn = tool2.transform?.[target];
|
|
170
|
-
return fn ? fn(result) : result;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
118
|
// src/server/define/tool-builder.ts
|
|
174
119
|
function makeToolBuilder(spec) {
|
|
175
120
|
const runtime = {
|
|
@@ -281,12 +226,10 @@ export {
|
|
|
281
226
|
action,
|
|
282
227
|
websocket,
|
|
283
228
|
middleware,
|
|
284
|
-
defineAgentTool,
|
|
285
|
-
applyTransform,
|
|
286
229
|
tool,
|
|
287
230
|
plugin,
|
|
288
231
|
uiMessageStreamResponse,
|
|
289
232
|
defineChannel,
|
|
290
233
|
defineWebChannel
|
|
291
234
|
};
|
|
292
|
-
//# sourceMappingURL=chunk-
|
|
235
|
+
//# sourceMappingURL=chunk-V3X5FWJA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/define/define-route.ts","../src/server/define/route-builder.ts","../src/server/define/define-action.ts","../src/server/define/action-builder.ts","../src/server/define/define-websocket.ts","../src/server/define/websocket-builder.ts","../src/server/define/define-middleware.ts","../src/server/define/middleware-builder.ts","../src/server/define/tool-builder.ts","../src/server/plugin-types.ts","../src/server/define/plugin-builder.ts","../src/server/define/ui-message-stream-response.ts","../src/server/define/define-channel.ts"],"sourcesContent":["import type { z } from 'zod'\n\n// T2.2 (architecture-cleanup) — RouteConfig type moved to core/contracts/\n// (canonical home per ADR-0001 v3). Re-export preserves the public path\n// `import { type RouteConfig } from 'theokit/server'`.\nexport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\n/**\n * Define a typed HTTP route.\n * Identity function — provides type inference for route handlers.\n */\nexport function defineRoute<\n TQuery extends z.ZodType = z.ZodUndefined,\n TBody extends z.ZodType = z.ZodUndefined,\n TParams extends z.ZodType = z.ZodUndefined,\n TCtx = unknown,\n TResponse = unknown,\n>(\n config: RouteConfig<TQuery, TBody, TParams, TCtx, TResponse>,\n): RouteConfig<TQuery, TBody, TParams, TCtx, TResponse> {\n return config\n}\n","/**\n * M31 Phase 3 — `route()`, the fluent builder that replaces `defineRoute({...})`.\n *\n * Pure type-state (mirrors `tool-builder.ts`). `.query/.body/.params` set Zod schemas whose\n * `z.infer<>` flows into the handler's `ctx`; `.handler()` is required before `.build()`. `.build()`\n * delegates to the internal {@link defineRoute} (an identity fn), emitting the identical\n * `RouteConfig` — the scan/execute path is UNCHANGED (identity-shape delegation, blueprint §2).\n *\n * export const POST = route()\n * .params(z.object({ id: z.string() }))\n * .body(z.object({ text: z.string() }))\n * .handler(({ params, body }) => save(params.id, body.text))\n * .build()\n */\nimport type { z } from 'zod'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport { defineRoute } from './define-route.js'\n\n/** Compile-error carrier: `.build()` called before `.handler()`. */\ninterface MissingHandlerError {\n readonly __theokitError: 'a route needs .handler(fn) before .build()'\n}\n\n/**\n * The fluent route builder. `TQuery/TBody/TParams` track the input schemas (default `z.ZodUndefined`,\n * matching {@link RouteConfig}); `TResponse` tracks the handler return; `THandlerSet` gates `.build()`.\n */\nexport interface RouteBuilder<\n TQuery extends z.ZodType = z.ZodUndefined,\n TBody extends z.ZodType = z.ZodUndefined,\n TParams extends z.ZodType = z.ZodUndefined,\n TCtx = unknown,\n TResponse = unknown,\n THandlerSet extends boolean = false,\n> {\n /** Set the URL search-params schema. Inferred into `ctx.query`. */\n query<S extends z.ZodType>(\n schema: S,\n ): RouteBuilder<S, TBody, TParams, TCtx, TResponse, THandlerSet>\n /** Set the request-body schema. Inferred into `ctx.body`. */\n body<S extends z.ZodType>(\n schema: S,\n ): RouteBuilder<TQuery, S, TParams, TCtx, TResponse, THandlerSet>\n /** Set the path-params schema. Inferred into `ctx.params`. */\n params<S extends z.ZodType>(\n schema: S,\n ): RouteBuilder<TQuery, TBody, S, TCtx, TResponse, THandlerSet>\n /** Runtime-only validation of the handler's plain-object return (500 on mismatch). Not inferred (YAGNI). */\n response(schema: z.ZodType): RouteBuilder<TQuery, TBody, TParams, TCtx, TResponse, THandlerSet>\n /** Override the HTTP status for a plain-object return (default 200; 204 for void). */\n status(code: number): RouteBuilder<TQuery, TBody, TParams, TCtx, TResponse, THandlerSet>\n /** Opt out of CSRF enforcement for this route (webhooks / OAuth callbacks). */\n csrf(disabled: false): RouteBuilder<TQuery, TBody, TParams, TCtx, TResponse, THandlerSet>\n /**\n * Set the handler. Its `ctx` infers `query/body/params` from the schemas set above. Required\n * before `.build()`.\n */\n handler<R>(\n fn: (ctx: {\n query: z.infer<TQuery>\n body: z.infer<TBody>\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n }) => R | Promise<R>,\n ): RouteBuilder<TQuery, TBody, TParams, TCtx, R, true>\n /**\n * Resolve to the `RouteConfig` — the SAME value `defineRoute({...})` returns. COMPILE ERROR when\n * `.handler()` was never called.\n */\n build(\n ...guard: THandlerSet extends true ? [] : [error: MissingHandlerError]\n ): RouteConfig<TQuery, TBody, TParams, TCtx, TResponse>\n}\n\n/**\n * Permissive internal shape — the runtime seam works with `z.ZodType` schemas (ctx fields typed\n * `unknown`); the precise per-schema types are carried to callers by the {@link RouteBuilder}\n * interface via the `as unknown as RouteBuilder` bridge. `defineRoute` is an identity fn.\n */\ntype AnyRouteConfig = RouteConfig<z.ZodType, z.ZodType, z.ZodType>\n\ninterface RouteSpecAccumulator {\n query?: z.ZodType\n body?: z.ZodType\n params?: z.ZodType\n response?: z.ZodType\n status?: number\n csrf?: false\n handler?: AnyRouteConfig['handler']\n}\n\nfunction makeRouteBuilder(spec: RouteSpecAccumulator): RouteBuilder {\n const runtime = {\n query: (schema: z.ZodType) => makeRouteBuilder({ ...spec, query: schema }),\n body: (schema: z.ZodType) => makeRouteBuilder({ ...spec, body: schema }),\n params: (schema: z.ZodType) => makeRouteBuilder({ ...spec, params: schema }),\n response: (schema: z.ZodType) => makeRouteBuilder({ ...spec, response: schema }),\n status: (code: number) => makeRouteBuilder({ ...spec, status: code }),\n csrf: (disabled: false) => makeRouteBuilder({ ...spec, csrf: disabled }),\n handler: (fn: AnyRouteConfig['handler']) => makeRouteBuilder({ ...spec, handler: fn }),\n build: (): AnyRouteConfig => {\n // Fail-fast for untyped (JS) callers — the type-state guard makes this unreachable from TS.\n if (spec.handler === undefined) {\n throw new Error('route(): call .handler(fn) before .build()')\n }\n const config: AnyRouteConfig = {\n ...(spec.query !== undefined ? { query: spec.query } : {}),\n ...(spec.body !== undefined ? { body: spec.body } : {}),\n ...(spec.params !== undefined ? { params: spec.params } : {}),\n ...(spec.response !== undefined ? { response: spec.response } : {}),\n ...(spec.status !== undefined ? { status: spec.status } : {}),\n ...(spec.csrf !== undefined ? { csrf: spec.csrf } : {}),\n handler: spec.handler,\n }\n return defineRoute(config)\n },\n }\n return runtime as unknown as RouteBuilder\n}\n\n/**\n * Start a fluent route definition. Chain `.query/.body/.params/.response/.status/.csrf` (all\n * optional), then `.handler()` (required) and `.build()` for the `RouteConfig`.\n */\nexport function route(): RouteBuilder {\n return makeRouteBuilder({})\n}\n","import type { z } from 'zod'\n\n/**\n * Action wire-protocol accept mode per plan g3-server-actions-and-useaction\n * v1.2 ADR D1. Default behavior (when omitted) is `'json'`. `'form'` opts the\n * action into FormData multipart parsing for progressive-enhancement forms;\n * the runtime in `server/http/action-execute.ts` will coerce FormData entries\n * against the `input` schema via `formDataToObject` (Astro pattern).\n */\nexport type ActionAccept = 'form' | 'json'\n\nexport interface ActionConfig<TInput extends z.ZodType, TCtx = unknown> {\n /**\n * Zod input schema. Required: every action declares its input contract via\n * Zod (architecture rule: zod-is-SSOT). The shape becomes the handler's\n * typed `input` parameter via `z.infer<TInput>`.\n */\n input: TInput\n /**\n * Wire-protocol accept mode. Defaults to `'json'` when omitted. Setting\n * `'form'` switches the runtime to FormData multipart parsing — the input\n * schema MUST be `z.object(...)` so field-by-field coercion can drive\n * boolean string / number / array coercion (Astro pattern).\n */\n accept?: ActionAccept\n /**\n * Opt OUT of CSRF enforcement for this action. Default (omitted) keeps the\n * multi-header CSRF gate active. Set `false` for endpoints intentionally\n * callable without the `X-Theo-Action` header (e.g. public webhooks). The\n * runtime in `server/http/action-execute.ts` reads this flag.\n */\n csrf?: false\n handler: (ctx: { input: z.infer<TInput>; ctx: TCtx }) => unknown\n}\n\n/**\n * Define a typed server action.\n *\n * Identity function — provides type inference for action handlers. The\n * runtime that consumes the config (validation + invocation + serialization)\n * lives in `server/http/action-execute.ts`.\n *\n * Per plan g3-server-actions-and-useaction v1.2 § Phase 1 / T1.2: the new\n * `accept?: 'form' | 'json'` field is the only contract change vs the\n * pre-G3 identity. Existing callsites (`defineAction({input, handler})`)\n * continue to compile — `accept` is opt-in.\n */\nexport function defineAction<TInput extends z.ZodType, TCtx = unknown>(\n config: ActionConfig<TInput, TCtx>,\n): ActionConfig<TInput, TCtx> {\n return config\n}\n","/**\n * M31 Phase 3 — `action()`, the fluent builder that replaces `defineAction({...})`.\n *\n * Pure type-state (mirrors `route-builder.ts`). `.input()` (required) sets the Zod schema whose\n * `z.infer<>` types the handler's `ctx.input`; `.handler()` (required) closes the chain. `.build()`\n * delegates to the internal {@link defineAction} (identity) — the action-execute path is UNCHANGED.\n *\n * export const createUser = action()\n * .input(z.object({ email: z.string().email() }))\n * .handler(({ input }) => createUser(input.email))\n * .build()\n */\nimport type { z } from 'zod'\n\nimport { defineAction, type ActionConfig, type ActionAccept } from './define-action.js'\n\n/** Compile-error carrier: `.execute`/`.build()` reached before `.input()`. */\ninterface MissingInputError {\n readonly __theokitError: 'call .input(schema) before .handler(fn)'\n}\n/** Compile-error carrier: `.build()` before both `.input()` and `.handler()` are set. */\ninterface IncompleteActionError {\n readonly __theokitError: 'an action needs .input(schema) and .handler(fn) before .build()'\n}\n\n/** A required-but-unset field. Branded so no ordinary value satisfies it (tRPC UnsetMarker). */\ntype UnsetMarker = 'theokit.unset' & { readonly __brand: 'theokit.unset' }\n\n/**\n * The fluent action builder. `TInput` tracks the Zod schema (drives `ctx.input` inference);\n * `THandlerSet` gates `.build()`.\n */\nexport interface ActionBuilder<\n TInput extends z.ZodType | UnsetMarker = UnsetMarker,\n TCtx = unknown,\n THandlerSet extends boolean = false,\n> {\n /** Set the Zod input schema. Required — every action declares its input contract (zod-is-SSOT). */\n input<S extends z.ZodType>(schema: S): ActionBuilder<S, TCtx, THandlerSet>\n /** Wire-protocol accept mode (`'json'` default, `'form'` for FormData multipart). */\n accept(mode: ActionAccept): ActionBuilder<TInput, TCtx, THandlerSet>\n /** Opt out of CSRF enforcement for this action. */\n csrf(disabled: false): ActionBuilder<TInput, TCtx, THandlerSet>\n /**\n * Set the handler. COMPILE ERROR before `.input()` — the param type collapses to\n * {@link MissingInputError}. `ctx.input` is inferred via `z.infer<TInput>`.\n */\n handler(\n fn: TInput extends z.ZodType\n ? (ctx: { input: z.infer<TInput>; ctx: TCtx }) => unknown\n : MissingInputError,\n ): ActionBuilder<TInput, TCtx, true>\n /**\n * Resolve to the `ActionConfig` — the SAME value `defineAction({...})` returns. COMPILE ERROR when\n * `.input()` or `.handler()` was never called.\n */\n build(\n ...guard: THandlerSet extends true\n ? TInput extends z.ZodType\n ? []\n : [error: IncompleteActionError]\n : [error: IncompleteActionError]\n ): ActionConfig<TInput extends z.ZodType ? TInput : z.ZodType, TCtx>\n}\n\ntype AnyActionConfig = ActionConfig<z.ZodType>\n\ninterface ActionSpecAccumulator {\n input?: z.ZodType\n accept?: ActionAccept\n csrf?: false\n handler?: AnyActionConfig['handler']\n}\n\nfunction makeActionBuilder(spec: ActionSpecAccumulator): ActionBuilder {\n const runtime = {\n input: (schema: z.ZodType) => makeActionBuilder({ ...spec, input: schema }),\n accept: (mode: ActionAccept) => makeActionBuilder({ ...spec, accept: mode }),\n csrf: (disabled: false) => makeActionBuilder({ ...spec, csrf: disabled }),\n handler: (fn: AnyActionConfig['handler']) => makeActionBuilder({ ...spec, handler: fn }),\n build: (): AnyActionConfig => {\n // Fail-fast for untyped (JS) callers — the type-state guards make this unreachable from TS.\n if (spec.input === undefined) {\n throw new Error('action(): call .input(schema) before .build()')\n }\n if (spec.handler === undefined) {\n throw new Error('action(): call .handler(fn) before .build()')\n }\n const config: AnyActionConfig = {\n input: spec.input,\n handler: spec.handler,\n ...(spec.accept !== undefined ? { accept: spec.accept } : {}),\n ...(spec.csrf !== undefined ? { csrf: spec.csrf } : {}),\n }\n return defineAction(config)\n },\n }\n return runtime as unknown as ActionBuilder\n}\n\n/**\n * Start a fluent action definition. Chain `.input()` (required), optionally `.accept()` / `.csrf()`,\n * then `.handler()` (required) and `.build()` for the `ActionConfig`.\n */\nexport function action(): ActionBuilder {\n return makeActionBuilder({})\n}\n","import type { IncomingMessage } from 'node:http'\n\nexport interface WebSocketLike {\n send(data: string | Buffer): void\n close(code?: number, reason?: string): void\n}\n\nexport interface WebSocketHandler {\n onOpen?: (ws: WebSocketLike, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, data: string | Buffer) => void\n onClose?: (ws: WebSocketLike, code: number, reason: Buffer) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Define a WebSocket endpoint handler.\n * Identity function — provides type inference for WebSocket handlers.\n */\nexport function defineWebSocket(handler: WebSocketHandler): WebSocketHandler {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 3/3 — Web-Standards WebSocket endpoint handler.\n *\n * Mirror of `WebSocketHandler` for the Web `Request` shape. `onOpen`\n * receives `request: Request` instead of `req: IncomingMessage`. The\n * rest of the lifecycle (onMessage, onClose, onError) is shape-agnostic\n * (`WebSocketLike` is already Web-standards-compatible per the existing\n * design — `send(string | Buffer)` works on both Node `ws` and Web\n * `WebSocket` instances; CF Workers / Bun / Deno coerce as needed at\n * the adapter boundary).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F (closes Phase F).\n *\n * **Architectural note — WebSocket upgrade semantics differ across runtimes:**\n * - Node + `ws`: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * `req` is `IncomingMessage`. Use `WebSocketHandler`.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request). Use `WebSocketHandlerWeb`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Cross-runtime WebSocket endpoints ship BOTH `WebSocketHandler` +\n * `WebSocketHandlerWeb` exports; the runtime adapter picks the matching\n * one. This is the canonical Hono / Nitric pattern.\n */\nexport interface WebSocketHandlerWeb {\n onOpen?: (ws: WebSocketLike, request: Request) => void\n onMessage?: (ws: WebSocketLike, data: string | Uint8Array) => void\n onClose?: (ws: WebSocketLike, code: number, reason: string) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Web-Standards `defineWebSocket` sibling. Identity function — provides\n * type inference for Web WebSocket handlers.\n *\n * **Type difference note vs Node path:**\n * - `onMessage` data is `string | Uint8Array` instead of `string | Buffer`\n * (Web standards have no `Buffer`; Node's Buffer is a Uint8Array\n * subclass so the Node path's Buffer values flow through unchanged\n * when adapters wrap them).\n * - `onClose` reason is `string` instead of `Buffer` (Web `CloseEvent`\n * exposes the reason as a UTF-8 string natively).\n */\nexport function defineWebSocketWeb(handler: WebSocketHandlerWeb): WebSocketHandlerWeb {\n return handler\n}\n","/**\n * M31 Phase 3 — `websocket()`, the fluent builder that replaces `defineWebSocket({...})`.\n *\n * Lifecycle setters (`onOpen/onMessage/onClose/onError`), all optional; `.build()` delegates to the\n * internal {@link defineWebSocket} (identity) — the ws handler loading path is UNCHANGED.\n *\n * export default websocket()\n * .onOpen((ws) => ws.send('hi'))\n * .onMessage((ws, data) => ws.send(`echo:${data}`))\n * .build()\n */\nimport { defineWebSocket, type WebSocketHandler } from './define-websocket.js'\n\n/** The fluent WebSocket builder. Each lifecycle hook is optional; `.build()` returns the handler. */\nexport interface WebSocketBuilder {\n onOpen(fn: NonNullable<WebSocketHandler['onOpen']>): WebSocketBuilder\n onMessage(fn: NonNullable<WebSocketHandler['onMessage']>): WebSocketBuilder\n onClose(fn: NonNullable<WebSocketHandler['onClose']>): WebSocketBuilder\n onError(fn: NonNullable<WebSocketHandler['onError']>): WebSocketBuilder\n /** Resolve to the `WebSocketHandler` — the SAME value `defineWebSocket({...})` returns. */\n build(): WebSocketHandler\n}\n\nfunction makeWebSocketBuilder(spec: WebSocketHandler): WebSocketBuilder {\n const runtime: WebSocketBuilder = {\n onOpen: (fn) => makeWebSocketBuilder({ ...spec, onOpen: fn }),\n onMessage: (fn) => makeWebSocketBuilder({ ...spec, onMessage: fn }),\n onClose: (fn) => makeWebSocketBuilder({ ...spec, onClose: fn }),\n onError: (fn) => makeWebSocketBuilder({ ...spec, onError: fn }),\n build: () => defineWebSocket(spec),\n }\n return runtime\n}\n\n/** Start a fluent WebSocket definition. Chain any of the lifecycle hooks, then `.build()`. */\nexport function websocket(): WebSocketBuilder {\n return makeWebSocketBuilder({})\n}\n","export type MiddlewareHandler = (\n request: Request,\n next: (request: Request) => Promise<Response>,\n) => Response | Promise<Response>\n\n/**\n * Define a middleware handler.\n * Identity function — provides type annotation for middleware.\n */\nexport function defineMiddleware(handler: MiddlewareHandler): MiddlewareHandler {\n return handler\n}\n","/**\n * M31 Phase 3 — `middleware()`, the fluent builder that replaces `defineMiddleware(fn)`.\n *\n * A middleware IS a single function `(request, next) => Response`. The builder's `.handle()` sets it\n * (required); `.build()` delegates to the internal {@link defineMiddleware} (identity) and returns\n * the handler the runtime expects.\n *\n * export default middleware()\n * .handle(async (request, next) => {\n * const res = await next(request)\n * res.headers.set('x-mw', '1')\n * return res\n * })\n * .build()\n */\nimport { defineMiddleware, type MiddlewareHandler } from './define-middleware.js'\n\n/** Compile-error carrier: `.build()` called before `.handle()`. */\ninterface MissingHandleError {\n readonly __theokitError: 'middleware needs .handle(fn) before .build()'\n}\n\n/** The fluent middleware builder. `THandleSet` gates `.build()`. */\nexport interface MiddlewareBuilder<THandleSet extends boolean = false> {\n /** Set the `(request, next) => Response` handler. Required before `.build()`. */\n handle(fn: MiddlewareHandler): MiddlewareBuilder<true>\n /** Resolve to the `MiddlewareHandler`. COMPILE ERROR when `.handle()` was never called. */\n build(...guard: THandleSet extends true ? [] : [error: MissingHandleError]): MiddlewareHandler\n}\n\nfunction makeMiddlewareBuilder(fn: MiddlewareHandler | undefined): MiddlewareBuilder {\n const runtime = {\n handle: (handler: MiddlewareHandler) => makeMiddlewareBuilder(handler),\n build: (): MiddlewareHandler => {\n // Fail-fast for untyped (JS) callers — the type-state guard makes this unreachable from TS.\n if (fn === undefined) {\n throw new Error('middleware(): call .handle(fn) before .build()')\n }\n return defineMiddleware(fn)\n },\n }\n return runtime as unknown as MiddlewareBuilder\n}\n\n/** Start a fluent middleware definition. Chain `.handle()` (required), then `.build()`. */\nexport function middleware(): MiddlewareBuilder {\n return makeMiddlewareBuilder(undefined)\n}\n","/**\n * M31 Phase 1 — `tool()`, the fluent builder that replaces `defineAgentTool({...})`.\n *\n * Pure type-state (tRPC `UnsetMarker` technique, mirroring `agent-builder.ts`). The runtime is a\n * plain accumulator; `.build()` delegates to the internal {@link defineAgentTool}, so the emitted\n * `CustomTool` is byte-for-byte the legacy shape — the SDK/agent compile path is UNCHANGED\n * (identity-shape delegation, blueprint §2).\n *\n * PURE metadata (G2 / sdk-runtime.md): a tool describes a capability; it NEVER calls an LLM.\n *\n * tool('read')\n * .describe('Read a UTF-8 file')\n * .input(z.object({ path: z.string() }))\n * .execute(async ({ path }, ctx) => readFile(resolveInProject(ctx, path)))\n * .build()\n */\nimport type { z } from 'zod'\n\nimport { defineAgentTool, type CustomTool, type ToolTransform } from './define-agent-tool.js'\n\n/** A required-but-unset builder field. Branded so no ordinary value satisfies it (tRPC UnsetMarker). */\ntype UnsetMarker = 'theokit.unset' & { readonly __brand: 'theokit.unset' }\n\n/** Compile-error carrier: `.execute()` called before `.input()`. */\ninterface MissingInputError {\n readonly __theokitError: 'call .input(schema) before .execute(handler)'\n}\n/** Compile-error carrier: `.build()` called before both `.input()` and `.execute()` are set. */\ninterface IncompleteToolError {\n readonly __theokitError: 'a tool needs .input(schema) and .execute(handler) before .build()'\n}\n\n/** The run context a tool handler receives (M7). */\ninterface ToolCtx {\n signal?: AbortSignal\n context?: unknown\n}\n\n/**\n * The fluent tool builder. Each method returns a NEW builder type with the relevant type parameter\n * advanced. `TInput` tracks the Zod schema (drives `execute` input inference); `R` tracks the\n * handler result; `THandlerSet` gates `.build()`.\n */\nexport interface ToolBuilder<\n TName extends string = string,\n TInput extends z.ZodType | UnsetMarker = UnsetMarker,\n R = string,\n THandlerSet extends boolean = false,\n> {\n /** Set the LLM-facing description. Optional; an empty description warns at build (LLM selection). */\n describe(description: string): ToolBuilder<TName, TInput, R, THandlerSet>\n /** Set the Zod input schema (must be `z.object(...)` at the root). Required before `.execute()`. */\n input<S extends z.ZodType>(schema: S): ToolBuilder<TName, S, R, THandlerSet>\n /**\n * Set the handler. COMPILE ERROR when `.input()` was not called first — the parameter type\n * collapses to {@link MissingInputError}. The `input` argument is inferred via `z.infer<TInput>`.\n */\n execute<R2>(\n handler: TInput extends z.ZodType\n ? (input: z.infer<TInput>, ctx?: ToolCtx) => R2 | Promise<R2>\n : MissingInputError,\n ): ToolBuilder<TName, TInput, R2, true>\n /** M18 — map a rich handler result to the model-visible string. */\n toModelOutput(fn: (result: R) => string): ToolBuilder<TName, TInput, R, THandlerSet>\n /** M18 — per-target formatters (`display` / `transcript`) for the app UI/transcript. */\n transform(t: ToolTransform<R>): ToolBuilder<TName, TInput, R, THandlerSet>\n /**\n * Resolve to the `CustomTool` — the SAME value `defineAgentTool({...})` returns. COMPILE ERROR\n * when `.input()` or `.execute()` was never called.\n */\n build(\n ...guard: THandlerSet extends true\n ? TInput extends z.ZodType\n ? []\n : [error: IncompleteToolError]\n : [error: IncompleteToolError]\n ): CustomTool\n}\n\ninterface ToolSpecAccumulator {\n name: string\n description?: string\n inputSchema?: z.ZodType\n handler?: (input: unknown, ctx?: ToolCtx) => unknown\n toModelOutput?: (result: unknown) => string\n transform?: ToolTransform\n}\n\n/**\n * Build the runtime accumulator. The public method signatures carry the type-state generics + the\n * compile-time guards; the runtime cannot track generics, so the object is bridged to the typed\n * interface once here (the single, documented type-state impl seam — same technique as agent-builder).\n */\nfunction makeToolBuilder(spec: ToolSpecAccumulator): ToolBuilder {\n const runtime = {\n describe: (description: string) => makeToolBuilder({ ...spec, description }),\n input: (schema: z.ZodType) => makeToolBuilder({ ...spec, inputSchema: schema }),\n execute: (handler: (input: unknown, ctx?: ToolCtx) => unknown) =>\n makeToolBuilder({ ...spec, handler }),\n toModelOutput: (fn: (result: unknown) => string) =>\n makeToolBuilder({ ...spec, toModelOutput: fn }),\n transform: (t: ToolTransform) => makeToolBuilder({ ...spec, transform: t }),\n build: (): CustomTool => {\n // Fail-fast: the type-state guards make these unreachable from typed callers, but an untyped\n // (JS) caller could skip them — surface a clear error instead of a confusing downstream one.\n if (spec.inputSchema === undefined) {\n throw new Error(`tool(${JSON.stringify(spec.name)}): call .input(schema) before .build()`)\n }\n if (spec.handler === undefined) {\n throw new Error(\n `tool(${JSON.stringify(spec.name)}): call .execute(handler) before .build()`,\n )\n }\n return defineAgentTool({\n name: spec.name,\n description: spec.description ?? '',\n inputSchema: spec.inputSchema,\n handler: spec.handler,\n ...(spec.toModelOutput !== undefined ? { toModelOutput: spec.toModelOutput } : {}),\n ...(spec.transform !== undefined ? { transform: spec.transform } : {}),\n })\n },\n }\n return runtime as unknown as ToolBuilder\n}\n\n/**\n * Start a fluent tool definition. Chain `.input()` + `.execute()` (both required), optionally\n * `.describe()` / `.toModelOutput()` / `.transform()`, then `.build()` for the `CustomTool`.\n */\nexport function tool<TName extends string>(name: TName): ToolBuilder<TName> {\n return makeToolBuilder({ name })\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\n\nexport interface PluginContext {\n request: IncomingMessage\n response: ServerResponse\n ctx: Record<string, unknown>\n requestId: string\n}\n\nexport interface PluginErrorContext extends PluginContext {\n error: unknown\n}\n\nexport interface RunHookOptions {\n inErrorPath?: boolean\n}\n\nexport interface HookResult {\n shortCircuited: boolean\n}\n\nexport type OnRequestHook = (ctx: PluginContext) => void | Promise<void>\nexport type PreHandlerHook = (ctx: PluginContext) => void | Promise<void>\nexport type OnResponseHook = (ctx: PluginContext) => void | Promise<void>\nexport type OnErrorHook = (ctx: PluginErrorContext) => void | Promise<void>\n\nexport type HookName = 'onRequest' | 'preHandler' | 'onResponse' | 'onError'\n\nexport type HookByName<K extends HookName> = K extends 'onError'\n ? OnErrorHook\n : K extends 'onRequest'\n ? OnRequestHook\n : K extends 'preHandler'\n ? PreHandlerHook\n : K extends 'onResponse'\n ? OnResponseHook\n : never\n\nexport interface TheoApp {\n addHook<K extends HookName>(name: K, fn: HookByName<K>): void\n // `T` lets plugin authors document the per-key shape of decorations.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- T documents the value type for plugin authors\n decorateRequest<T>(key: string, value: T): void\n}\n\nexport interface TheoPlugin {\n name: string\n register(app: TheoApp): void | Promise<void>\n}\n\n/**\n * Identity function for plugin authors. Provides auto-completion + type\n * inference at the call site (TanStack/Vite/Astro pattern). Pure runtime\n * no-op — returns the input unchanged.\n *\n * @example\n * import { definePlugin } from 'theokit/server'\n * export default definePlugin({\n * name: 'my-plugin',\n * register(app) {\n * app.addHook('onRequest', (req) => { ... })\n * },\n * })\n *\n * Equivalent to `const p: TheoPlugin = {...}` but more ergonomic. See\n * ADR-0008 (D1 + D6) for the rationale.\n */\nexport function definePlugin(plugin: TheoPlugin): TheoPlugin {\n return plugin\n}\n\n// ===== T5a.2 Phase F slice 1/3 — Web-Standards plugin context types =====\n//\n// Mirror of the IncomingMessage/ServerResponse-shaped `PluginContext` for\n// the Web `Request`/`Headers` shape. Per `docs/plans/t5a2-incoming-message-\n// to-request-shape-refactor-plan.md` v1.0 § Phase F.\n//\n// **Key difference vs IncomingMessage path:** the Web path has no\n// `ServerResponse` to mutate. Plugins instead get a `responseHeaders: Headers`\n// instance they can append to (e.g., add Set-Cookie, CORS headers) and the\n// runtime composes the final `Response` after the hook chain runs. The\n// `response` object (if any) is the in-flight Response constructed by the\n// handler — present only during `onResponse` / `onError` hooks AFTER the\n// handler returned, NOT during `onRequest` / `preHandler` (which fire BEFORE\n// the handler runs).\n//\n// This split mirrors Hono's `c.res` + Fastify's `reply.headers` semantics\n// — plugins mutate headers freely; the body is the handler's responsibility.\n\n/**\n * Web-Standards plugin context. Available during all 4 hook lifecycle\n * stages (onRequest, preHandler, onResponse, onError).\n *\n * - `request` — the incoming Web Request (read-only at the runtime level;\n * plugins can call `request.headers.get()`, `request.clone()`, etc.).\n * - `responseHeaders` — a mutable `Headers` instance the runtime threads\n * through the hook chain. Plugins append (e.g., CORS, Set-Cookie); the\n * final Response composes these.\n * - `response` — set to the handler's Response AFTER the handler returns.\n * Available during `onResponse` / `onError`. `undefined` during\n * `onRequest` / `preHandler` (which fire before the handler runs).\n * - `ctx` / `requestId` — same semantics as the IncomingMessage path.\n */\nexport interface WebPluginContext {\n request: Request\n responseHeaders: Headers\n response?: Response\n ctx: Record<string, unknown>\n requestId: string\n}\n\nexport interface WebPluginErrorContext extends WebPluginContext {\n error: unknown\n}\n\nexport type WebOnRequestHook = (ctx: WebPluginContext) => void | Promise<void>\nexport type WebPreHandlerHook = (ctx: WebPluginContext) => void | Promise<void>\nexport type WebOnResponseHook = (ctx: WebPluginContext) => void | Promise<void>\nexport type WebOnErrorHook = (ctx: WebPluginErrorContext) => void | Promise<void>\n\nexport type WebHookByName<K extends HookName> = K extends 'onError'\n ? WebOnErrorHook\n : K extends 'onRequest'\n ? WebOnRequestHook\n : K extends 'preHandler'\n ? WebPreHandlerHook\n : K extends 'onResponse'\n ? WebOnResponseHook\n : never\n\n/**\n * Web-Standards `TheoApp` facade. Same `addHook` + `decorateRequest`\n * surface as the IncomingMessage path; only the hook function signatures\n * differ (they receive `WebPluginContext` instead of `PluginContext`).\n *\n * Plugin authors who target both shapes can branch on the context type\n * via a type guard (`'responseHeaders' in ctx`) OR ship two separate\n * `register()` exports — one for each runtime adapter. Most plugins\n * register hooks at the IncomingMessage path today (legacy); future\n * Web-native plugins will register against `WebTheoApp`.\n */\nexport interface WebTheoApp {\n addHook<K extends HookName>(name: K, fn: WebHookByName<K>): void\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- T documents the value type for plugin authors\n decorateRequest<T>(key: string, value: T): void\n}\n\n/**\n * Web-Standards plugin shape. Identical to `TheoPlugin` except the\n * `register(app)` argument is `WebTheoApp` instead of `TheoApp`.\n *\n * Cross-runtime plugins ship BOTH `TheoPlugin` + `WebTheoPlugin` exports;\n * the adapter (Node, CF Workers, Bun, Deno) picks the matching one based\n * on which runtime executes the plugin chain. This is the canonical\n * Hono/Nitro pattern.\n */\nexport interface WebTheoPlugin {\n name: string\n register(app: WebTheoApp): void | Promise<void>\n}\n\n/**\n * Identity function for Web plugin authors — same auto-completion +\n * type-inference DX as `definePlugin`, but for the Web-shaped `WebTheoApp`.\n */\nexport function defineWebPlugin(plugin: WebTheoPlugin): WebTheoPlugin {\n return plugin\n}\n","/**\n * M31 Phase 3 — `plugin()`, the fluent builder that replaces `definePlugin({...})`.\n *\n * Collects lifecycle hooks + request decorations and SYNTHESIZES the `register(app)` function, so\n * authors never write the imperative `register` body. `.build()` returns a `TheoPlugin` the plugin\n * runner consumes UNCHANGED.\n *\n * export default plugin('request-id')\n * .onRequest((ctx) => { ctx.ctx.requestId = crypto.randomUUID() })\n * .onResponse((ctx) => { ctx.response.setHeader('x-request-id', String(ctx.ctx.requestId)) })\n * .build()\n */\nimport {\n definePlugin,\n type TheoPlugin,\n type TheoApp,\n type OnRequestHook,\n type PreHandlerHook,\n type OnResponseHook,\n type OnErrorHook,\n} from '../plugin-types.js'\n\n/** The fluent plugin builder. `name` is set at entry; every hook is optional and may repeat. */\nexport interface PluginBuilder {\n /** Register an `onRequest` hook (runs before the CSRF gate). May be called multiple times. */\n onRequest(fn: OnRequestHook): PluginBuilder\n /** Register a `preHandler` hook (after CSRF, before the route handler). */\n preHandler(fn: PreHandlerHook): PluginBuilder\n /** Register an `onResponse` hook (after the handler returns). */\n onResponse(fn: OnResponseHook): PluginBuilder\n /** Register an `onError` hook (error path). */\n onError(fn: OnErrorHook): PluginBuilder\n /** Decorate every request with a key/value pair (available on `ctx.ctx[key]`). */\n decorateRequest<T>(key: string, value: T): PluginBuilder\n /** Resolve to the `TheoPlugin` — a synthesized `{ name, register }` the runner consumes. */\n build(): TheoPlugin\n}\n\ninterface PluginSpecAccumulator {\n name: string\n onRequest: OnRequestHook[]\n preHandler: PreHandlerHook[]\n onResponse: OnResponseHook[]\n onError: OnErrorHook[]\n decorations: { key: string; value: unknown }[]\n}\n\nfunction makePluginBuilder(spec: PluginSpecAccumulator): PluginBuilder {\n const runtime: PluginBuilder = {\n onRequest: (fn) => makePluginBuilder({ ...spec, onRequest: [...spec.onRequest, fn] }),\n preHandler: (fn) => makePluginBuilder({ ...spec, preHandler: [...spec.preHandler, fn] }),\n onResponse: (fn) => makePluginBuilder({ ...spec, onResponse: [...spec.onResponse, fn] }),\n onError: (fn) => makePluginBuilder({ ...spec, onError: [...spec.onError, fn] }),\n decorateRequest: (key, value) =>\n makePluginBuilder({ ...spec, decorations: [...spec.decorations, { key, value }] }),\n build: () =>\n definePlugin({\n name: spec.name,\n register(app: TheoApp): void {\n for (const fn of spec.onRequest) app.addHook('onRequest', fn)\n for (const fn of spec.preHandler) app.addHook('preHandler', fn)\n for (const fn of spec.onResponse) app.addHook('onResponse', fn)\n for (const fn of spec.onError) app.addHook('onError', fn)\n for (const d of spec.decorations) app.decorateRequest(d.key, d.value)\n },\n }),\n }\n return runtime\n}\n\n/** Start a fluent plugin definition. `name` is required; chain hooks/decorations, then `.build()`. */\nexport function plugin(name: string): PluginBuilder {\n return makePluginBuilder({\n name,\n onRequest: [],\n preHandler: [],\n onResponse: [],\n onError: [],\n decorations: [],\n })\n}\n","import type { UIMessageChunk } from 'ai'\n\n/**\n * M0 (theokit-ai-first) — serialize a stream of ai-sdk `UIMessageChunk`s into a\n * Web-Standards `Response` on the UIMessageStream wire so `@ai-sdk/react`'s\n * `useChat` consumes it WITHOUT a custom adapter.\n *\n * Wire contract (must match ai-sdk's consumer transport exactly):\n * - `content-type: text/event-stream`\n * - `x-vercel-ai-ui-message-stream: v1` — the version marker `useChat` checks\n * - each chunk framed as `data: ${JSON.stringify(chunk)}\\n\\n`\n * - a terminal `data: [DONE]\\n\\n` after the last chunk (ignored by the parser)\n *\n * Web Standards only — `Response` + `ReadableStream` (G8, no node:http). The\n * headers commit before the stream starts.\n *\n * Fail-clear (error-handling.md): if the source iterable throws mid-stream, the\n * `[DONE]` terminal is still flushed and the stream is closed — never left\n * hanging. (The translator upstream already closes gracefully; this is defense\n * in depth for any other chunk source.)\n */\nconst UI_MESSAGE_STREAM_HEADERS = {\n 'content-type': 'text/event-stream',\n 'x-vercel-ai-ui-message-stream': 'v1',\n} as const\n\nconst DONE_FRAME = 'data: [DONE]\\n\\n'\n\nfunction encode(text: string): Uint8Array {\n return new TextEncoder().encode(text)\n}\n\nexport function uiMessageStreamResponse(chunks: AsyncIterable<UIMessageChunk>): Response {\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of chunks) {\n controller.enqueue(encode(`data: ${JSON.stringify(chunk)}\\n\\n`))\n }\n } catch {\n // The source iterable aborted mid-stream. The upstream translator owns\n // error semantics (it surfaces failures as chunks + closes gracefully);\n // this transport's sole guarantee is a terminated stream — fall through\n // to the DONE terminal rather than re-throw and error an open stream.\n } finally {\n controller.enqueue(encode(DONE_FRAME))\n controller.close()\n }\n },\n })\n return new Response(stream, { headers: UI_MESSAGE_STREAM_HEADERS })\n}\n","import type { IncomingMessage } from 'node:http'\n\nimport type { WebSocketLike } from './define-websocket.js'\n\nexport interface ChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Define a channel handler for WebSocket rooms.\n * Identity function — provides type inference for channel handlers.\n */\nexport function defineChannel<TMessage = unknown>(\n handler: ChannelHandler<TMessage>,\n): ChannelHandler<TMessage> {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 2/3 — Web-Standards channel handler.\n *\n * Mirror of `ChannelHandler<TMessage>` for the Web `Request` shape.\n * `onSubscribe` receives `request: Request` instead of `req: IncomingMessage`\n * — the rest of the surface (onMessage, onUnsubscribe) is shape-agnostic\n * (WebSocketLike is already Web-standards-compatible per `define-websocket.ts`).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F.\n *\n * **Architectural note:** WebSocket upgrade semantics differ across\n * runtimes:\n * - Node: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * hands you `req: IncomingMessage` at the upgrade handshake.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request) — hands you `request: Request`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Channel handlers targeting CF/Bun/Deno use `WebChannelHandler`; legacy\n * Node consumers stay on `ChannelHandler`. Cross-runtime channels ship\n * both shapes.\n */\nexport interface WebChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, request: Request) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Web-Standards `defineChannel` sibling. Identity function — provides\n * type inference for Web channel handlers.\n */\nexport function defineWebChannel<TMessage = unknown>(\n handler: WebChannelHandler<TMessage>,\n): WebChannelHandler<TMessage> {\n return handler\n}\n"],"mappings":"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","names":["plugin"]}
|
package/dist/chunk-VRVNM3QL.js
CHANGED
|
File without changes
|
package/dist/chunk-WR4F4EEZ.js
CHANGED
|
File without changes
|
package/dist/chunk-Y4TOVMNC.js
CHANGED
|
File without changes
|
package/dist/chunk-YJWEADAW.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/db-3UNAMSFK.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Item #4 — `defineAgentTool`
|
|
5
|
+
*
|
|
6
|
+
* Sugar over the `@theokit/sdk` `CustomTool` contract. Takes a Zod schema +
|
|
7
|
+
* handler and produces a structurally-compatible `CustomTool` that
|
|
8
|
+
* `Agent.create({ tools: [...] })` accepts.
|
|
9
|
+
*
|
|
10
|
+
* Uses Zod v4's native `z.toJSONSchema()` to convert the input schema to
|
|
11
|
+
* JSON Schema for LLM providers.
|
|
12
|
+
*
|
|
13
|
+
* Handler error propagation:
|
|
14
|
+
* `defineAgentTool` parses the input via the Zod schema BEFORE calling the
|
|
15
|
+
* user handler. Invalid input throws a `ZodError`, which the SDK's tool-
|
|
16
|
+
* dispatcher treats as a tool failure and surfaces to the model as a tool
|
|
17
|
+
* error (the SDK owns the wire; ADR D3).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Local mirror of the SDK's `CustomTool` interface. We don't `import type`
|
|
21
|
+
* from `@theokit/sdk` because the SDK is an optional peer (consumers who
|
|
22
|
+
* never call `defineAgentTool` shouldn't need it installed). The shape is
|
|
23
|
+
* the wire contract; any structurally-matching object is accepted by
|
|
24
|
+
* `Agent.create({ tools })`.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
interface CustomTool {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: Record<string, unknown>;
|
|
32
|
+
handler: (input: Record<string, unknown>, ctx?: {
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
context?: unknown;
|
|
35
|
+
}) => string | Promise<string>;
|
|
36
|
+
/** M18 — optional per-target formatters for the app's UI/transcript (ignored by the SDK wire). */
|
|
37
|
+
transform?: ToolTransform;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* M18 — per-target formatters. `display` shapes the rich handler result for the UI; `transcript`
|
|
41
|
+
* shapes it for a saved transcript. Applied by {@link applyTransform}, never by the model wire.
|
|
42
|
+
*/
|
|
43
|
+
interface ToolTransform<R = unknown> {
|
|
44
|
+
display?: (result: R) => unknown;
|
|
45
|
+
transcript?: (result: R) => unknown;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Spec accepted by {@link defineAgentTool}. `inputSchema` is a Zod 3 schema
|
|
49
|
+
* rooted in `z.object(...)`. The `handler` argument type is inferred via
|
|
50
|
+
* `z.infer<T>`.
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
interface DefineAgentToolSpec<T extends z.ZodType, R = string> {
|
|
55
|
+
/** Tool name surfaced to the LLM. Must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$`. */
|
|
56
|
+
name: string;
|
|
57
|
+
/** Description surfaced to the LLM. Required — drives tool-selection accuracy. */
|
|
58
|
+
description: string;
|
|
59
|
+
/** Zod schema describing the input. Must be `z.object(...)` at the root. */
|
|
60
|
+
inputSchema: T;
|
|
61
|
+
/**
|
|
62
|
+
* Handler invoked with the parsed input and, optionally, the run `ctx` (M7). `ctx.context`
|
|
63
|
+
* is the object supplied once at the agent level (`defineAgent({ context })`) or per-run —
|
|
64
|
+
* read it for shared config like `projectRoot` instead of baking it into the factory.
|
|
65
|
+
* `ctx.signal` is the abort signal. Optional so existing one-arg handlers keep working.
|
|
66
|
+
*
|
|
67
|
+
* M18 — the handler may return RICH data `R` (not just a string) when `toModelOutput` is
|
|
68
|
+
* provided to map it to the model-visible string.
|
|
69
|
+
*/
|
|
70
|
+
handler: (input: z.infer<T>, ctx?: {
|
|
71
|
+
signal?: AbortSignal;
|
|
72
|
+
context?: unknown;
|
|
73
|
+
}) => R | Promise<R>;
|
|
74
|
+
/**
|
|
75
|
+
* M18 — map the rich handler result `R` to the string the model sees. Required (in practice)
|
|
76
|
+
* when `handler` returns a non-string; absent ⇒ the handler must return a string.
|
|
77
|
+
*/
|
|
78
|
+
toModelOutput?: (result: R) => string;
|
|
79
|
+
/** M18 — per-target formatters (`display` / `transcript`) for the app, applied by {@link applyTransform}. */
|
|
80
|
+
transform?: ToolTransform<R>;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* M18 — apply a tool's `transform` for a target (`display` / `transcript`). Returns the formatted
|
|
84
|
+
* value, or the raw `result` when the tool declares no transform for that target.
|
|
85
|
+
*/
|
|
86
|
+
declare function applyTransform(tool: CustomTool, result: unknown, target: 'display' | 'transcript'): unknown;
|
|
87
|
+
|
|
88
|
+
export { type CustomTool as C, type DefineAgentToolSpec as D, type ToolTransform as T, applyTransform as a };
|
|
File without changes
|
package/dist/dev-5ZQMWVFC.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/docker-LZZB4D5E.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -8,29 +8,30 @@ import {
|
|
|
8
8
|
scanRoutes,
|
|
9
9
|
theoConfigSchema,
|
|
10
10
|
theoPlugin
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HAOPVC47.js";
|
|
12
|
+
import "./chunk-D7ZH7DTG.js";
|
|
12
13
|
import "./chunk-7BIM27LV.js";
|
|
13
14
|
import "./chunk-RSVN727G.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-4MTCKE5I.js";
|
|
16
|
+
import "./chunk-TGTNRUH3.js";
|
|
17
|
+
import "./chunk-GY5Q27BJ.js";
|
|
16
18
|
import "./chunk-5QW7IQQU.js";
|
|
19
|
+
import "./chunk-WFNLNIJX.js";
|
|
17
20
|
import "./chunk-IAJ2JVEH.js";
|
|
18
21
|
import "./chunk-VMEWD57H.js";
|
|
19
22
|
import "./chunk-JQSKBMXP.js";
|
|
20
23
|
import "./chunk-RKDH4DWL.js";
|
|
21
24
|
import "./chunk-WSJKACWB.js";
|
|
22
|
-
import "./chunk-JBCHWRKF.js";
|
|
23
|
-
import "./chunk-C3ZZ56YZ.js";
|
|
24
|
-
import "./chunk-7MQOHNHE.js";
|
|
25
|
-
import "./chunk-X2VVCJ4V.js";
|
|
26
|
-
import "./chunk-TGTNRUH3.js";
|
|
27
|
-
import "./chunk-GY5Q27BJ.js";
|
|
28
|
-
import "./chunk-WFNLNIJX.js";
|
|
29
25
|
import "./chunk-ZEGYW52B.js";
|
|
26
|
+
import "./chunk-JBCHWRKF.js";
|
|
30
27
|
import "./chunk-TSLSIRBR.js";
|
|
31
28
|
import "./chunk-UD3LFGDL.js";
|
|
32
29
|
import "./chunk-X32XEJXR.js";
|
|
33
30
|
import "./chunk-UVXB2ER7.js";
|
|
31
|
+
import "./chunk-HZ6USUHC.js";
|
|
32
|
+
import "./chunk-C3ZZ56YZ.js";
|
|
33
|
+
import "./chunk-7MQOHNHE.js";
|
|
34
|
+
import "./chunk-X2VVCJ4V.js";
|
|
34
35
|
import "./chunk-DGUM43GV.js";
|
|
35
36
|
|
|
36
37
|
// src/config/define-config.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/define-config.ts","../src/config/config-builder.ts","../src/config/validate-structure.ts","../src/core/errors.ts"],"sourcesContent":["import type { TheoConfig } from './schema.js'\n\n/**\n * Define Theo framework configuration.\n * Identity function — provides type inference for theo.config.ts.\n * Runtime validation happens in loadConfig(), not here.\n */\nexport function defineConfig(config: Partial<TheoConfig>): Partial<TheoConfig> {\n return config\n}\n","/**\n * M31 Phase 3 — `config()`, the fluent builder that replaces `defineConfig({...})`.\n *\n * Config is a ~30-field flat bag — a pure setter chain would be worse DX than an object literal\n * (Vite/Nuxt/Astro keep config as identity for this reason). So `config()` is HYBRID (ADR-M31-3):\n * chainable setters for the common fields PLUS a `.set(partial)` escape hatch for the long tail.\n * `.build()` delegates to the internal {@link defineConfig} (identity) — `loadConfig` is UNCHANGED.\n *\n * export default config()\n * .serverDir('core')\n * .agentsDir('core/agents')\n * .appDir('apps/web')\n * .set({ security: { csrf: 'strict' } })\n * .build()\n */\nimport { defineConfig } from './define-config.js'\nimport type { TheoConfig } from './schema.js'\n\n/** The fluent config builder. No field is required; `.set()` merges arbitrary config fields. */\nexport interface ConfigBuilder {\n /** Project identifier (DNS-1123) — used by `.theokit/services.json`. */\n name(value: TheoConfig['name']): ConfigBuilder\n /** Backend root dir (route/action/agent discovery). Default `'server'`. */\n serverDir(value: TheoConfig['serverDir']): ConfigBuilder\n /** Frontend root dir (file-based router). Default `'app'`. */\n appDir(value: TheoConfig['appDir']): ConfigBuilder\n /** Agents root dir. Default `'agents'`. */\n agentsDir(value: TheoConfig['agentsDir']): ConfigBuilder\n /** Build output dir. Default `'.theokit'`. */\n distDir(value: TheoConfig['distDir']): ConfigBuilder\n /** Dev/prod port. Default `3000`. */\n port(value: TheoConfig['port']): ConfigBuilder\n /** Bind host. Default `'localhost'`. */\n host(value: TheoConfig['host']): ConfigBuilder\n /** Enable server-side rendering. Default `false`. */\n ssr(value: TheoConfig['ssr']): ConfigBuilder\n /** Escape hatch — merge any config fields not covered by a dedicated setter (rate-limit, security…). */\n set(partial: Partial<TheoConfig>): ConfigBuilder\n /** Resolve to the `Partial<TheoConfig>` — the SAME value `defineConfig({...})` returns. */\n build(): Partial<TheoConfig>\n}\n\nfunction makeConfigBuilder(spec: Partial<TheoConfig>): ConfigBuilder {\n const merge = (patch: Partial<TheoConfig>): ConfigBuilder =>\n makeConfigBuilder({ ...spec, ...patch })\n return {\n name: (value) => merge({ name: value }),\n serverDir: (value) => merge({ serverDir: value }),\n appDir: (value) => merge({ appDir: value }),\n agentsDir: (value) => merge({ agentsDir: value }),\n distDir: (value) => merge({ distDir: value }),\n port: (value) => merge({ port: value }),\n host: (value) => merge({ host: value }),\n ssr: (value) => merge({ ssr: value }),\n set: (partial) => merge(partial),\n build: () => defineConfig(spec),\n }\n}\n\n/**\n * Start a fluent config definition. Chain the common setters and/or `.set(partial)`, then `.build()`.\n */\nexport function config(): ConfigBuilder {\n return makeConfigBuilder({})\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Project-structure validator. Reads paths joined onto `projectRoot`,\n * with names from a fixed `ValidationRule[]` table. No HTTP input.\n */\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport { TheoProjectError } from '../core/errors.js'\n\ninterface ValidationRule {\n path: string\n errorMessage: string\n}\n\nconst REQUIRED_FILES: ValidationRule[] = [\n {\n path: 'theo.config.ts',\n errorMessage: 'Missing required file: theo.config.ts',\n },\n {\n path: 'package.json',\n errorMessage: 'Missing required file: package.json',\n },\n]\n\n// #95 — honor config `appDir` (default \"app\") so a project that groups its frontend under a custom\n// directory (e.g. `apps/web`) is not rejected by a hardcoded `app/` requirement.\nexport function validateProjectStructure(rootDir: string, appDir = 'app'): void {\n if (!existsSync(rootDir)) {\n throw new TheoProjectError([`Project directory does not exist: ${rootDir}`], rootDir)\n }\n\n const errors: string[] = []\n\n const requiredDirs: ValidationRule[] = [\n { path: appDir, errorMessage: `Missing required directory: ${appDir}/` },\n ]\n\n for (const rule of requiredDirs) {\n if (!existsSync(join(rootDir, rule.path))) {\n errors.push(rule.errorMessage)\n }\n }\n\n for (const rule of REQUIRED_FILES) {\n if (!existsSync(join(rootDir, rule.path))) {\n errors.push(rule.errorMessage)\n }\n }\n\n if (errors.length > 0) {\n throw new TheoProjectError(errors, rootDir)\n }\n}\n","export class TheoProjectError extends Error {\n public readonly errors: string[]\n public readonly rootDir: string\n\n constructor(errors: string[], rootDir: string) {\n const errorLines = errors.map((e) => ` - ${e}`).join('\\n')\n\n super(\n `Invalid Theo project structure\\n\\n` +\n ` Root: ${rootDir}\\n\\n` +\n (errorLines ? ` Errors:\\n${errorLines}\\n` : ''),\n )\n\n this.name = 'TheoProjectError'\n this.errors = errors\n this.rootDir = rootDir\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/config/define-config.ts","../src/config/config-builder.ts","../src/config/validate-structure.ts","../src/core/errors.ts"],"sourcesContent":["import type { TheoConfig } from './schema.js'\n\n/**\n * Define Theo framework configuration.\n * Identity function — provides type inference for theo.config.ts.\n * Runtime validation happens in loadConfig(), not here.\n */\nexport function defineConfig(config: Partial<TheoConfig>): Partial<TheoConfig> {\n return config\n}\n","/**\n * M31 Phase 3 — `config()`, the fluent builder that replaces `defineConfig({...})`.\n *\n * Config is a ~30-field flat bag — a pure setter chain would be worse DX than an object literal\n * (Vite/Nuxt/Astro keep config as identity for this reason). So `config()` is HYBRID (ADR-M31-3):\n * chainable setters for the common fields PLUS a `.set(partial)` escape hatch for the long tail.\n * `.build()` delegates to the internal {@link defineConfig} (identity) — `loadConfig` is UNCHANGED.\n *\n * export default config()\n * .serverDir('core')\n * .agentsDir('core/agents')\n * .appDir('apps/web')\n * .set({ security: { csrf: 'strict' } })\n * .build()\n */\nimport { defineConfig } from './define-config.js'\nimport type { TheoConfig } from './schema.js'\n\n/** The fluent config builder. No field is required; `.set()` merges arbitrary config fields. */\nexport interface ConfigBuilder {\n /** Project identifier (DNS-1123) — used by `.theokit/services.json`. */\n name(value: TheoConfig['name']): ConfigBuilder\n /** Backend root dir (route/action/agent discovery). Default `'server'`. */\n serverDir(value: TheoConfig['serverDir']): ConfigBuilder\n /** Frontend root dir (file-based router). Default `'app'`. */\n appDir(value: TheoConfig['appDir']): ConfigBuilder\n /** Agents root dir. Default `'agents'`. */\n agentsDir(value: TheoConfig['agentsDir']): ConfigBuilder\n /** Build output dir. Default `'.theokit'`. */\n distDir(value: TheoConfig['distDir']): ConfigBuilder\n /** Dev/prod port. Default `3000`. */\n port(value: TheoConfig['port']): ConfigBuilder\n /** Bind host. Default `'localhost'`. */\n host(value: TheoConfig['host']): ConfigBuilder\n /** Enable server-side rendering. Default `false`. */\n ssr(value: TheoConfig['ssr']): ConfigBuilder\n /** Escape hatch — merge any config fields not covered by a dedicated setter (rate-limit, security…). */\n set(partial: Partial<TheoConfig>): ConfigBuilder\n /** Resolve to the `Partial<TheoConfig>` — the SAME value `defineConfig({...})` returns. */\n build(): Partial<TheoConfig>\n}\n\nfunction makeConfigBuilder(spec: Partial<TheoConfig>): ConfigBuilder {\n const merge = (patch: Partial<TheoConfig>): ConfigBuilder =>\n makeConfigBuilder({ ...spec, ...patch })\n return {\n name: (value) => merge({ name: value }),\n serverDir: (value) => merge({ serverDir: value }),\n appDir: (value) => merge({ appDir: value }),\n agentsDir: (value) => merge({ agentsDir: value }),\n distDir: (value) => merge({ distDir: value }),\n port: (value) => merge({ port: value }),\n host: (value) => merge({ host: value }),\n ssr: (value) => merge({ ssr: value }),\n set: (partial) => merge(partial),\n build: () => defineConfig(spec),\n }\n}\n\n/**\n * Start a fluent config definition. Chain the common setters and/or `.set(partial)`, then `.build()`.\n */\nexport function config(): ConfigBuilder {\n return makeConfigBuilder({})\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Project-structure validator. Reads paths joined onto `projectRoot`,\n * with names from a fixed `ValidationRule[]` table. No HTTP input.\n */\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport { TheoProjectError } from '../core/errors.js'\n\ninterface ValidationRule {\n path: string\n errorMessage: string\n}\n\nconst REQUIRED_FILES: ValidationRule[] = [\n {\n path: 'theo.config.ts',\n errorMessage: 'Missing required file: theo.config.ts',\n },\n {\n path: 'package.json',\n errorMessage: 'Missing required file: package.json',\n },\n]\n\n// #95 — honor config `appDir` (default \"app\") so a project that groups its frontend under a custom\n// directory (e.g. `apps/web`) is not rejected by a hardcoded `app/` requirement.\nexport function validateProjectStructure(rootDir: string, appDir = 'app'): void {\n if (!existsSync(rootDir)) {\n throw new TheoProjectError([`Project directory does not exist: ${rootDir}`], rootDir)\n }\n\n const errors: string[] = []\n\n const requiredDirs: ValidationRule[] = [\n { path: appDir, errorMessage: `Missing required directory: ${appDir}/` },\n ]\n\n for (const rule of requiredDirs) {\n if (!existsSync(join(rootDir, rule.path))) {\n errors.push(rule.errorMessage)\n }\n }\n\n for (const rule of REQUIRED_FILES) {\n if (!existsSync(join(rootDir, rule.path))) {\n errors.push(rule.errorMessage)\n }\n }\n\n if (errors.length > 0) {\n throw new TheoProjectError(errors, rootDir)\n }\n}\n","export class TheoProjectError extends Error {\n public readonly errors: string[]\n public readonly rootDir: string\n\n constructor(errors: string[], rootDir: string) {\n const errorLines = errors.map((e) => ` - ${e}`).join('\\n')\n\n super(\n `Invalid Theo project structure\\n\\n` +\n ` Root: ${rootDir}\\n\\n` +\n (errorLines ? ` Errors:\\n${errorLines}\\n` : ''),\n )\n\n this.name = 'TheoProjectError'\n this.errors = errors\n this.rootDir = rootDir\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,SAAS,aAAaA,SAAkD;AAC7E,SAAOA;AACT;;;ACiCA,SAAS,kBAAkB,MAA0C;AACnE,QAAM,QAAQ,CAAC,UACb,kBAAkB,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;AACzC,SAAO;AAAA,IACL,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,WAAW,CAAC,UAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,QAAQ,CAAC,UAAU,MAAM,EAAE,QAAQ,MAAM,CAAC;AAAA,IAC1C,WAAW,CAAC,UAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,SAAS,CAAC,UAAU,MAAM,EAAE,SAAS,MAAM,CAAC;AAAA,IAC5C,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,KAAK,CAAC,UAAU,MAAM,EAAE,KAAK,MAAM,CAAC;AAAA,IACpC,KAAK,CAAC,YAAY,MAAM,OAAO;AAAA,IAC/B,OAAO,MAAM,aAAa,IAAI;AAAA,EAChC;AACF;AAKO,SAAS,SAAwB;AACtC,SAAO,kBAAkB,CAAC,CAAC;AAC7B;;;AC5DA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;;;ACLd,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EAEhB,YAAY,QAAkB,SAAiB;AAC7C,UAAM,aAAa,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAE1D;AAAA,MACE;AAAA;AAAA,UACa,OAAO;AAAA;AAAA,KACjB,aAAa;AAAA,EAAc,UAAU;AAAA,IAAO;AAAA,IACjD;AAEA,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AACF;;;ADHA,IAAM,iBAAmC;AAAA,EACvC;AAAA,IACE,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AACF;AAIO,SAAS,yBAAyB,SAAiB,SAAS,OAAa;AAC9E,MAAI,CAAC,WAAW,OAAO,GAAG;AACxB,UAAM,IAAI,iBAAiB,CAAC,qCAAqC,OAAO,EAAE,GAAG,OAAO;AAAA,EACtF;AAEA,QAAM,SAAmB,CAAC;AAE1B,QAAM,eAAiC;AAAA,IACrC,EAAE,MAAM,QAAQ,cAAc,+BAA+B,MAAM,IAAI;AAAA,EACzE;AAEA,aAAW,QAAQ,cAAc;AAC/B,QAAI,CAAC,WAAW,KAAK,SAAS,KAAK,IAAI,CAAC,GAAG;AACzC,aAAO,KAAK,KAAK,YAAY;AAAA,IAC/B;AAAA,EACF;AAEA,aAAW,QAAQ,gBAAgB;AACjC,QAAI,CAAC,WAAW,KAAK,SAAS,KAAK,IAAI,CAAC,GAAG;AACzC,aAAO,KAAK,KAAK,YAAY;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,IAAI,iBAAiB,QAAQ,OAAO;AAAA,EAC5C;AACF;","names":["config"]}
|
package/dist/info-2OOXFTJX.js
CHANGED
|
File without changes
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import "./chunk-RSVN727G.js";
|
|
2
|
+
import {
|
|
3
|
+
BATCH_PATH,
|
|
4
|
+
TRACE_HEADER,
|
|
5
|
+
createCorsHandler,
|
|
6
|
+
executeAction,
|
|
7
|
+
executeRoute,
|
|
8
|
+
extractTraceId,
|
|
9
|
+
handleBatchRequest,
|
|
10
|
+
sendError
|
|
11
|
+
} from "./chunk-TGTNRUH3.js";
|
|
12
|
+
import "./chunk-GY5Q27BJ.js";
|
|
2
13
|
import {
|
|
3
14
|
findSuggestion
|
|
4
15
|
} from "./chunk-5QW7IQQU.js";
|
|
16
|
+
import {
|
|
17
|
+
logRequest
|
|
18
|
+
} from "./chunk-WFNLNIJX.js";
|
|
5
19
|
import {
|
|
6
20
|
createPluginRunnerFromConfig
|
|
7
21
|
} from "./chunk-IAJ2JVEH.js";
|
|
@@ -21,6 +35,7 @@ import {
|
|
|
21
35
|
scanWebSocketRoutes
|
|
22
36
|
} from "./chunk-RKDH4DWL.js";
|
|
23
37
|
import "./chunk-WSJKACWB.js";
|
|
38
|
+
import "./chunk-ZEGYW52B.js";
|
|
24
39
|
import {
|
|
25
40
|
CSP_REPORT_PATH,
|
|
26
41
|
CsrfReadinessStore,
|
|
@@ -28,29 +43,14 @@ import {
|
|
|
28
43
|
handleCspReport,
|
|
29
44
|
handleCsrfReadiness
|
|
30
45
|
} from "./chunk-JBCHWRKF.js";
|
|
31
|
-
import {
|
|
32
|
-
generateNonce
|
|
33
|
-
} from "./chunk-C3ZZ56YZ.js";
|
|
34
|
-
import "./chunk-X2VVCJ4V.js";
|
|
35
|
-
import {
|
|
36
|
-
BATCH_PATH,
|
|
37
|
-
TRACE_HEADER,
|
|
38
|
-
createCorsHandler,
|
|
39
|
-
executeAction,
|
|
40
|
-
executeRoute,
|
|
41
|
-
extractTraceId,
|
|
42
|
-
handleBatchRequest,
|
|
43
|
-
sendError
|
|
44
|
-
} from "./chunk-TGTNRUH3.js";
|
|
45
|
-
import "./chunk-GY5Q27BJ.js";
|
|
46
|
-
import {
|
|
47
|
-
logRequest
|
|
48
|
-
} from "./chunk-WFNLNIJX.js";
|
|
49
|
-
import "./chunk-ZEGYW52B.js";
|
|
50
46
|
import "./chunk-TSLSIRBR.js";
|
|
51
47
|
import "./chunk-UD3LFGDL.js";
|
|
52
48
|
import "./chunk-X32XEJXR.js";
|
|
53
49
|
import "./chunk-UVXB2ER7.js";
|
|
50
|
+
import {
|
|
51
|
+
generateNonce
|
|
52
|
+
} from "./chunk-C3ZZ56YZ.js";
|
|
53
|
+
import "./chunk-X2VVCJ4V.js";
|
|
54
54
|
import "./chunk-DGUM43GV.js";
|
|
55
55
|
export {
|
|
56
56
|
BATCH_PATH,
|
|
@@ -80,4 +80,4 @@ export {
|
|
|
80
80
|
scanWebSocketRoutes,
|
|
81
81
|
sendError
|
|
82
82
|
};
|
|
83
|
-
//# sourceMappingURL=internal-api-
|
|
83
|
+
//# sourceMappingURL=internal-api-QSP2HCUU.js.map
|
|
File without changes
|
|
File without changes
|
package/dist/mcp-VMKWB2BY.js
CHANGED
|
File without changes
|
package/dist/netlify-PMLHVPN4.js
CHANGED
|
File without changes
|
package/dist/node-BPJ3Z4DT.js
CHANGED
|
File without changes
|
package/dist/openapi-ERYWAT3A.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/router-TLEAOFID.js
CHANGED
|
File without changes
|
package/dist/routes-XNS3UM3B.js
CHANGED
|
File without changes
|
package/dist/scan-7MJC6PYU.js
CHANGED
|
File without changes
|
package/dist/schema-LYOLNHZ7.js
CHANGED
|
File without changes
|