theokit 0.40.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/{actions-virtual-module-RNPMHJOM.js → actions-virtual-module-LD3YKWIX.js} +2 -2
  2. package/dist/{actions-virtual-module-YGKSEIOJ.js → actions-virtual-module-N7GKUS3D.js} +3 -3
  3. package/dist/{agent-ST6GB3VX.js → agent-U35G3WNE.js} +2 -2
  4. package/dist/{app-typed-client-YSLQU5HT.js → app-typed-client-6YZRDAPY.js} +3 -3
  5. package/dist/{app-typed-client-FQPUOL6A.js → app-typed-client-V77SVU2O.js} +2 -2
  6. package/dist/{build-VAR5EFOU.js → build-BYLQZJT2.js} +2 -2
  7. package/dist/{chunk-L4CYLM2V.js → chunk-2ZX4J4SX.js} +11 -7
  8. package/dist/chunk-2ZX4J4SX.js.map +1 -0
  9. package/dist/{chunk-KLFCJQXU.js → chunk-AXVFVMLM.js} +17 -3
  10. package/dist/chunk-AXVFVMLM.js.map +1 -0
  11. package/dist/{chunk-63BUBV5L.js → chunk-E25FBYJP.js} +1 -1
  12. package/dist/chunk-E25FBYJP.js.map +1 -0
  13. package/dist/{chunk-YMS6KMKA.js → chunk-FEDSPOY6.js} +2 -2
  14. package/dist/{chunk-MYDS52BG.js → chunk-IPC5UREF.js} +13 -9
  15. package/dist/chunk-IPC5UREF.js.map +1 -0
  16. package/dist/{chunk-EV33DOG6.js → chunk-JQJN6LFK.js} +2 -2
  17. package/dist/{chunk-HQQADLLD.js → chunk-SPJNVWOK.js} +2 -2
  18. package/dist/{chunk-SPFMJAFW.js → chunk-UI6FWWOF.js} +2 -2
  19. package/dist/{chunk-HEDLJJDF.js → chunk-UNLG36Z5.js} +17 -3
  20. package/dist/{chunk-HEDLJJDF.js.map → chunk-UNLG36Z5.js.map} +1 -1
  21. package/dist/{chunk-BEQQ6WCK.js → chunk-UO7WS32S.js} +2 -2
  22. package/dist/{chunk-32GOXYA7.js → chunk-XZ4QD5IN.js} +7 -3
  23. package/dist/{chunk-32GOXYA7.js.map → chunk-XZ4QD5IN.js.map} +1 -1
  24. package/dist/cli/index.js +6 -6
  25. package/dist/client/core.js +1 -1
  26. package/dist/client/index.js +1 -1
  27. package/dist/{define-agent-tool-ChaGymol.d.ts → define-agent-tool-cRuSpidb.d.ts} +29 -9
  28. package/dist/{dev-VAIYPLV6.js → dev-PS2NGT6I.js} +5 -5
  29. package/dist/{generate-ATHMC4ET.js → generate-5X4LG77M.js} +12 -17
  30. package/dist/generate-5X4LG77M.js.map +1 -0
  31. package/dist/index.js +2 -2
  32. package/dist/{internal-api-ORXPQTEI.js → internal-api-FBFV265J.js} +3 -3
  33. package/dist/{internal-api-MRTUTAM7.js → internal-api-LFW7R65K.js} +2 -2
  34. package/dist/{mcp-SMDPAW7T.js → mcp-ML4QK5ON.js} +2 -2
  35. package/dist/server/agent/index.d.ts +1 -1
  36. package/dist/server/agent/index.js +2 -2
  37. package/dist/server/define/index.d.ts +2 -2
  38. package/dist/server/define/index.js +2 -2
  39. package/dist/server/index.d.ts +1 -1
  40. package/dist/server/index.js +3 -3
  41. package/dist/{start-MK3MNSFB.js → start-YLR2SFHU.js} +91 -10
  42. package/dist/start-YLR2SFHU.js.map +1 -0
  43. package/dist/vite-plugin/index.js +2 -2
  44. package/dist/{vite-plugin-WB57H4AT.js → vite-plugin-6VVU6PPC.js} +5 -5
  45. package/package.json +5 -4
  46. package/dist/chunk-63BUBV5L.js.map +0 -1
  47. package/dist/chunk-KLFCJQXU.js.map +0 -1
  48. package/dist/chunk-L4CYLM2V.js.map +0 -1
  49. package/dist/chunk-MYDS52BG.js.map +0 -1
  50. package/dist/generate-ATHMC4ET.js.map +0 -1
  51. package/dist/start-MK3MNSFB.js.map +0 -1
  52. /package/dist/{actions-virtual-module-RNPMHJOM.js.map → actions-virtual-module-LD3YKWIX.js.map} +0 -0
  53. /package/dist/{actions-virtual-module-YGKSEIOJ.js.map → actions-virtual-module-N7GKUS3D.js.map} +0 -0
  54. /package/dist/{agent-ST6GB3VX.js.map → agent-U35G3WNE.js.map} +0 -0
  55. /package/dist/{app-typed-client-YSLQU5HT.js.map → app-typed-client-6YZRDAPY.js.map} +0 -0
  56. /package/dist/{app-typed-client-FQPUOL6A.js.map → app-typed-client-V77SVU2O.js.map} +0 -0
  57. /package/dist/{build-VAR5EFOU.js.map → build-BYLQZJT2.js.map} +0 -0
  58. /package/dist/{chunk-YMS6KMKA.js.map → chunk-FEDSPOY6.js.map} +0 -0
  59. /package/dist/{chunk-EV33DOG6.js.map → chunk-JQJN6LFK.js.map} +0 -0
  60. /package/dist/{chunk-HQQADLLD.js.map → chunk-SPJNVWOK.js.map} +0 -0
  61. /package/dist/{chunk-SPFMJAFW.js.map → chunk-UI6FWWOF.js.map} +0 -0
  62. /package/dist/{chunk-BEQQ6WCK.js.map → chunk-UO7WS32S.js.map} +0 -0
  63. /package/dist/{dev-VAIYPLV6.js.map → dev-PS2NGT6I.js.map} +0 -0
  64. /package/dist/{internal-api-MRTUTAM7.js.map → internal-api-FBFV265J.js.map} +0 -0
  65. /package/dist/{internal-api-ORXPQTEI.js.map → internal-api-LFW7R65K.js.map} +0 -0
  66. /package/dist/{mcp-SMDPAW7T.js.map → mcp-ML4QK5ON.js.map} +0 -0
  67. /package/dist/{vite-plugin-WB57H4AT.js.map → vite-plugin-6VVU6PPC.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/http/controller-dispatch.ts","../src/server/agent/mount-agent.ts","../src/server/agent/build-agent-streamer.ts","../src/server/agent/approval-registry.ts","../src/server/agent/durable-ui-message-stream-response.ts","../src/server/agent/run-event-cache.ts","../src/server/agent/provider-resolver.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Controller files are walked from the developer's `serverDir/controllers`\n * (a build-time config path), never from HTTP input. No injection vector.\n */\nimport { readdirSync, type Dirent } from 'node:fs'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { join } from 'node:path'\n\nimport { createDecoratorHandler, isControllerClass, type ServeAgent } from '@theokit/http'\n\nimport { dispatchCsrfWarn } from '../security/csrf-warn-dispatch.js'\nimport { enforceCsrf, type DisallowedConfig } from '../security/csrf.js'\n\nimport { incomingMessageToWebRequest } from './node-request.js'\nimport { sendError } from './send-response.js'\n\n/** A decorator controller constructor (`@Controller` class). */\ntype ControllerClass = new (...args: never[]) => object\n\n/** Loads a controller module by absolute path. In dev this is Vite's `ssrLoadModule`\n * (the Task 1.1 swc transform has already compiled the parameter decorators); tests\n * inject `@theokit/http`'s `loadControllerWithSwc`. */\nexport type ControllerModuleLoader = (absPath: string) => Promise<Record<string, unknown>>\n\n/** A built controller route table exposed as a pure Web-Standard handler. */\nexport interface ControllerDispatcher {\n /** `null` = no controller route matched — the host owns the miss (404 / fall-through). */\n dispatch(request: Request): Promise<Response | null>\n /** Non-executing route probe — true when a controller route owns `method` + `pathname`. */\n matches(method: string, pathname: string): boolean\n}\n\n// State-mutating methods get CSRF, mirroring the file-route pipeline (execute.ts).\nconst CSRF_PROTECTED_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\n/** Recursively collect `*.controller.ts` files under `dir` (absolute paths). */\nfunction findControllerFiles(dir: string): string[] {\n const found: string[] = []\n const walk = (current: string): void => {\n let entries: Dirent[]\n try {\n entries = readdirSync(current, { withFileTypes: true })\n } catch {\n return // dir doesn't exist — no controllers\n }\n for (const entry of entries) {\n const full = join(current, entry.name)\n if (entry.isDirectory()) walk(full)\n else if (entry.name.endsWith('.controller.ts')) found.push(full)\n }\n }\n walk(dir)\n return found\n}\n\n/** A discovered controller: its source file + the loaded `@Controller` class. */\nexport interface ControllerModule {\n filePath: string\n cls: ControllerClass\n}\n\n/**\n * Load every `@Controller` class under `controllersDir` via the injected loader,\n * keeping each class paired with its source file (needed by the typed-client\n * codegen to emit `import type { X } from '<file>'`). Non-controller exports are\n * ignored (`isControllerClass` — reused from @theokit/http).\n */\nexport async function scanControllerModules(\n controllersDir: string,\n loadModule: ControllerModuleLoader,\n): Promise<ControllerModule[]> {\n const files = findControllerFiles(controllersDir)\n const modules: ControllerModule[] = []\n for (const filePath of files) {\n const mod = await loadModule(filePath)\n for (const exported of Object.values(mod)) {\n if (typeof exported === 'function' && isControllerClass(exported)) {\n modules.push({ filePath, cls: exported as ControllerClass })\n }\n }\n }\n return modules\n}\n\n/** Load every `@Controller` class under `controllersDir` (classes only). */\nexport async function scanControllers(\n controllersDir: string,\n loadModule: ControllerModuleLoader,\n): Promise<ControllerClass[]> {\n const modules = await scanControllerModules(controllersDir, loadModule)\n return modules.map((m) => m.cls)\n}\n\n/**\n * Scan `controllersDir` and build a Web-Standard dispatcher over the decorator\n * controllers found. Returns `null` when the directory has no controllers, so\n * the host can skip the controller path entirely (zero cost for routes-only apps).\n *\n * Dispatch REUSES @theokit/http's `createDecoratorHandler` (match + `@Param`\n * binding + `@Body` validation + Response building) — never re-implemented (ADR-1).\n */\nexport async function createControllerDispatcher(opts: {\n controllersDir: string\n loadModule: ControllerModuleLoader\n /** M47 — serves `@Expose`-bound agent routes (theo supplies a `mountAgent`-backed impl). */\n serveAgent?: ServeAgent\n}): Promise<ControllerDispatcher | null> {\n const classes = await scanControllers(opts.controllersDir, opts.loadModule)\n if (classes.length === 0) return null\n const handle = createDecoratorHandler({ controllers: classes, serveAgent: opts.serveAgent })\n return {\n dispatch: (request) => handle(request),\n matches: (method, pathname) => handle.matches(method, pathname),\n }\n}\n\n/** Write a buffered Web `Response` (controllers never stream) to a Node response. */\nasync function writeControllerResponse(res: ServerResponse, response: Response): Promise<void> {\n const headersBag: Record<string, string> = {}\n for (const [k, v] of response.headers) {\n if (k.toLowerCase() !== 'set-cookie') headersBag[k] = v\n }\n const setCookies = response.headers.getSetCookie()\n if (setCookies.length > 0) res.setHeader('Set-Cookie', setCookies)\n res.writeHead(response.status, headersBag)\n const body = response.body ? await response.text() : ''\n res.end(body || undefined)\n}\n\n/**\n * The `api-middleware` fall-through in one call: scan `controllersDir`, build the\n * dispatcher, and serve the request. Builds a body-ful Web `Request` (`@Body`\n * needs the body; the raw stream is undrained at a route miss) and enforces CSRF\n * with the SAME gate file routes use (parity). Returns `true` when a controller\n * handled it (or CSRF blocked it), `false` when there are no controllers OR none\n * matched (the host continues to its own 404). Built per-miss so controller edits\n * reflect via HMR.\n */\nexport async function dispatchControllerRequest(args: {\n controllersDir: string\n loadModule: ControllerModuleLoader\n req: IncomingMessage\n res: ServerResponse\n csrfMode: 'off' | 'warn' | 'strict'\n disallowed?: DisallowedConfig\n requestId: string\n /** M47 — serves `@Expose`-bound agent routes (mountAgent-backed); omit for routes-only apps. */\n serveAgent?: ServeAgent\n}): Promise<boolean> {\n const { req, res, csrfMode, disallowed, requestId } = args\n const dispatcher = await createControllerDispatcher({\n controllersDir: args.controllersDir,\n loadModule: args.loadModule,\n serveAgent: args.serveAgent,\n })\n if (!dispatcher) return false\n\n const method = (req.method ?? 'GET').toUpperCase()\n const webRequest = incomingMessageToWebRequest(req)\n const pathname = new URL(webRequest.url).pathname\n\n // CSRF parity: enforce ONLY when a protected-method controller route actually\n // owns this path (probe with the non-executing matcher — never double-dispatch,\n // which would run the handler + its side effects). An unrouted path falls\n // through to the host's own 404, not a 403.\n if (CSRF_PROTECTED_METHODS.has(method) && dispatcher.matches(method, pathname)) {\n const decision = enforceCsrf(\n req,\n csrfMode,\n { warn: dispatchCsrfWarn, path: req.url },\n disallowed,\n )\n if (!decision.allow) {\n sendError(\n res,\n 'CSRF_INVALID',\n decision.reason ?? 'CSRF check failed',\n 403,\n undefined,\n requestId,\n )\n return true\n }\n }\n\n const response = await dispatcher.dispatch(webRequest)\n if (response === null) return false\n await writeControllerResponse(res, response)\n return true\n}\n","/**\n * M2 (theokit-ai-first) — mount a scanned `agents/<name>.ts` module as an SSE endpoint.\n *\n * The SINGLE wiring point shared by dev (vite middleware) and prod (built server), so the\n * two never drift (EC-4). Web-Standard `Request` → `Response`: parse the chat body, compile\n * the module (`compileAgentModule`, converges both surfaces), stream via the M0/M1 canonical\n * protocol (`streamAgentUIMessages` → `uiMessageStreamResponse`).\n *\n * Request body — accepts the `@ai-sdk/react` `useChat` shape (`{ id, messages: UIMessage[] }`,\n * the typed-client path) AND a simple `{ message, sessionId? }` shape (M0/M1-style clients).\n */\nimport { compileAgentModule, resolveEnabledSkills, streamAgentUIMessages } from '@theokit/agents'\n\nimport { validateCsrfRequest, type CsrfMode } from '../security/csrf.js'\n\nimport { buildAgentHitl } from './build-agent-streamer.js'\nimport { durableUiMessageStreamResponse } from './durable-ui-message-stream-response.js'\nimport { getRunEventCache, mintRunId } from './run-event-cache.js'\n\n/** The message + session extracted from a chat request, or `null` when the body is invalid. */\nexport interface AgentRequestInput {\n message: string\n sessionId: string\n}\n\n/** Extract the text of a `{ type: 'text', text: string }` part from an untrusted value. */\nfunction partText(part: unknown): string {\n if (typeof part !== 'object' || part === null) return ''\n const p = part as Record<string, unknown>\n return p.type === 'text' && typeof p.text === 'string' ? p.text : ''\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 * Extract `{ message, sessionId }` from a chat request body. Returns `null` when neither the\n * ai-sdk `messages` shape nor the simple `message` shape yields non-empty user text.\n */\nexport function parseAgentRequestBody(body: unknown): AgentRequestInput | null {\n if (typeof body !== 'object' || body === null) return null\n const b = body as Record<string, unknown>\n\n // ai-sdk useChat shape: { id, messages: UIMessage[] } — take the last message's text parts.\n if (Array.isArray(b.messages) && b.messages.length > 0) {\n const last = b.messages[b.messages.length - 1] as Record<string, unknown>\n const parts = Array.isArray(last.parts) ? last.parts : []\n const text = parts.map(partText).join('')\n if (text.length === 0) return null\n const sessionId = typeof b.id === 'string' && b.id.length > 0 ? b.id : crypto.randomUUID()\n return { message: text, sessionId }\n }\n\n // Simple shape: { message, sessionId? }.\n if (typeof b.message === 'string' && b.message.length > 0) {\n const sessionId =\n typeof b.sessionId === 'string' && b.sessionId.length > 0 ? b.sessionId : crypto.randomUUID()\n return { message: b.message, sessionId }\n }\n\n return null\n}\n\n/**\n * Mount a loaded agent module as a `Response`. `apiKey` is resolved by the caller\n * (`resolveProvider`). `source` labels a fail-fast `AgentDefinitionError` (the file path).\n */\nexport async function mountAgent(\n mod: unknown,\n request: Request,\n apiKey: string,\n source = 'agent module',\n csrfMode: CsrfMode = 'strict',\n): Promise<Response> {\n // Enforce CSRF BEFORE any work — an agent run spends real LLM tokens, so a cross-origin\n // POST must be rejected before it reaches the SDK (parity with actions/routes). The custom\n // `X-Theo-Action` header + Origin match is the same defense `executeRoute`/`executeAction`\n // apply; the `useAgent` client sends the header. `off` skips; `warn` never blocks.\n if (csrfMode !== 'off') {\n const csrf = validateCsrfRequest(request)\n if (!csrf.valid && csrfMode === 'strict') {\n return jsonError(403, 'CSRF_FAILED', `CSRF check failed: ${csrf.reason}`)\n }\n }\n\n const compiled = compileAgentModule(mod, source)\n\n // M13 — resolve a per-request skills selector (from `defineAgent({ skills: (ctx) => [...] })`)\n // against the M7 run-context, setting `skills.enabled` before the SDK runs. `undefined` ⇒ the\n // SDK enables every discovered skill. `compiled` is fresh per request, so mutation is safe.\n if (compiled.skillsResolver) {\n const enabled = await resolveEnabledSkills(compiled.skillsResolver, compiled.runContext ?? {})\n if (enabled !== undefined) compiled.skills = { enabled, autoInject: true }\n }\n\n let body: unknown = null\n try {\n body = await request.json()\n } catch {\n /* invalid/empty JSON → handled below as a 400 */\n }\n\n const input = parseAgentRequestBody(body)\n if (input === null) {\n return jsonError(400, 'BAD_REQUEST', 'Request must contain a non-empty message or messages[].')\n }\n\n // When the agent has @HumanInTheLoop-gated tools (M4), wire the pause: the plugin's `awaitApproval`\n // registers a pending approval in the shared registry (the Promise that PAUSES the run); the\n // approve route (`handleAgentApproval`) resolves it. No gated tools ⇒ the M2 stream path unchanged.\n // Extracted to `build-agent-streamer.ts` (M39 / DRY — the thread routes reuse the same wiring).\n const hitl = buildAgentHitl(compiled)\n\n // M37 (ADR-0046) — mint a transport runId + stream through the durable layer:\n // each SSE frame is cached + `id:`-tagged so a dropped client can reconnect\n // (or a second client observe) via `GET /api/agents/<name>/runs/<runId>/stream`.\n // The runId is surfaced in the `x-theokit-run-id` response header.\n const runId = mintRunId()\n return durableUiMessageStreamResponse(\n streamAgentUIMessages(compiled, apiKey, { ...input, hitl, signal: request.signal }),\n { runId, cache: getRunEventCache() },\n )\n}\n","/**\n * M39 (ADR-0048) — shared agent-run streamer builders, extracted from\n * `mount-agent.ts` (DRY / G12) so the thread routes drive the SAME SDK run path\n * as the plain POST. Reuses SDK primitives (`compileAgentModule` +\n * `streamAgentUIMessages`) — it does NOT reimplement the loop (G2).\n */\n\nimport {\n compileAgentModule,\n type HumanInTheLoopOptions,\n resolveEnabledSkills,\n streamAgentUIMessages,\n} from '@theokit/agents'\nimport type { UIMessageChunk } from 'ai'\n\nimport { getApprovalRegistry } from './approval-registry.js'\n\ntype Compiled = ReturnType<typeof compileAgentModule>\n\n/**\n * Build the HITL wiring for a compiled agent: gated tools register a pending\n * approval in the shared registry (the Promise that PAUSES the run). `undefined`\n * when the agent has no `@HumanInTheLoop`-gated tools. Extracted verbatim from\n * `mountAgent` so both the plain POST and the thread routes wire HITL identically.\n */\nexport function buildAgentHitl(compiled: Compiled) {\n const gated = compiled.hitl\n if (gated === undefined || gated.size === 0) return undefined\n const registry = getApprovalRegistry()\n return {\n gated,\n awaitApproval: (approvalId: string, opts: HumanInTheLoopOptions, toolName: string) =>\n registry.register(approvalId, {\n timeoutMs: opts.timeout ?? 300_000,\n onTimeout: opts.onTimeout ?? 'abort',\n toolName,\n question: opts.question,\n ...(opts.payloadSchema !== undefined ? { payloadSchema: opts.payloadSchema } : {}),\n }),\n }\n}\n\n/**\n * A `startRun(sessionId, message)` closure for the thread dispatcher. Per run it\n * compiles the module fresh (skills resolution mutates `compiled`), resolves\n * per-request skills, builds HITL, and streams. Headless — no request signal (a\n * thread continuation runs to completion into the durable cache, not to a client).\n */\nexport function makeThreadStartRun(\n mod: unknown,\n apiKey: string,\n source: string,\n): (sessionId: string, message: string) => AsyncIterable<UIMessageChunk> {\n return (sessionId, message) =>\n (async function* () {\n const compiled = compileAgentModule(mod, source)\n if (compiled.skillsResolver) {\n const enabled = await resolveEnabledSkills(\n compiled.skillsResolver,\n compiled.runContext ?? {},\n )\n if (enabled !== undefined) compiled.skills = { enabled, autoInject: true }\n }\n const hitl = buildAgentHitl(compiled)\n yield* streamAgentUIMessages(compiled, apiKey, { message, sessionId, hitl })\n })()\n}\n","/**\n * M4 (theokit-ai-first) — the in-process HITL approval registry.\n *\n * The HITL plugin's `awaitApproval` calls `register(approvalId)` and awaits the returned Promise\n * (this is what genuinely PAUSES the SDK run — the SDK `pre_tool_call` hook is awaited). The\n * approve route calls `resolve(approvalId, approved)` to settle it. A per-approval timeout settles\n * the Promise deterministically per the `@HumanInTheLoop` `onTimeout` policy so a hung approval\n * never leaks the paused stream.\n *\n * Single-process contract (ADR 0038 / plan Drawback 2): a multi-instance deploy needs a shared\n * registry — the interface is injectable so a durable impl (Redis, etc.) slots in without touching\n * the harness. We do NOT build a durable store now (YAGNI).\n */\n// The timeout policy vocabulary is owned by the `@HumanInTheLoop` decorator (DRY / G12) — reuse it\n// rather than re-declaring the union, so the two can never drift.\nimport type { TimeoutAction } from '@theokit/agents'\n\nexport type { TimeoutAction }\n\nexport interface RegisterOptions {\n /** Milliseconds before the approval auto-settles per `onTimeout`. */\n timeoutMs: number\n /**\n * What a timeout means. Only `'proceed'` auto-approves; `'abort'` and `'retry'` both deny — the\n * registry does NOT implement retry semantics (a timed-out `'retry'` is a deny, not a re-prompt).\n */\n onTimeout: TimeoutAction\n /** M14 — the gated tool name, surfaced by `list()` (optional; absent for legacy callers). */\n toolName?: string\n /** M14 — the approval question, surfaced by `list()` (optional). */\n question?: string\n /**\n * M20 — an optional JSON-schema descriptor of the custom payload the approver may attach. Carried\n * verbatim into `list()` + the `approval_required` event so the UI knows what to collect. Kept as\n * a plain JSON object (not a live Zod schema) so the registry stays serializable and SDK-free.\n */\n payloadSchema?: Record<string, unknown>\n}\n\n/**\n * M20 — a settled HITL decision. `approved` is the allow/deny bit (backward-compatible with the\n * legacy boolean); `reason` + `payload` are the optional approver-attached extras that surface to\n * the model (on denial, via the veto message) and to the app/UI.\n */\nexport interface ApprovalDecision {\n approved: boolean\n reason?: string\n payload?: unknown\n}\n\n/** M14 — a pending approval as surfaced by {@link ApprovalRegistry.list}. */\nexport interface PendingApproval {\n approvalId: string\n toolName?: string\n question?: string\n /** Epoch millis when the pending approval auto-settles (registeredAt + timeoutMs). */\n expiresAt: number\n /** M20 — the declared custom-payload schema, if the gated tool declares one. */\n payloadSchema?: Record<string, unknown>\n}\n\nexport interface ApprovalRegistry {\n /**\n * Register a pending approval; the returned Promise settles with the full {@link ApprovalDecision}\n * on `resolve` or timeout (M20 — was a bare boolean pre-M20).\n */\n register(approvalId: string, opts: RegisterOptions): Promise<ApprovalDecision>\n /**\n * Settle a pending approval. Accepts a full {@link ApprovalDecision} OR a bare boolean (coerced to\n * `{ approved }` — backward-compatible). Returns false if the id is unknown or already settled.\n */\n resolve(approvalId: string, decision: boolean | ApprovalDecision): boolean\n /** M14 — list the currently-pending approvals (process-wide; single-process contract). */\n list(): PendingApproval[]\n}\n\ninterface Pending {\n settle: (decision: ApprovalDecision) => void\n timer: ReturnType<typeof setTimeout>\n info: PendingApproval\n}\n\n/**\n * The one process-wide registry the stream mount (`mountAgent`) and the approve route share.\n *\n * The in-process impl holds LIVE Promise resolvers in memory — the approval a request awaits and\n * the approval the route resolves MUST be the same object, so a single instance per process is not\n * a convenience but a correctness requirement. Lazily created; a durable/multi-instance deploy\n * swaps this accessor for a shared-store impl (ADR 0038 / plan Drawback 2) without touching callers.\n * Tests use {@link createInProcessApprovalRegistry} directly — never this singleton.\n */\nlet serverRegistry: ApprovalRegistry | undefined\nexport function getApprovalRegistry(): ApprovalRegistry {\n serverRegistry ??= createInProcessApprovalRegistry()\n return serverRegistry\n}\n\nexport function createInProcessApprovalRegistry(): ApprovalRegistry {\n const pending = new Map<string, Pending>()\n\n return {\n register(approvalId, opts) {\n return new Promise<ApprovalDecision>((resolve) => {\n const settle = (decision: ApprovalDecision): void => {\n const entry = pending.get(approvalId)\n if (!entry) return\n clearTimeout(entry.timer)\n pending.delete(approvalId)\n resolve(decision)\n }\n // 'proceed' → allow on timeout; 'abort'/'retry' → deny on timeout.\n const timer = setTimeout(() => {\n settle({ approved: opts.onTimeout === 'proceed' })\n }, opts.timeoutMs)\n const info: PendingApproval = {\n approvalId,\n toolName: opts.toolName,\n question: opts.question,\n expiresAt: Date.now() + opts.timeoutMs,\n ...(opts.payloadSchema !== undefined ? { payloadSchema: opts.payloadSchema } : {}),\n }\n pending.set(approvalId, { settle, timer, info })\n })\n },\n resolve(approvalId, decision) {\n const entry = pending.get(approvalId)\n if (!entry) return false\n // M20 — coerce the legacy bare-boolean form to a decision object.\n entry.settle(typeof decision === 'boolean' ? { approved: decision } : decision)\n return true\n },\n list() {\n return [...pending.values()].map((p) => p.info)\n },\n }\n}\n","import type { UIMessageChunk } from 'ai'\n\nimport type { RunEventCache } from './run-event-cache.js'\n\n/**\n * M37 (ADR-0046) — the DURABLE variant of `uiMessageStreamResponse`. Same\n * `UIMessageStream` wire (`useChat` still consumes it), plus three additions so\n * a dropped client can reconnect without missing chunks:\n *\n * 1. each SSE frame gains a monotonic `id: <seq>\\n` line (SSE-native — the\n * browser echoes it as `Last-Event-ID` on reconnect, ADR-0046 D3);\n * 2. every frame is `append`ed to the {@link RunEventCache} keyed by `runId`\n * so the reconnect endpoint can replay it;\n * 3. the response carries `x-theokit-run-id: <runId>` so the client learns the\n * reconnect key (ADR-0046 D2).\n *\n * Fail-clear (error-handling.md): if the source aborts mid-stream, the run is\n * still `end`ed in the cache and `[DONE]` is flushed — never left hanging.\n */\n\n/** The UIMessageStream SSE base headers — shared by the encoder + reconnect handler (DRY). */\nexport const SSE_BASE_HEADERS = {\n 'content-type': 'text/event-stream',\n 'x-vercel-ai-ui-message-stream': 'v1',\n} as const\n\n/** Header the client reads to obtain the reconnect key. */\nexport const RUN_ID_HEADER = 'x-theokit-run-id'\n\nexport const SSE_DONE_FRAME = 'data: [DONE]\\n\\n'\n\n/** Format one SSE frame with its sequence id (shared by the encoder + reconnect replay). */\nexport function formatSseFrame(seq: number, data: string): string {\n return `id: ${seq}\\ndata: ${data}\\n\\n`\n}\n\n/** UTF-8 encode an SSE frame for a `ReadableStream<Uint8Array>` (shared). */\nexport function encodeSse(text: string): Uint8Array {\n return new TextEncoder().encode(text)\n}\n\nexport interface DurableStreamDeps {\n readonly runId: string\n readonly cache: RunEventCache\n}\n\nexport function durableUiMessageStreamResponse(\n chunks: AsyncIterable<UIMessageChunk>,\n deps: DurableStreamDeps,\n): Response {\n const { runId, cache } = deps\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of chunks) {\n const data = JSON.stringify(chunk)\n const seq = cache.append(runId, data)\n controller.enqueue(encodeSse(formatSseFrame(seq, data)))\n }\n } catch {\n // Source aborted mid-stream. The upstream translator owns error\n // semantics (surfaces failures as chunks + closes gracefully); this\n // transport guarantees only a terminated, cache-ended stream.\n } finally {\n cache.end(runId)\n controller.enqueue(encodeSse(SSE_DONE_FRAME))\n controller.close()\n }\n },\n })\n return new Response(stream, {\n headers: { ...SSE_BASE_HEADERS, [RUN_ID_HEADER]: runId },\n })\n}\n","/**\n * M37 (ADR-0046) — the durable event cache behind resumable agent streams.\n *\n * As an agent turn streams over SSE, each `UIMessageChunk` frame is `append`ed\n * here keyed by a transport `runId`. A client that drops and reconnects (or a\n * second client that observes) `attach`es to the run: it replays the frames it\n * missed (`seq > Last-Event-ID`) and then follows the live tail. This is the\n * TRANSPORT half of durable agents (ADR-0040/0044) — it caches serialized\n * frames, it does NOT run the agent loop.\n *\n * Single-process by default (an in-memory `Map`, same contract as the HITL\n * `approval-registry`). A persistent backend (Redis / `ConversationStorageAdapter`)\n * plugs in behind {@link RunEventCache} for multi-instance deploys — it is NOT\n * shipped in core (ADR-0046 D4: no broker in core).\n */\n\n/** One recorded SSE frame: its monotonic sequence id + the serialized `data:` payload. */\nexport interface CachedFrame {\n readonly seq: number\n readonly data: string\n}\n\n/** The result of {@link RunEventCache.attach}. */\nexport interface AttachResult {\n /** False when `runId` is unknown (never started, or evicted). */\n readonly known: boolean\n /** Frames with `seq > afterSeq`, in order — replay these before the live tail. */\n readonly replay: readonly CachedFrame[]\n /** True when the run already terminated: `replay` is complete, no live frames follow. */\n readonly ended: boolean\n /** Detach the live listener (idempotent). */\n readonly unsubscribe: () => void\n}\n\n/**\n * A per-`runId` ordered frame buffer with live fan-out. Implemented in-memory by\n * default; swap a persistent backend for multi-instance deploys.\n */\nexport interface RunEventCache {\n /**\n * M39 — synchronously register `runId` as a live (frame-less) run so `has()` is\n * true and a subscriber can `attach()` BEFORE the first frame. Idempotent.\n * Closes the race where a thread's active run is resolvable in the registry but\n * not yet in the cache (a headless pump appends its first frame asynchronously).\n */\n begin(runId: string): void\n /** Record a frame for `runId`, returning its assigned monotonic `seq`. Notifies live listeners. */\n append(runId: string, data: string): number\n /** Mark `runId` terminated: notify listeners, then schedule bounded eviction. Idempotent. */\n end(runId: string): void\n /** Whether `runId` is currently cached (started + not yet evicted). */\n has(runId: string): boolean\n /**\n * Atomically snapshot the frames after `afterSeq` AND (when the run is still\n * live) register `onFrame`/`onEnd` in the SAME synchronous tick — so no frame\n * slips between replay and subscribe, and none is duplicated.\n */\n attach(\n runId: string,\n afterSeq: number,\n onFrame: (frame: CachedFrame) => void,\n onEnd: () => void,\n ): AttachResult\n}\n\ninterface Listener {\n readonly onFrame: (frame: CachedFrame) => void\n readonly onEnd: () => void\n}\n\ninterface RunBuffer {\n readonly frames: CachedFrame[]\n ended: boolean\n readonly listeners: Set<Listener>\n evictTimer?: ReturnType<typeof setTimeout>\n}\n\nconst DEFAULT_EVICT_AFTER_MS = 5 * 60_000 // 5 min after end (parity with approval-registry)\n\nconst NOOP_UNSUBSCRIBE = (): void => {\n // No live listener was registered (unknown or already-ended run).\n}\n\nexport interface RunEventCacheOptions {\n /** Milliseconds after `end()` before a run's buffer is evicted. Default 5 min. */\n readonly evictAfterMs?: number\n}\n\nexport function createInMemoryRunEventCache(opts: RunEventCacheOptions = {}): RunEventCache {\n const evictAfterMs = opts.evictAfterMs ?? DEFAULT_EVICT_AFTER_MS\n const runs = new Map<string, RunBuffer>()\n\n function getOrCreate(runId: string): RunBuffer {\n let buf = runs.get(runId)\n if (buf === undefined) {\n buf = { frames: [], ended: false, listeners: new Set() }\n runs.set(runId, buf)\n }\n return buf\n }\n\n return {\n begin(runId) {\n getOrCreate(runId)\n },\n\n append(runId, data) {\n const buf = getOrCreate(runId)\n const seq = buf.frames.length\n const frame: CachedFrame = { seq, data }\n buf.frames.push(frame)\n // Notify live listeners (a throwing listener must not break the others).\n for (const l of buf.listeners) {\n try {\n l.onFrame(frame)\n } catch {\n /* a broken subscriber never breaks the producer or its peers */\n }\n }\n return seq\n },\n\n has(runId) {\n return runs.has(runId)\n },\n\n end(runId) {\n const buf = runs.get(runId)\n if (buf === undefined || buf.ended) return\n buf.ended = true\n for (const l of buf.listeners) {\n try {\n l.onEnd()\n } catch {\n /* isolate a broken subscriber */\n }\n }\n buf.listeners.clear()\n buf.evictTimer = setTimeout(() => runs.delete(runId), evictAfterMs)\n // Never keep the process alive just for an eviction timer.\n buf.evictTimer.unref()\n },\n\n attach(runId, afterSeq, onFrame, onEnd) {\n const buf = runs.get(runId)\n if (buf === undefined) {\n return { known: false, replay: [], ended: false, unsubscribe: NOOP_UNSUBSCRIBE }\n }\n // Synchronous snapshot — no `await` before the subscribe below, so no\n // append can interleave (single-threaded): no gap, no dup.\n const replay = buf.frames.filter((f) => f.seq > afterSeq)\n if (buf.ended) {\n return { known: true, replay, ended: true, unsubscribe: NOOP_UNSUBSCRIBE }\n }\n const listener: Listener = { onFrame, onEnd }\n buf.listeners.add(listener)\n return {\n known: true,\n replay,\n ended: false,\n unsubscribe: () => {\n buf.listeners.delete(listener)\n },\n }\n },\n }\n}\n\n/**\n * Process-wide singleton — the SSE encoder (`durableUiMessageStreamResponse`) and\n * the reconnect endpoint MUST share ONE cache. Lazily created; a multi-instance\n * deploy swaps this accessor for a shared-store impl (ADR-0046 D4) without\n * touching callers. Tests use {@link createInMemoryRunEventCache} directly.\n */\nlet serverCache: RunEventCache | undefined\nexport function getRunEventCache(): RunEventCache {\n serverCache ??= createInMemoryRunEventCache()\n return serverCache\n}\n\n/** Mint a stable transport `runId` (the reconnect key, ADR-0046 D2). */\nexport function mintRunId(): string {\n return `run-${crypto.randomUUID()}`\n}\n","/**\n * Provider Resolver — Strategy + Registry pattern (FAANG-grade).\n *\n * Inspiração: Dapr Conversation Registry (`dapr/pkg/components/conversation/registry.go`)\n * + Encore Manager provider array (`encore/runtimes/go/pubsub/manager_internal.go`).\n *\n * Princípio: provider routing é responsabilidade do FRAMEWORK, não do consumer.\n * Consumer template usa `model: { id: 'gpt-4o-mini' }` puro — sem conditionals.\n *\n * Wire protocol: OpenAI Chat Completions (universal — implementado por todos\n * os providers: OpenRouter, Groq, Mistral, Together, Anthropic via proxy, etc).\n *\n * Resolução por prioridade (FIRST match wins):\n * 1. OPENROUTER_API_KEY → baseUrl=openrouter.ai (gateway multi-modelo)\n * 2. OPENAI_API_KEY → baseUrl=api.openai.com\n * 3. ANTHROPIC_API_KEY → direct Anthropic (Messages API, não OpenAI-compat)\n *\n * Escape hatch: `options.apiKey` explícito SOBREPÕE auto-resolution\n * (consumer pode forçar provider específico se quiser).\n */\n\n/**\n * Provider configuration descriptor — Registry entry shape.\n *\n * @public\n */\nexport interface ProviderDescriptor {\n /** Stable name used internally — não exposto no wire. */\n name: string\n /** Environment variable that holds the API key for this provider. */\n envKey: string\n /** Base URL for the provider's OpenAI-compatible (or native) API. */\n baseUrl: string\n /** Resolution priority (lower = higher priority). FIRST match wins. */\n priority: number\n}\n\n/**\n * Resolved provider configuration — output of `resolveProvider()`.\n *\n * @public\n */\nexport interface ResolvedProvider {\n name: string\n apiKey: string\n baseUrl: string\n}\n\n/**\n * Default provider registry. Order = priority (first = highest).\n *\n * Adding a new provider:\n * 1. Append entry below (or register via `registerProvider()`).\n * 2. Set `envKey` matching the user's env var convention.\n * 3. Set `baseUrl` to the OpenAI-compat endpoint (or native if not compat).\n * 4. Provider name used in telemetry/logs only — never wire-exposed.\n */\nconst DEFAULT_REGISTRY: ProviderDescriptor[] = [\n {\n name: 'openrouter',\n envKey: 'OPENROUTER_API_KEY',\n baseUrl: 'https://openrouter.ai/api/v1',\n priority: 1,\n },\n {\n name: 'openai',\n envKey: 'OPENAI_API_KEY',\n baseUrl: 'https://api.openai.com/v1',\n priority: 2,\n },\n {\n name: 'anthropic',\n envKey: 'ANTHROPIC_API_KEY',\n baseUrl: 'https://api.anthropic.com',\n priority: 3,\n },\n]\n\n/**\n * Runtime registry — copy of DEFAULT_REGISTRY mutable via registerProvider().\n * Sorted by priority on every resolve (stable, O(n log n) — n <= ~10 providers).\n */\nconst registry: ProviderDescriptor[] = [...DEFAULT_REGISTRY]\n\n/**\n * Register a new provider (Registry pattern — runtime extension point).\n * Useful for self-hosted endpoints or custom providers without touching theokit src.\n *\n * @example\n * registerProvider({\n * name: 'self-hosted',\n * envKey: 'SELF_HOSTED_API_KEY',\n * baseUrl: 'https://llm.internal.acme.com/v1',\n * priority: 0, // highest priority\n * })\n *\n * @public\n */\nexport function registerProvider(descriptor: ProviderDescriptor): void {\n // Idempotent — replace existing by name.\n const idx = registry.findIndex((p) => p.name === descriptor.name)\n if (idx >= 0) registry[idx] = descriptor\n else registry.push(descriptor)\n}\n\n/**\n * Reset registry to DEFAULT_REGISTRY (test-only / dev escape hatch).\n *\n * @public\n */\nexport function resetProviderRegistry(): void {\n registry.length = 0\n registry.push(...DEFAULT_REGISTRY)\n}\n\n/**\n * Get current registry snapshot (read-only — inspection).\n *\n * @public\n */\nexport function listProviders(): readonly ProviderDescriptor[] {\n return [...registry].sort((a, b) => a.priority - b.priority)\n}\n\n/**\n * Resolve provider from env vars by priority. FIRST env var found wins.\n *\n * @returns ResolvedProvider with apiKey + baseUrl + name\n * @throws Error if NO provider env var is set (actionable message)\n *\n * @public\n */\nexport function resolveProvider(): ResolvedProvider {\n const sorted = [...registry].sort((a, b) => a.priority - b.priority)\n for (const desc of sorted) {\n const apiKey = process.env[desc.envKey]\n if (apiKey && apiKey.length > 0) {\n return {\n name: desc.name,\n apiKey,\n baseUrl: desc.baseUrl,\n }\n }\n }\n // No env var found — emit actionable error.\n const envKeys = sorted.map((p) => p.envKey).join(' OR ')\n throw new Error(\n `No LLM provider API key found in environment. Set one of: ${envKeys}. ` +\n `Get a free OpenRouter key at https://openrouter.ai/keys (recommended — one key, many models).`,\n )\n}\n\n/**\n * Try to resolve — does NOT throw. Returns null if no provider available.\n * Useful for graceful degradation (e.g., mock mode).\n *\n * @public\n */\nexport function tryResolveProvider(): ResolvedProvider | null {\n try {\n return resolveProvider()\n } catch {\n return null\n }\n}\n"],"mappings":"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","names":["compileAgentModule","resolveEnabledSkills","streamAgentUIMessages","registry","compileAgentModule","resolveEnabledSkills","streamAgentUIMessages"]}