theokit 0.25.0 → 0.26.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.
@@ -823,11 +823,16 @@ declare class CodeModePermissionDeniedError extends Error {
823
823
  constructor(tool: string, reason?: string);
824
824
  }
825
825
  /**
826
- * Build a code-mode `CustomTool`. Fails fast if `onPermissionRequest` or `sandbox` is missing
827
- * (security by default). The returned tool takes `{ code }`, assembles the permission-gated restricted
828
- * API from `tools`, runs the code in the injected sandbox, and returns the code's result.
829
- */
830
- declare function createCodeMode(config: CodeModeConfig): CustomTool;
826
+ * Build a code-mode tool + its generated model instructions (M40 / ADR-0049). Fails fast if
827
+ * `onPermissionRequest` or `sandbox` is missing (security by default). `tool` takes `{ code }`,
828
+ * assembles the permission-gated restricted API from `tools`, runs the code in the injected sandbox,
829
+ * and returns the code's result. `instructions` (add it to the agent's system prompt) teaches the
830
+ * model the sandboxed-code contract + the available `api.<name>(input)` calls.
831
+ */
832
+ declare function createCodeMode(config: CodeModeConfig): {
833
+ tool: CustomTool;
834
+ instructions: string;
835
+ };
831
836
 
832
837
  /**
833
838
  * M27 (ADR-0041) — channel webhook routes: `POST /api/agents/<name>/channels/<platform>/webhook`.
@@ -1223,6 +1223,23 @@ var CodeModePermissionDeniedError = class extends Error {
1223
1223
  this.name = "CodeModePermissionDeniedError";
1224
1224
  }
1225
1225
  };
1226
+ function describeToolInput(inputSchema) {
1227
+ const props = inputSchema.properties ?? {};
1228
+ const required = new Set(inputSchema.required ?? []);
1229
+ const entries = Object.entries(props).map(([key, spec]) => {
1230
+ const type = typeof spec.type === "string" ? spec.type : "unknown";
1231
+ return `${key}${required.has(key) ? "" : "?"}: ${type}`;
1232
+ });
1233
+ return entries.length > 0 ? `{ ${entries.join(", ")} }` : "{}";
1234
+ }
1235
+ function generateCodeModeInstructions(tools, toolName) {
1236
+ const calls = tools.map((t) => `- \`await api.${t.name}(${describeToolInput(t.inputSchema)})\` \u2014 ${t.description}`).join("\n");
1237
+ return [
1238
+ `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):`,
1239
+ calls,
1240
+ "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."
1241
+ ].join("\n\n");
1242
+ }
1226
1243
  function createCodeMode(config) {
1227
1244
  if (typeof config.onPermissionRequest !== "function") {
1228
1245
  throw new Error(
@@ -1235,16 +1252,22 @@ function createCodeMode(config) {
1235
1252
  "createCodeMode requires an injected `sandbox` with a run() method (a vetted isolation boundary \u2014 never node:vm)."
1236
1253
  );
1237
1254
  }
1255
+ if (config.tools.length === 0) {
1256
+ throw new Error(
1257
+ "createCodeMode requires a non-empty tools[] \u2014 the restricted API would be empty."
1258
+ );
1259
+ }
1238
1260
  const api = {};
1239
- for (const tool2 of config.tools) {
1240
- api[tool2.name] = async (args) => {
1241
- const decision = await config.onPermissionRequest({ tool: tool2.name, args });
1242
- if (!decision.granted) throw new CodeModePermissionDeniedError(tool2.name, decision.reason);
1243
- return tool2.handler(args);
1261
+ for (const tool3 of config.tools) {
1262
+ api[tool3.name] = async (args) => {
1263
+ const decision = await config.onPermissionRequest({ tool: tool3.name, args });
1264
+ if (!decision.granted) throw new CodeModePermissionDeniedError(tool3.name, decision.reason);
1265
+ return tool3.handler(args);
1244
1266
  };
1245
1267
  }
1246
- return {
1247
- name: config.name ?? "run_code",
1268
+ const name = config.name ?? "run_code";
1269
+ const tool2 = {
1270
+ name,
1248
1271
  description: config.description ?? "Run code that composes the available tools. Only the declared tools are callable.",
1249
1272
  inputSchema: {
1250
1273
  type: "object",
@@ -1257,6 +1280,7 @@ function createCodeMode(config) {
1257
1280
  return typeof result === "string" ? result : JSON.stringify(result);
1258
1281
  }
1259
1282
  };
1283
+ return { tool: tool2, instructions: generateCodeModeInstructions(config.tools, name) };
1260
1284
  }
1261
1285
 
1262
1286
  // src/server/agent/channel-webhook.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/openapi/serve-docs.ts","../../src/cache/constants.ts","../../src/cache/validation.ts","../../src/cache/define-cached-function.ts","../../src/cache/cache-control-header.ts","../../src/cache/key-derivation.ts","../../src/cache/define-cached-route.ts","../../src/cache/cache-engine.ts","../../src/cache/in-memory-adapter.ts","../../src/cache/engine-singleton.ts","../../src/cache/revalidate.ts","../../src/cache/route-rules.ts","../../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","../../src/server/serialization.ts","../../src/server/http/in-process-caller.ts","../../src/server/http/ctx-reconciliation.ts","../../src/server/index.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename -- paths derived from build-time cwd, not user input */\n/**\n * Built-in OpenAPI docs — serves Scalar UI at /api/docs and the JSON spec\n * at /api/docs/openapi.json. Zero npm deps (Scalar loaded via CDN).\n *\n * Absorbed from @theokit/plugin-openapi (theokit-plugins sibling repo).\n * Core already emits the spec via vite-plugin/openapi-emit/ — this module\n * adds the runtime serving layer.\n *\n * Security: XSS-safe HTML escaping, CSP header for CDN host, GET-only,\n * 10MB filesize cap, path-traversal defense on specFilePath.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport interface OpenApiDocsOptions {\n /** Path to serve Scalar UI (default: '/api/docs'). */\n docsPath?: string\n /** Path to serve the JSON spec (default: '/api/docs/openapi.json'). */\n openapiJsonPath?: string\n /** Path to the spec file on disk (default: '.theokit/openapi.json'). */\n specFilePath?: string\n /** Page title (default: 'API Reference'). */\n pageTitle?: string\n /** Scalar CDN URL (default: jsdelivr). Must be HTTPS. */\n cdnUrl?: string\n}\n\nconst MAX_SPEC_BYTES = 10 * 1024 * 1024 // 10MB cap (DoS defense)\nconst DEFAULT_CDN = 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'\n\n/**\n * Creates a request handler that serves OpenAPI docs.\n * Returns `null` for non-matching requests (passthrough).\n */\nexport function createOpenApiHandler(opts: OpenApiDocsOptions = {}) {\n const docsPath = opts.docsPath ?? '/api/docs'\n const jsonPath = opts.openapiJsonPath ?? '/api/docs/openapi.json'\n const rawSpecFile = opts.specFilePath ?? '.theokit/openapi.json'\n const title = opts.pageTitle ?? 'API Reference'\n const cdn = opts.cdnUrl ?? DEFAULT_CDN\n\n // Path-traversal defense — validate the RAW input, BEFORE resolve().\n // resolve() normalizes `..` away (e.g. '../../../etc/passwd' becomes an\n // absolute path with no '..' left), so checking the resolved string is a\n // dead guard. Reject any `..` path segment in the input instead; absolute\n // paths without traversal segments stay allowed.\n if (hasDotDotSegment(rawSpecFile)) {\n throw new Error(`[theokit:openapi] specFilePath must not contain \"..\" segments: ${rawSpecFile}`)\n }\n const specFile = resolve(rawSpecFile)\n\n return (request: Request): Response | null => {\n if (request.method !== 'GET') return null\n\n const url = new URL(request.url)\n\n if (url.pathname === docsPath) {\n const cdnHost = new URL(cdn).host\n return new Response(renderScalarHtml(title, jsonPath, cdn), {\n status: 200,\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n 'content-security-policy': `script-src 'self' 'unsafe-eval' ${cdnHost}; style-src 'self' 'unsafe-inline'; img-src 'self' data: ${cdnHost}; font-src 'self' data: ${cdnHost}; connect-src 'self' ${cdnHost}`,\n },\n })\n }\n\n if (url.pathname === jsonPath) {\n return serveSpecFile(specFile)\n }\n\n return null\n }\n}\n\n/** True if the raw path contains a `..` segment (POSIX `/` or Windows `\\` separator). */\nfunction hasDotDotSegment(p: string): boolean {\n return p.split(/[/\\\\]/).includes('..')\n}\n\n// ── HTML renderer ──\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction renderScalarHtml(title: string, specUrl: string, cdnUrl: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>${escapeHtml(title)}</title>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n</head>\n<body>\n <script id=\"api-reference\" data-url=\"${escapeHtml(specUrl)}\"></script>\n <script src=\"${escapeHtml(cdnUrl)}\"></script>\n</body>\n</html>`\n}\n\n// ── Spec file server ──\n\nfunction serveSpecFile(filePath: string): Response {\n if (!existsSync(filePath)) {\n return jsonResponse(503, {\n error: {\n code: 'OPENAPI_NOT_EMITTED',\n message: 'OpenAPI spec not generated yet. Start the dev server and visit a route first.',\n },\n })\n }\n\n try {\n const stat = statSync(filePath)\n if (stat.size > MAX_SPEC_BYTES) {\n return jsonResponse(413, {\n error: {\n code: 'OPENAPI_TOO_LARGE',\n message: `Spec file exceeds ${MAX_SPEC_BYTES / 1024 / 1024}MB limit`,\n },\n })\n }\n\n const content = readFileSync(filePath, 'utf-8')\n return new Response(content, {\n status: 200,\n headers: { 'content-type': 'application/json', 'cache-control': 'no-cache' },\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to read OpenAPI spec file'\n return jsonResponse(500, {\n error: { code: 'OPENAPI_READ_FAILED', message },\n })\n }\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n","/**\n * Single source of truth for cache subsystem constants.\n * Limits mirror Next.js (NEXT_CACHE_TAG_MAX_LENGTH / NEXT_CACHE_TAG_MAX_ITEMS)\n * — see reference doc §3.2 and ADR D6 of caching-and-revalidation-plan.md.\n */\n\nexport const CACHE_TAG_MAX_LENGTH = 256\nexport const CACHE_TAG_MAX_ITEMS = 128\nexport const THEO_T_PREFIX = '_THEO_T_'\n\nexport const DEFAULT_MAX_AGE = 1\nexport const DEFAULT_SWR_MULTIPLIER = 60\n","import {\n CACHE_TAG_MAX_ITEMS,\n CACHE_TAG_MAX_LENGTH,\n DEFAULT_MAX_AGE,\n THEO_T_PREFIX,\n} from './constants.js'\n\nexport interface ValidationResult<T> {\n valid: T[]\n dropped: { value: unknown; reason: string }[]\n}\n\n/**\n * Validate an array of cache tags.\n * Drops invalid entries (type / length / reserved-prefix / overflow) with warn log.\n * NEVER throws on runtime input — caller-facing safety.\n *\n * EC-1: defensive guard for non-array input (e.g., undefined from optional chain).\n */\nexport function validateTags(tags: unknown, description: string): ValidationResult<string> {\n // EC-1 guard\n if (!Array.isArray(tags)) {\n const result: ValidationResult<string> = {\n valid: [],\n dropped: [{ value: tags, reason: `expected array, got ${typeof tags}` }],\n }\n warnDropped(result, description)\n return result\n }\n\n // Array.isArray narrows to `any[]` (TS limitation). Re-type as unknown[]\n // so each element flows through explicit type guards below.\n const tagArr: unknown[] = tags as unknown[]\n const valid: string[] = []\n const dropped: { value: unknown; reason: string }[] = []\n\n for (let i = 0; i < tagArr.length; i++) {\n if (valid.length >= CACHE_TAG_MAX_ITEMS) {\n for (let j = i; j < tagArr.length; j++) {\n dropped.push({ value: tagArr[j], reason: 'overflow (max 128 tags)' })\n }\n break\n }\n const tag: unknown = tagArr[i]\n if (typeof tag !== 'string') {\n dropped.push({ value: tag, reason: 'invalid type, must be a string' })\n continue\n }\n if (tag.length > CACHE_TAG_MAX_LENGTH) {\n dropped.push({\n value: tag,\n reason: `exceeded max length of ${CACHE_TAG_MAX_LENGTH}`,\n })\n continue\n }\n if (tag.startsWith(THEO_T_PREFIX)) {\n dropped.push({\n value: tag,\n reason: `reserved prefix \"${THEO_T_PREFIX}\"`,\n })\n continue\n }\n valid.push(tag)\n }\n\n warnDropped({ valid, dropped }, description)\n return { valid, dropped }\n}\n\n/**\n * Validate a `maxAge` value in seconds.\n * Throws on invalid input (config-time validation).\n * Returns DEFAULT_MAX_AGE when undefined.\n */\nexport function validateMaxAge(maxAge: unknown, description: string): number {\n if (maxAge === undefined) return DEFAULT_MAX_AGE\n if (typeof maxAge === 'number' && Number.isFinite(maxAge) && maxAge >= 0) {\n return maxAge\n }\n throw new Error(\n `Invalid maxAge \"${JSON.stringify(maxAge)}\" in ${description}, must be a non-negative finite number`,\n )\n}\n\n/**\n * Validate an `expire` value in seconds, optionally cross-checked against `revalidate`.\n * Throws on invalid input (config-time validation).\n */\nexport function validateExpire(\n expire: unknown,\n revalidate: number | undefined,\n description: string,\n): number | undefined {\n if (expire === undefined) return undefined\n if (typeof expire !== 'number' || !Number.isFinite(expire) || expire < 0) {\n throw new Error(\n `Invalid expire \"${JSON.stringify(expire)}\" in ${description}, must be a non-negative finite number`,\n )\n }\n if (revalidate !== undefined && expire < revalidate) {\n throw new Error(\n `Invalid expire ${expire} in ${description}, must be greater than or equal to revalidate ${revalidate}`,\n )\n }\n return expire\n}\n\nfunction warnDropped(result: ValidationResult<string>, description: string): void {\n if (result.dropped.length === 0) return\n console.warn(`[theokit:cache] ${description}: dropped ${result.dropped.length} invalid tag(s):`)\n for (const { value, reason } of result.dropped) {\n console.warn(` - ${JSON.stringify(value)}: ${reason}`)\n }\n}\n","import type { CacheEngine } from './cache-engine.js'\nimport { validateExpire, validateMaxAge, validateTags } from './validation.js'\n\nexport interface DefineCachedFunctionOptions<TArgs extends unknown[], TReturn> {\n /** Required cache namespace; appears in keys as \"fn:${name}:...\" */\n name: string\n /** seconds; defaults to DEFAULT_MAX_AGE (1) */\n maxAge?: number\n /** seconds; stale-while-revalidate window */\n swr?: number\n /** Custom key derivation from args. Default: JSON.stringify(args). */\n getKey?: (...args: TArgs) => string\n /** Static or dynamic tags. */\n tags?: string[] | ((...args: TArgs) => string[])\n /** Version stamp; bump to invalidate all entries under this name. */\n cacheVersion?: string\n /** Transform returned value before caching. */\n transform?: (raw: TReturn) => TReturn\n /** Skip cache if validate returns false (treats existing entry as miss). */\n validate?: (raw: TReturn) => boolean\n /** Called on any error in the cache pipeline. */\n onError?: (err: unknown, ctx: { args: TArgs }) => void\n}\n\nexport type CachedFunction<TArgs extends unknown[], TReturn> = ((\n ...args: TArgs\n) => Promise<TReturn>) & {\n /** Bust the cache entry for these specific args. */\n invalidate: (...args: TArgs) => Promise<void>\n}\n\n/**\n * Wrap an async function with cache semantics.\n * Returns a callable that memoizes by `(name + args)` and exposes `.invalidate(args)`.\n *\n * The engine is supplied by the caller (avoids module-level singleton coupling\n * during testing; framework wiring provides it in production).\n */\nexport function defineCachedFunction<TArgs extends unknown[], TReturn>(\n engine: CacheEngine,\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n opts: DefineCachedFunctionOptions<TArgs, TReturn>,\n): CachedFunction<TArgs, TReturn> {\n if (typeof opts.name !== 'string' || opts.name.length === 0) {\n throw new Error('defineCachedFunction: opts.name is required (non-empty string)')\n }\n const maxAge = validateMaxAge(opts.maxAge, `defineCachedFunction(${opts.name})`)\n const swr = validateExpire(opts.swr, maxAge, `defineCachedFunction(${opts.name})`)\n\n const prefix = `fn:${opts.name}`\n\n function deriveCacheKey(args: TArgs): string {\n const tail = opts.getKey ? opts.getKey(...args) : JSON.stringify(args)\n return `${prefix}:${tail}`\n }\n\n function resolveTags(args: TArgs): string[] {\n const raw = typeof opts.tags === 'function' ? opts.tags(...args) : (opts.tags ?? [])\n const { valid } = validateTags(raw, `defineCachedFunction(${opts.name})`)\n return valid\n }\n\n const wrapped = (async (...args: TArgs) => {\n const key = deriveCacheKey(args)\n const tags = resolveTags(args)\n try {\n const { value } = await engine.getOrCompute<TReturn>(key, async () => fn(...args), {\n maxAge,\n swr: swr ?? maxAge * 60,\n tags,\n cacheVersion: opts.cacheVersion,\n transform: opts.transform,\n validate: opts.validate,\n })\n return value\n } catch (err) {\n opts.onError?.(err, { args })\n throw err\n }\n }) as CachedFunction<TArgs, TReturn>\n\n wrapped.invalidate = async (...args: TArgs) => {\n const key = deriveCacheKey(args)\n await engine.invalidate(key)\n }\n\n return wrapped\n}\n","export interface CacheControlInput {\n /** seconds; 0 forces no-cache */\n maxAge: number\n /** stale-while-revalidate window in seconds; 0 or undefined omits directive */\n swr?: number\n /** emit `private,` prefix (skips shared CDN caching) */\n isPrivate?: boolean\n}\n\nconst NO_CACHE_HEADER = 'private, no-cache, no-store, max-age=0, must-revalidate'\n\n/**\n * Build a canonical Cache-Control header value.\n *\n * `maxAge === 0` always yields the strict no-cache directive regardless\n * of `swr` or `isPrivate` — defensive default.\n *\n * EC-13: pure function intentional — caller is responsible for input\n * validation (see validateMaxAge / validateExpire in validation.ts).\n */\nexport function getCacheControlHeader(input: CacheControlInput): string {\n if (input.maxAge === 0) return NO_CACHE_HEADER\n const parts: string[] = []\n if (input.isPrivate) parts.push('private')\n parts.push(`s-maxage=${input.maxAge}`)\n if (input.swr !== undefined && input.swr > 0) {\n parts.push(`stale-while-revalidate=${input.swr}`)\n }\n return parts.join(', ')\n}\n","/**\n * Default tracking/analytics query parameters excluded from cache keys.\n * Mirrors Astro's DEFAULT_EXCLUDED_PARAMS list (memory-provider.ts:117).\n * Set as exact-match (not glob) for KISS + zero-dep.\n */\nexport const DEFAULT_EXCLUDED_QUERY_PARAMS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'dclid',\n 'msclkid',\n 'twclid',\n 'li_fat_id',\n 'mc_cid',\n 'mc_eid',\n '_ga',\n '_gl',\n '_hsenc',\n '_hsmi',\n '_ke',\n 'oly_anon_id',\n 'oly_enc_id',\n 'rb_clickid',\n 's_cid',\n 'vero_id',\n 'wickedid',\n 'yclid',\n '__s',\n 'ref',\n]\n\nexport interface KeyDerivationOptions {\n /** Total override — when provided, bypasses all internal logic. */\n getKey?: (req: Request) => string | Promise<string>\n /** Exact-match query param names to drop. Defaults to DEFAULT_EXCLUDED_QUERY_PARAMS. */\n excludeQuery?: string[]\n /** Whether to sort query params alphabetically. Defaults to true. */\n sortQuery?: boolean\n /** Header names whose values are appended as `\\0name=value` suffix. */\n varies?: string[]\n /** Namespace prefix (e.g., route name). */\n prefix?: string\n}\n\n/**\n * Derive a deterministic cache key from a Request.\n *\n * Default behaviour: `${prefix?}${protocol}//${lower(host)}${path}${?sortedFilteredQuery}` + Vary suffix.\n * `\\0` separator chosen because it cannot appear in URLs or HTTP header values.\n *\n * EC-6: malformed URL on getKey path is caller's responsibility.\n * EC-7: enforces getKey returns string.\n */\nexport async function deriveKey(req: Request, opts: KeyDerivationOptions = {}): Promise<string> {\n if (opts.getKey) {\n const k = await opts.getKey(req)\n if (typeof k !== 'string') {\n throw new Error(`getKey must return a string, got ${typeof k}`)\n }\n return k\n }\n\n const url = new URL(req.url)\n const queryString = buildQueryString(url, opts)\n const base = `${opts.prefix ? opts.prefix + ':' : ''}${url.protocol}//${url.hostname.toLowerCase()}${url.pathname}${queryString ? '?' + queryString : ''}`\n\n if (!opts.varies || opts.varies.length === 0) return base\n const parts: string[] = []\n for (const header of opts.varies) {\n parts.push(`${header}=${req.headers.get(header) ?? ''}`)\n }\n return base + '\\0' + parts.join('\\0')\n}\n\nfunction buildQueryString(url: URL, opts: KeyDerivationOptions): string {\n const params = new URLSearchParams(url.searchParams)\n const exclude = opts.excludeQuery ?? DEFAULT_EXCLUDED_QUERY_PARAMS\n const excludeSet = new Set(exclude)\n for (const key of [...params.keys()]) {\n if (excludeSet.has(key)) params.delete(key)\n }\n if (opts.sortQuery !== false) params.sort()\n return params.toString()\n}\n","import type { z } from 'zod'\n\nimport type { RouteConfig } from '../core/contracts/route-config.js'\n\nimport { getCacheControlHeader } from './cache-control-header.js'\nimport type { CacheEngine, CacheStatus } from './cache-engine.js'\nimport { THEO_T_PREFIX } from './constants.js'\nimport { deriveKey } from './key-derivation.js'\nimport type { CacheEntry } from './storage-adapter.js'\nimport { validateExpire, validateMaxAge, validateTags } from './validation.js'\n\n/** Default 10 MB cap per cached route entry (EC-3). */\nexport const DEFAULT_MAX_ENTRY_SIZE = 10 * 1024 * 1024\nconst VARIES_IGNORED = new Set(['cookie', 'set-cookie'])\n\nexport interface RouteCacheOptions {\n maxAge?: number\n swr?: number\n tags?: string[]\n varies?: string[]\n getKey?: (req: Request) => string | Promise<string>\n bypassWhen?: (req: Request) => boolean | Promise<boolean>\n cacheVersion?: string\n cacheErrors?: boolean\n methods?: string[]\n cacheable?: (response: Response) => boolean\n /** Max body bytes (EC-3); default DEFAULT_MAX_ENTRY_SIZE. */\n maxEntrySize?: number\n}\n\nexport interface CachedRouteConfig<\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> extends Omit<RouteConfig<TQuery, TBody, TParams, TCtx>, 'handler'> {\n cache: RouteCacheOptions\n handler: (ctx: {\n query: z.infer<TQuery>\n body: z.infer<TBody>\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n }) => unknown\n}\n\ninterface RouteCacheValue {\n body: string\n status: number\n headers: [string, string][]\n}\n\nconst setCookieWarnedRoutes = new WeakSet()\nconst variesCookieWarnedRoutes = new WeakSet()\nconst oversizedWarnedRoutes = new WeakSet()\n\n/**\n * Wrap a `RouteConfig` with cache-aware handler logic.\n *\n * Architecture: wraps the user `handler` so cache lookup happens AT\n * handler-invocation time, AFTER router middleware (auth/csrf/etc) ran.\n * This structurally satisfies EC-4 (cache-after-auth) without modifying\n * the router internals.\n *\n * Algorithm per request:\n * 1. Method check + bypassWhen + maxAge=0 → call handler raw\n * 2. Derive key (path + sortedQuery + varies, prefix by method)\n * 3. Cache lookup → HIT/STALE return cached Response\n * 4. Miss → run handler, check cacheability (Set-Cookie / status / size / SSE / streaming)\n * 5. Cacheable → write entry + return Response with X-Theo-Cache: MISS (dev)\n * 6. Not cacheable → return original Response unchanged\n *\n * Concurrent dedupe is INTENTIONALLY NOT used for routes — Response objects\n * cannot be safely shared across concurrent callers (body is single-use stream).\n * Each request that misses runs the handler independently.\n */\nexport function defineCachedRoute<\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>(\n engine: CacheEngine,\n config: CachedRouteConfig<TQuery, TBody, TParams, TCtx>,\n): RouteConfig<TQuery, TBody, TParams, TCtx, Response> {\n const { cache, handler, ...rest } = config\n\n const maxAge = validateMaxAge(cache.maxAge, 'defineCachedRoute')\n const swr = validateExpire(cache.swr, maxAge, 'defineCachedRoute')\n if (cache.cacheVersion !== undefined && cache.cacheVersion === '') {\n throw new Error('defineCachedRoute: cacheVersion must be non-empty if provided')\n }\n // EC-19: maxEntrySize validation\n const maxEntrySize = cache.maxEntrySize ?? DEFAULT_MAX_ENTRY_SIZE\n if (!Number.isFinite(maxEntrySize) || maxEntrySize < 0) {\n throw new Error(\n `Invalid maxEntrySize \"${String(cache.maxEntrySize)}\" in defineCachedRoute, must be a non-negative finite number`,\n )\n }\n const methods = new Set((cache.methods ?? ['GET', 'HEAD']).map((m) => m.toUpperCase()))\n const baseTags = validateTags(cache.tags ?? [], 'defineCachedRoute').valid\n\n // EC-2: filter cookie/set-cookie from varies + warn-once per route\n const variesRaw = cache.varies ?? []\n const variesLower = variesRaw.map((v) => v.toLowerCase())\n const hadCookieVary = variesLower.some((v) => VARIES_IGNORED.has(v))\n const safeVaries = variesLower.filter((v) => !VARIES_IGNORED.has(v))\n if (hadCookieVary && !variesCookieWarnedRoutes.has(config)) {\n variesCookieWarnedRoutes.add(config)\n console.warn(\n `[theokit:cache] defineCachedRoute: 'cookie'/'set-cookie' removed from varies — they fragment cache to zero hit rate (EC-2)`,\n )\n }\n\n const wrappedHandler = async (ctx: {\n query: z.infer<TQuery>\n body: z.infer<TBody>\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n }): Promise<Response> => {\n // TheoKit's dispatcher may pass a Node IncomingMessage (not a Web Request).\n // Normalize to a Web Request so deriveKey / bypassWhen / URL parsing work uniformly.\n const webRequest = toWebRequest(ctx.request)\n\n if (!methods.has(webRequest.method.toUpperCase())) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n if (cache.bypassWhen && (await cache.bypassWhen(webRequest))) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n if (maxAge === 0) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n\n const key = await deriveKey(webRequest, {\n prefix: 'route:' + webRequest.method.toUpperCase(),\n varies: safeVaries,\n getKey: cache.getKey,\n })\n\n // ---- Cache lookup (T4.2 DRY — delegates to engine canonical) ----\n const cached = await engine.tryReadCached<RouteCacheValue>(key, {\n cacheVersion: cache.cacheVersion,\n })\n\n // T4.3 — build options bag once; pass to all helpers (≤ 4 params each).\n const routeCacheCtx: RouteCacheCtx = {\n engine,\n key,\n cache,\n routeConfig: config,\n maxEntrySize,\n maxAge,\n swr,\n baseTags,\n webRequest,\n }\n\n if (cached) {\n if (cached.status === 'hit') {\n return buildResponseFromCache(cached.value, 'hit', maxAge, swr)\n }\n // Only 'stale' remains (engine never returns 'miss' from tryReadCached).\n // Stale: schedule background refresh + return stale immediately.\n scheduleRouteRevalidate(routeCacheCtx, handler, ctx)\n return buildResponseFromCache(cached.value, 'stale', maxAge, swr)\n }\n\n // ---- Miss: run handler ----\n const response = await invokeHandlerAsResponse(handler, ctx)\n return persistAndReturn(routeCacheCtx, response)\n }\n\n return {\n ...rest,\n handler: wrappedHandler,\n }\n}\n\n// T4.2 (PV-5 DRY): tryReadCacheEntry was removed — duplicated the engine's\n// canonical tryReadCached (staleness check, version check, JSON parse,\n// clock-skew clamp). Route wrapper now delegates to `engine.tryReadCached`.\n\n/**\n * T4.3 options-bag context (PV-6 — Clean Code consensus ≤ 4 params).\n * Collapses 10/11 positional params of `persistAndReturn` and\n * `scheduleRouteRevalidate` to 2 params each (ctx + payload).\n *\n * Some fields are derived from `cache` config (EC-22 documented redundancy) —\n * the trade-off is O(1) construction per request for vastly simpler call\n * sites and safer additions of new fields without reordering args.\n */\ninterface RouteCacheCtx {\n engine: CacheEngine\n key: string\n cache: RouteCacheOptions\n routeConfig: object\n maxEntrySize: number\n maxAge: number\n swr: number | undefined\n baseTags: string[]\n webRequest: Request\n}\n\nfunction buildRouteCacheEntry(value: RouteCacheValue, ctx: RouteCacheCtx): CacheEntry {\n const pathTag = THEO_T_PREFIX + new URL(ctx.webRequest.url).pathname\n return {\n body: JSON.stringify(value),\n status: 200,\n headers: [],\n storedAt: Date.now(),\n maxAge: ctx.maxAge,\n swr: ctx.swr ?? ctx.maxAge * 60,\n tags: [...ctx.baseTags, pathTag],\n cacheVersion: ctx.cache.cacheVersion,\n }\n}\n\nasync function persistAndReturn(ctx: RouteCacheCtx, response: Response): Promise<Response> {\n const cacheableResult = await tryCacheResponse(\n response,\n ctx.cache,\n ctx.routeConfig,\n ctx.maxEntrySize,\n )\n if (!cacheableResult) {\n // Not cached — return original response unchanged\n return response\n }\n await ctx.engine.set(ctx.key, buildRouteCacheEntry(cacheableResult, ctx))\n return buildResponseFromCache(cacheableResult, 'miss', ctx.maxAge, ctx.swr)\n}\n\nfunction scheduleRouteRevalidate<THandlerCtx>(\n ctx: RouteCacheCtx,\n handler: (handlerCtx: THandlerCtx) => unknown,\n handlerCtx: THandlerCtx,\n): void {\n void (async () => {\n try {\n const response = await invokeHandlerAsResponse(handler, handlerCtx)\n const result = await tryCacheResponse(response, ctx.cache, ctx.routeConfig, ctx.maxEntrySize)\n if (!result) return\n await ctx.engine.set(ctx.key, buildRouteCacheEntry(result, ctx))\n } catch {\n // Stale entry remains; future request retries on its own stale-check\n }\n })()\n}\n\n/**\n * Type for Node.js IncomingMessage (subset we read).\n * Avoids a direct `node:http` import which would block edge runtimes.\n */\ninterface NodeLikeRequest {\n url?: string\n method?: string\n headers: Record<string, string | string[] | undefined>\n socket?: { encrypted?: boolean }\n}\n\n/**\n * Adapt either a Web Request or a Node IncomingMessage to a Web Request.\n * TheoKit's runtime dispatch may pass either depending on the adapter.\n */\n\n// Node IncomingMessage) inside one function so the call sites stay shape-blind.\nfunction toWebRequest(req: Request | NodeLikeRequest): Request {\n // Web Request fast-path\n if (typeof (req as Request).clone === 'function' && (req as Request).headers instanceof Headers) {\n return req as Request\n }\n const node = req as NodeLikeRequest\n const host = (typeof node.headers.host === 'string' ? node.headers.host : null) ?? 'localhost'\n const protocol = node.socket?.encrypted ? 'https' : 'http'\n const path = node.url ?? '/'\n const url = path.startsWith('http') ? path : `${protocol}://${host}${path}`\n const headers = new Headers()\n for (const [k, v] of Object.entries(node.headers)) {\n if (Array.isArray(v)) {\n for (const item of v) headers.append(k, item)\n } else if (typeof v === 'string') {\n headers.set(k, v)\n }\n }\n return new Request(url, {\n method: (node.method ?? 'GET').toUpperCase(),\n headers,\n })\n}\n\nasync function invokeHandlerAsResponse<TCtx>(\n handler: (ctx: TCtx) => unknown,\n ctx: TCtx,\n): Promise<Response> {\n const raw = await handler(ctx)\n if (raw instanceof Response) return raw\n return Response.json(raw)\n}\n\n/**\n * Decide whether `response` is cacheable. Returns serialized form on yes; undefined on no.\n * Order matters: cheap checks first, body read last (only for cacheable candidates).\n */\nasync function tryCacheResponse(\n response: Response,\n cache: RouteCacheOptions,\n routeConfig: object,\n maxEntrySize: number,\n): Promise<RouteCacheValue | undefined> {\n // D7 / EC-2: Set-Cookie auto-bypass\n if (response.headers.has('set-cookie')) {\n if (!setCookieWarnedRoutes.has(routeConfig)) {\n setCookieWarnedRoutes.add(routeConfig)\n console.warn('[theokit:cache] response has Set-Cookie — skipping cache write (D7)')\n }\n return undefined\n }\n // SSE\n const contentType = response.headers.get('content-type') ?? ''\n if (contentType.includes('text/event-stream')) return undefined\n // EC-11: chunked streaming (transfer-encoding: chunked OR no content-length on a\n // user-constructed Response — i.e., a Response built from a ReadableStream that\n // wasn't via Response.json/text helpers). We detect via the explicit\n // transfer-encoding header since Response.json() also uses a ReadableStream\n // body internally and we don't want to refuse those.\n if (response.headers.get('transfer-encoding')?.toLowerCase() === 'chunked') {\n return undefined\n }\n // D9: status >= 400 not cached unless opt-in\n if (response.status >= 400 && !cache.cacheErrors) return undefined\n // Custom predicate (overrides built-ins)\n if (cache.cacheable && !cache.cacheable(response)) return undefined\n\n // Read body (clone to preserve the response for downstream)\n const text = await response.clone().text()\n\n // EC-3: oversized bypass\n if (text.length > maxEntrySize) {\n if (!oversizedWarnedRoutes.has(routeConfig)) {\n oversizedWarnedRoutes.add(routeConfig)\n console.warn(\n `[theokit:cache] response body ${text.length} bytes exceeds maxEntrySize ${maxEntrySize}; skipping cache (EC-3)`,\n )\n }\n return undefined\n }\n\n const headers: [string, string][] = []\n response.headers.forEach((v, k) => {\n if (k.toLowerCase() === 'set-cookie') return // defense-in-depth\n headers.push([k, v])\n })\n return { body: text, status: response.status, headers }\n}\n\nfunction buildResponseFromCache(\n value: RouteCacheValue,\n status: CacheStatus,\n maxAge: number,\n swr: number | undefined,\n): Response {\n const headers = new Headers(value.headers)\n if (!headers.has('cache-control')) {\n headers.set('cache-control', getCacheControlHeader({ maxAge, swr: swr ?? maxAge * 60 }))\n }\n if (process.env.NODE_ENV !== 'production') {\n let cacheStatusHeader: 'HIT' | 'STALE' | 'MISS' = 'MISS'\n if (status === 'hit') cacheStatusHeader = 'HIT'\n else if (status === 'stale') cacheStatusHeader = 'STALE'\n headers.set('X-Theo-Cache', cacheStatusHeader)\n }\n return new Response(value.body, { status: value.status, headers })\n}\n","import { THEO_T_PREFIX } from './constants.js'\nimport type { CacheEntry, CacheStorageAdapter } from './storage-adapter.js'\n\nexport type CacheStatus = 'hit' | 'stale' | 'miss'\n\nexport interface CacheEngineOptions {\n storage: CacheStorageAdapter\n defaults?: {\n maxAge?: number\n swr?: number\n cacheVersion?: string\n }\n onError?: (err: unknown, ctx: { phase: 'get' | 'set' | 'revalidate'; key: string }) => void\n}\n\nexport interface GetOrComputeOptions<T> {\n maxAge: number\n swr?: number\n tags?: string[]\n cacheVersion?: string\n transform?: (raw: T) => T\n validate?: (raw: T) => boolean\n /**\n * When `true`, the value is returned but NOT written to cache.\n * Used by route middleware to bypass cache for uncacheable responses\n * (Set-Cookie, oversized body, status >= 400 with cacheErrors=false).\n */\n skipCacheWhen?: (raw: T) => boolean\n}\n\nexport interface CacheEngine {\n getOrCompute<T>(\n key: string,\n fn: () => Promise<T>,\n opts: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus }>\n\n /**\n * Public canonical cache read (T4.2 of architecture-review-remediation-plan,\n * PV-5 DRY consolidation). Returns the parsed value + status (`hit` | `stale`)\n * for callers that DON'T want to bind a loader function (e.g., HTTP route\n * middleware that may want to bypass on miss instead of running a loader).\n *\n * Returns undefined when:\n * - Entry not present in storage\n * - `opts.cacheVersion` mismatch with entry\n * - Body is not a JSON string (parse failed)\n * - `opts.validate` returns false (or throws — caller's onError invoked)\n * - Entry is fully expired (past maxAge + swr)\n */\n tryReadCached<T>(\n key: string,\n opts: { cacheVersion?: string; validate?: (v: T) => boolean },\n ): Promise<{ value: T; status: 'hit' | 'stale' } | undefined>\n\n set(key: string, entry: CacheEntry): Promise<void>\n invalidate(key: string): Promise<boolean>\n invalidateTag(tag: string): Promise<number>\n revalidatePath(path: string, type?: 'layout' | 'page'): Promise<number>\n\n /** Storage adapter passthrough (read-only access for diagnostics). */\n readonly storage: CacheStorageAdapter\n}\n\n/**\n * Build a cache engine wrapping a storage adapter.\n *\n * Implements:\n * - SWR (fresh / stale / expired branching) — Astro `memory-provider.ts:423`-style.\n * - In-flight dedupe via `Map<key, Promise>` — Next.js `pendingRevalidates` pattern.\n * - Tag-based invalidation via adapter's deleteByTag.\n * - Path-as-tag encoding (revalidatePath sugar) — Next.js `revalidate.ts:105`.\n *\n * EC-8: Math.max(0, age) guards clock skew.\n * EC-9: validate callback wrapped in try/catch.\n * EC-10: loader returning undefined skips cache write + warns once.\n *\n * NOTE on max-lines-per-function disable below: createCacheEngine is a factory\n * closure that owns the in-flight/bg/warned maps. Splitting would force the\n * helpers across modules and re-introduce the shared mutable state through\n * parameter lists.\n */\n// eslint-disable-next-line max-lines-per-function\nexport function createCacheEngine(opts: CacheEngineOptions): CacheEngine {\n const { storage, onError } = opts\n const inFlight = new Map<string, Promise<unknown>>()\n const bgInFlight = new Set<string>()\n const undefinedLoaderWarned = new Set<string>()\n\n async function getOrCompute<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus }> {\n // Dedupe: concurrent first-miss shares the loader promise\n const pending = inFlight.get(key)\n if (pending) {\n const value = (await pending) as T\n return { value, status: 'miss' }\n }\n\n // maxAge=0 → always miss, never cache\n if (options.maxAge === 0) {\n return claimAndRun(key, fn, options, /* skipWrite */ true)\n }\n\n // Atomically claim the in-flight slot BEFORE any await (dedupe race fix).\n return claimAndRun(key, fn, options, false)\n }\n\n /**\n * Claims the in-flight slot synchronously, then performs the get/loader work\n * inside. Concurrent callers awaiting the same key share this slot.\n */\n function claimAndRun<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n skipWrite: boolean,\n ): Promise<{ value: T; status: CacheStatus }> {\n let resolveOuter!: (v: T) => void\n let rejectOuter!: (e: unknown) => void\n const outerPromise = new Promise<T>((resolve, reject) => {\n resolveOuter = resolve\n rejectOuter = reject\n })\n // Prevent unhandled-rejection when no concurrent awaiter exists\n void outerPromise.catch(() => {\n /* swallow — the leader handles via work promise */\n })\n inFlight.set(key, outerPromise)\n\n const work = (async (): Promise<{ value: T; status: CacheStatus }> => {\n try {\n if (!skipWrite) {\n const cached = await tryReadCached<T>(key, options)\n if (cached) {\n // HIT or STALE — value already resolved\n resolveOuter(cached.value)\n if (cached.status === 'stale') {\n scheduleBackgroundRevalidate(key, fn, options)\n }\n return cached\n }\n }\n // Miss path: run loader\n const value = await runLoader(key, fn, options, skipWrite)\n resolveOuter(value)\n return { value, status: 'miss' as const }\n } catch (err) {\n rejectOuter(err)\n throw err\n } finally {\n inFlight.delete(key)\n }\n })()\n\n return work\n }\n\n // One inline staleness machine; each guard (version check, parse, validate,\n // age, swr window) is one short branch. Extracting per-step would dilute,\n // not clarify.\n // eslint-disable-next-line complexity\n async function tryReadCached<T>(\n key: string,\n options: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus } | undefined> {\n let entry: CacheEntry | undefined\n try {\n entry = await storage.get(key)\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n if (!entry) return undefined\n if (options.cacheVersion !== undefined && entry.cacheVersion !== options.cacheVersion) {\n return undefined\n }\n if (typeof entry.body !== 'string') return undefined\n let parsed: T\n try {\n parsed = JSON.parse(entry.body) as T\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n // EC-9: validate wrapped in try/catch\n if (options.validate) {\n try {\n if (!options.validate(parsed)) return undefined\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n }\n // EC-8: clamp age to non-negative (clock skew)\n const age = Math.max(0, (Date.now() - entry.storedAt) / 1000)\n if (age <= entry.maxAge) {\n const value = options.transform ? options.transform(parsed) : parsed\n return { value, status: 'hit' }\n }\n if (age <= entry.maxAge + entry.swr) {\n const value = options.transform ? options.transform(parsed) : parsed\n return { value, status: 'stale' }\n }\n return undefined\n }\n\n // runLoader always returns `value` by design: loader output is the caller's\n // contract; every branch short-circuits a *write*, never the return path.\n // eslint-disable-next-line sonarjs/no-invariant-returns, complexity\n async function runLoader<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n skipWrite = false,\n ): Promise<T> {\n const raw = await fn()\n const value = options.transform ? options.transform(raw) : raw\n\n if (skipWrite) return value\n\n // skipCacheWhen sentinel — caller-controlled skip-write\n if (options.skipCacheWhen?.(value)) return value\n\n // EC-9: validate during write\n if (options.validate) {\n let isValid = true\n try {\n isValid = options.validate(value)\n } catch (err) {\n onError?.(err, { phase: 'set', key })\n return value\n }\n if (!isValid) return value\n }\n\n // EC-10: undefined return → warn-once + skip cache\n if (value === undefined) {\n if (!undefinedLoaderWarned.has(key)) {\n undefinedLoaderWarned.add(key)\n console.warn(`[theokit:cache] loader returned undefined for key \"${key}\"; entry not cached`)\n }\n return value\n }\n\n try {\n const entry: CacheEntry = {\n body: JSON.stringify(value),\n status: 200,\n headers: [],\n storedAt: Date.now(),\n maxAge: options.maxAge,\n swr: options.swr ?? 0,\n tags: options.tags ?? [],\n cacheVersion: options.cacheVersion,\n }\n await storage.set(key, entry)\n } catch (err) {\n onError?.(err, { phase: 'set', key })\n }\n return value\n }\n\n function scheduleBackgroundRevalidate<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n ): void {\n if (bgInFlight.has(key)) return\n bgInFlight.add(key)\n void runLoader(key, fn, options)\n .catch((err: unknown) => {\n onError?.(err, { phase: 'revalidate', key })\n })\n .finally(() => {\n bgInFlight.delete(key)\n })\n }\n\n return {\n storage,\n\n getOrCompute,\n\n async tryReadCached<T>(\n key: string,\n opts: { cacheVersion?: string; validate?: (v: T) => boolean },\n ): Promise<{ value: T; status: 'hit' | 'stale' } | undefined> {\n // Delegate to internal impl (which uses the broader GetOrComputeOptions\n // type). tryReadCached never returns status: 'miss' — that codepath\n // returns undefined. Narrow the type via assertion.\n const result = await tryReadCached<T>(key, {\n ...opts,\n maxAge: 0, // unused by tryReadCached\n })\n if (!result) return undefined\n return result as { value: T; status: 'hit' | 'stale' }\n },\n\n async set(key, entry) {\n await storage.set(key, entry)\n },\n\n async invalidate(key) {\n // Best-effort: clear in-flight too so next request starts fresh\n inFlight.delete(key)\n return storage.delete(key)\n },\n\n async invalidateTag(tag) {\n return storage.deleteByTag(tag)\n },\n\n async revalidatePath(path, type) {\n const tag = THEO_T_PREFIX + path + (type ? '/' + type : '')\n return storage.deleteByTag(tag)\n },\n }\n}\n","import type { CacheEntry, CacheStorageAdapter } from './storage-adapter.js'\n\nexport interface InMemoryCacheAdapterOptions {\n /** Maximum number of entries before LRU eviction. Default 1000. */\n maxEntries?: number\n}\n\n/**\n * In-memory cache adapter with LRU eviction + reverse tag index.\n *\n * Uses Map insertion-order for O(1) LRU (Astro LRUMap pattern).\n * Reverse index `tagIndex: Map<tag, Set<key>>` makes deleteByTag O(matched-keys).\n *\n * Invariants:\n * - `entries.size <= maxEntries` post-set.\n * - `tagIndex[tag].has(key)` ↔ `entries.get(key)?.tags.includes(tag)`.\n *\n * eslint-disable @typescript-eslint/require-await — the CacheStorageAdapter\n * interface is intentionally async so Redis/file/external adapters fit. The\n * in-memory variant returns immediately but keeps the async signature to\n * satisfy the contract.\n */\n/* eslint-disable @typescript-eslint/require-await */\nexport class InMemoryCacheAdapter implements CacheStorageAdapter {\n readonly name = 'memory'\n readonly #entries = new Map<string, CacheEntry>()\n readonly #tagIndex = new Map<string, Set<string>>()\n readonly #maxEntries: number\n\n constructor(opts: InMemoryCacheAdapterOptions = {}) {\n this.#maxEntries = opts.maxEntries ?? 1000\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = this.#entries.get(key)\n if (entry === undefined) return undefined\n // LRU bump\n this.#entries.delete(key)\n this.#entries.set(key, entry)\n return entry\n }\n\n async set(key: string, entry: CacheEntry): Promise<void> {\n // Overwrite case: clean old tags first\n const existing = this.#entries.get(key)\n if (existing) {\n this.#removeKeyFromTagIndex(key, existing.tags)\n this.#entries.delete(key)\n } else if (this.#entries.size >= this.#maxEntries) {\n // LRU eviction\n const oldestIter = this.#entries.keys().next()\n if (!oldestIter.done) {\n const oldestKey = oldestIter.value\n const oldestEntry = this.#entries.get(oldestKey)\n if (oldestEntry) {\n this.#removeKeyFromTagIndex(oldestKey, oldestEntry.tags)\n }\n this.#entries.delete(oldestKey)\n }\n }\n this.#entries.set(key, entry)\n for (const tag of entry.tags) {\n let bucket = this.#tagIndex.get(tag)\n if (!bucket) {\n bucket = new Set()\n this.#tagIndex.set(tag, bucket)\n }\n bucket.add(key)\n }\n }\n\n async delete(key: string): Promise<boolean> {\n const entry = this.#entries.get(key)\n if (!entry) return false\n this.#removeKeyFromTagIndex(key, entry.tags)\n this.#entries.delete(key)\n return true\n }\n\n async deleteByTag(tag: string): Promise<number> {\n const bucket = this.#tagIndex.get(tag)\n if (!bucket || bucket.size === 0) return 0\n const keys = [...bucket]\n for (const key of keys) {\n const entry = this.#entries.get(key)\n if (entry) {\n this.#unindexFromOtherTags(key, entry.tags, tag)\n }\n this.#entries.delete(key)\n }\n this.#tagIndex.delete(tag)\n return keys.length\n }\n\n async size(): Promise<number> {\n return this.#entries.size\n }\n\n async clear(): Promise<void> {\n this.#entries.clear()\n this.#tagIndex.clear()\n }\n\n async *keys(prefix?: string): AsyncIterableIterator<string> {\n for (const key of this.#entries.keys()) {\n if (prefix && !key.startsWith(prefix)) continue\n yield key\n }\n }\n\n #removeKeyFromTagIndex(key: string, tags: string[]): void {\n for (const tag of tags) {\n const bucket = this.#tagIndex.get(tag)\n if (!bucket) continue\n bucket.delete(key)\n if (bucket.size === 0) this.#tagIndex.delete(tag)\n }\n }\n\n #unindexFromOtherTags(key: string, tags: string[], skipTag: string): void {\n for (const otherTag of tags) {\n if (otherTag === skipTag) continue\n const otherBucket = this.#tagIndex.get(otherTag)\n if (!otherBucket) continue\n otherBucket.delete(key)\n if (otherBucket.size === 0) this.#tagIndex.delete(otherTag)\n }\n }\n}\n","import type { CacheEngine, CacheEngineOptions } from './cache-engine.js'\nimport { createCacheEngine } from './cache-engine.js'\nimport { InMemoryCacheAdapter } from './in-memory-adapter.js'\nimport type { CacheStorageAdapter } from './storage-adapter.js'\n\nexport interface NormalizedCacheConfig {\n enabled: boolean\n storage: 'memory' | CacheStorageAdapter\n maxEntries: number\n defaults: {\n maxAge: number\n swr?: number\n cacheErrors: boolean\n }\n}\n\nlet _engine: CacheEngine | undefined\n\n/**\n * Initialize the singleton cache engine for this process.\n * Throws if called twice; tests should call `_resetCacheEngine()` between.\n */\nexport function initCacheEngine(\n config: NormalizedCacheConfig,\n hooks: Pick<CacheEngineOptions, 'onError'> = {},\n): CacheEngine {\n if (_engine) {\n throw new Error(\n 'Cache engine already initialized — call _resetCacheEngine() in tests, or check init order in production.',\n )\n }\n if (!config.enabled) {\n throw new Error(\n 'initCacheEngine: config.enabled is false. Skip this call entirely when cache is disabled.',\n )\n }\n const adapter =\n config.storage === 'memory'\n ? new InMemoryCacheAdapter({ maxEntries: config.maxEntries })\n : config.storage\n _engine = createCacheEngine({\n storage: adapter,\n defaults: config.defaults,\n onError: hooks.onError,\n })\n return _engine\n}\n\n/**\n * Resolve the singleton cache engine.\n * Throws a clear error if not initialized — usually means the framework\n * bootstrap missed calling initCacheEngine, or cache.enabled is false.\n */\nexport function getCacheEngine(): CacheEngine {\n if (!_engine) {\n throw new Error(\n 'Cache engine not initialized. Ensure theo.config.ts has `cache.enabled: true` and the framework bootstrap called initCacheEngine.',\n )\n }\n return _engine\n}\n\n/**\n * Test-only: clear the singleton so the next test can re-init.\n * Production code MUST NOT call this.\n */\nexport function _resetCacheEngine(): void {\n _engine = undefined\n}\n","import { getCacheEngine } from './engine-singleton.js'\nimport { validateTags } from './validation.js'\n\nexport interface RevalidateResult {\n deleted: number\n}\n\n/**\n * Invalidate all cache entries carrying the given tag.\n * Safe to call from any context (route handler, action, webhook).\n *\n * `opts.expire` accepted for API compatibility with Next.js; at MVP we delete\n * immediately (no SWR-with-expire semantics). A non-zero value emits one warn.\n */\nexport async function revalidateTag(\n tag: string,\n opts?: { expire?: number },\n): Promise<RevalidateResult> {\n if (opts?.expire !== undefined && opts.expire > 0) {\n warnOnce(\n 'revalidateTag-expire',\n '[theokit:cache] revalidateTag opts.expire is accepted but not honored at MVP (entries are deleted immediately).',\n )\n }\n const { valid } = validateTags([tag], 'revalidateTag')\n if (valid.length === 0) return { deleted: 0 }\n const engine = getCacheEngine()\n const deleted = await engine.invalidateTag(valid[0])\n return { deleted }\n}\n\n/**\n * Immediate invalidation (no SWR), Server-Action-safe.\n * Same semantics as revalidateTag at MVP; kept as separate name for\n * call-site clarity (\"I want fresh data NOW\").\n */\nexport async function updateTag(tag: string): Promise<RevalidateResult> {\n const { valid } = validateTags([tag], 'updateTag')\n if (valid.length === 0) return { deleted: 0 }\n const engine = getCacheEngine()\n const deleted = await engine.invalidateTag(valid[0])\n return { deleted }\n}\n\n/**\n * Invalidate cached entries for a route path.\n * Sugar over `revalidateTag('_THEO_T_/${path}/${type?}')`.\n */\nexport async function revalidatePath(\n path: string,\n opts?: { type?: 'layout' | 'page'; expire?: number },\n): Promise<RevalidateResult> {\n if (opts?.expire !== undefined && opts.expire > 0) {\n warnOnce(\n 'revalidatePath-expire',\n '[theokit:cache] revalidatePath opts.expire is accepted but not honored at MVP.',\n )\n }\n const engine = getCacheEngine()\n const deleted = await engine.revalidatePath(path, opts?.type)\n return { deleted }\n}\n\nconst warnedKeys = new Set<string>()\nfunction warnOnce(key: string, message: string): void {\n if (warnedKeys.has(key)) return\n warnedKeys.add(key)\n console.warn(message)\n}\n","import picomatch from 'picomatch'\n\nexport interface RouteRule {\n maxAge?: number\n swr?: number\n tags?: string[]\n}\n\nexport type RouteRules = Record<string, RouteRule>\n\nexport interface CompiledRouteRule {\n matcher: (path: string) => boolean\n rule: RouteRule\n /** Original glob pattern (for debugging). */\n pattern: string\n}\n\n/**\n * Compile route-rule glob patterns into matcher functions.\n * First-match-wins semantics (preserves insertion order).\n *\n * EC-5: picomatch is a direct production dependency (see plan T7.2).\n */\nexport function compileRouteRules(rules: RouteRules): CompiledRouteRule[] {\n return Object.entries(rules).map(([pattern, rule]) => ({\n matcher: picomatch(pattern, { dot: true }),\n rule,\n pattern,\n }))\n}\n\n/**\n * Resolve the first matching rule for `path`, or `undefined` if none match.\n */\nexport function resolveRouteRule(\n path: string,\n compiled: CompiledRouteRule[],\n): RouteRule | undefined {\n for (const c of compiled) {\n if (c.matcher(path)) return c.rule\n }\n return undefined\n}\n","/**\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/**\n * Build a code-mode `CustomTool`. Fails fast if `onPermissionRequest` or `sandbox` is missing\n * (security by default). The returned tool takes `{ code }`, assembles the permission-gated restricted\n * API from `tools`, runs the code in the injected sandbox, and returns the code's result.\n */\nexport function createCodeMode(config: CodeModeConfig): CustomTool {\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\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 return {\n name: config.name ?? 'run_code',\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}\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","import superjson from 'superjson'\n\nexport interface SerializedResponse {\n json: unknown\n meta?: unknown\n}\n\n/**\n * Serialize data using superjson for rich type support (Date, Map, Set, BigInt, etc.)\n */\nexport function serializeResponse(data: unknown): SerializedResponse {\n return superjson.serialize(data)\n}\n\n/**\n * Deserialize data that was serialized with superjson.\n */\nexport function deserializeResponse(serialized: SerializedResponse): unknown {\n return superjson.deserialize(serialized as Parameters<typeof superjson.deserialize>[0])\n}\n","/**\n * M33 Phase 1 — `callProcedure`, the in-process typed caller.\n *\n * The load-bearing seam for non-HTTP surfaces (TUI / Tauri / MCP-tools): invoke a route's shared\n * logic with STRUCTURED input, WITHOUT going through the HTTP transport (no URL/body parsing, no\n * middleware chain, no Response). It reuses the SAME Zod validation pipeline as the HTTP path\n * (`validateRouteInput`) so there is no drift, and reuses the SAME `config.response` server-fault\n * check. Failures throw typed errors (there is no HTTP status off-web).\n *\n * Prior art: tRPC `callProcedure` / `createCallerFactory`\n * (`.claude/knowledge-base/references/trpc/packages/server/src/unstable-core-do-not-import/router.ts:401,441`).\n *\n * Design (ADR-0044 / blueprint §5.4): the AUTHOR passes structured input `{query?, body?, params?}`\n * — never synthesizes a Request. A minimal in-process `Request` is provided to the handler ONLY so\n * handlers that read `request.headers`/`request.url` still work (opencode's proven pattern); the\n * input itself is NOT parsed from it.\n */\nimport type { z } from 'zod'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport {\n validateRouteInput,\n type RawRouteInput,\n type RouteInputChannel,\n} from './validate-route-input.js'\n\n/** Structured input for an in-process procedure call — one object per declared channel. */\nexport type ProcedureInput = RawRouteInput\n\n/**\n * Thrown when structured input fails the route's Zod validation. The in-process analog of the HTTP\n * 400 — carries the failing channel + the Zod issues (typed error, not a magic value; Rule 8).\n */\nexport class ProcedureInputError extends Error {\n readonly channel: RouteInputChannel\n readonly issues: z.core.$ZodIssue[]\n constructor(channel: RouteInputChannel, error: z.ZodError) {\n super(`Invalid ${channel} for in-process procedure call: ${error.message}`)\n this.name = 'ProcedureInputError'\n this.channel = channel\n this.issues = error.issues\n }\n}\n\n/**\n * Thrown when the handler's plain-object return drifts from `config.response` — a SERVER fault\n * (the handler violated its own declared contract), mirroring the HTTP path's 500 as a throw.\n */\nexport class ProcedureOutputError extends Error {\n readonly issues: z.core.$ZodIssue[]\n constructor(error: z.ZodError) {\n super(`In-process procedure output failed its response schema: ${error.message}`)\n this.name = 'ProcedureOutputError'\n this.issues = error.issues\n }\n}\n\n/** A minimal, stable in-process Request for handlers that read `request.*`. Never parsed for input. */\nfunction inProcessRequest(): Request {\n return new Request('theo://in-process/procedure', { method: 'POST' })\n}\n\n/**\n * Invoke a route/procedure's handler in-process with structured, Zod-validated input.\n *\n * @param config the `RouteConfig` (what `route().build()` produces).\n * @param input structured `{query?, body?, params?}` — validated by the route's schemas.\n * @param ctx the typed run-context the handler receives (built by the CALLER — a TUI/Tauri/MCP\n * surface supplies its own ctx factory; there is no HTTP middleware chain here).\n * @returns the handler's result (validated against `config.response` when declared).\n * @throws ProcedureInputError on invalid structured input (the off-web analog of a 400).\n * @throws ProcedureOutputError on a handler output that drifts from `config.response` (server fault).\n */\nexport async function callProcedure(\n // Accept ANY RouteConfig regardless of its per-channel schema generics — a caller passes a concrete\n // `route().body(z.object(...)).build()` whose generics differ from the `ZodUndefined` defaults.\n config: RouteConfig<z.ZodType, z.ZodType, z.ZodType>,\n input: ProcedureInput = {},\n ctx?: unknown,\n): Promise<unknown> {\n const validated = validateRouteInput(config, input)\n if (!validated.ok) throw new ProcedureInputError(validated.channel, validated.error)\n\n const result = await config.handler({\n query: validated.query,\n body: validated.body,\n params: validated.params,\n request: inProcessRequest(),\n ctx: ctx,\n })\n\n // Server-fault response validation (parity with the HTTP path) — only for plain values, and only\n // when a response schema is declared. `Response` instances are pass-through (unusual off-web).\n const responseSchema = config.response\n if (responseSchema !== undefined && !(result instanceof Response)) {\n const parsed = responseSchema.safeParse(result)\n if (!parsed.success) throw new ProcedureOutputError(parsed.error)\n return parsed.data\n }\n return result\n}\n","/**\n * M33 Phase 1 — the ctx reconciliation contract (ADR-0044 D4 / blueprint §5.2, §8.5).\n *\n * ## The problem the deep research verified against our own code\n *\n * At runtime (`execute.ts:122-165`) the handler's `ctx` is written by THREE sources, not one:\n *\n * 1. **the user `context.ts` factory** — via `runMiddlewareAndContext` (`execute.ts:131`). This is\n * the ONLY writer the author controls + declares a shape for. **This is the typed surface.**\n * 2. **plugin decorations** — `pluginRunner.applyDecorations(ctx)` (`execute.ts:124,136`). Plugins\n * add arbitrary keys (`decorateRequest`) whose types the route author does not see.\n * 3. **the jobs backend** — `ctx.queue` injected when `jobs.backend` is configured (`execute.ts:141-150`).\n *\n * A naive \"infer `TCtx` from everything on `ctx`\" would LIE — it cannot see writers (2) and (3), so\n * `ctx.queue` / plugin keys would be typed as present when they are not (or vice-versa). That is the\n * exact Hono/global-augmentation failure the blueprint refuted (§8.5). oRPC/tRPC avoid it only\n * because middleware is their SOLE ctx writer; TheoKit is multi-writer.\n *\n * ## The reconciliation (what this contract locks)\n *\n * The typed `TCtx` a route handler sees reflects **only writer (1)** — the user `context.ts` factory\n * (`ContextValue` below). Writers (2) and (3) are **explicitly untyped** on the route surface:\n *\n * - `ctx.queue` (jobs) is reached through the dedicated {@link JobsAugmentedCtx} helper, NOT the\n * inferred `TCtx` — a handler that needs the queue opts into the augmented type explicitly.\n * - plugin-decorated keys are `unknown` by design (a plugin is a cross-cutting, per-app concern;\n * typing them into every route's `TCtx` would couple routes to plugin internals — G5).\n *\n * This keeps the LOCKED 5-arity `RouteConfig` generic (`route-config-generic-arity.test.ts`, GAP-4)\n * intact — `TCtx` stays the single typed ctx slot; we only define WHICH writer it corresponds to,\n * so `runtime ⊇ type` holds honestly (the type is a sound subset of the runtime ctx, never a lie).\n *\n * Type-tests proving this live in `tests/ctx-reconciliation.test-d.ts`.\n */\n\n/**\n * The typed run-context a route handler sees = the return of the user `context.ts` factory.\n * `TValue` is inferred from that factory at the web adapter seam; it EXCLUDES plugin decorations and\n * `ctx.queue` (those are not part of the author-declared shape).\n */\nexport type ContextValue<TValue extends Record<string, unknown> = Record<string, unknown>> = TValue\n\n/** The `ctx.queue` client shape injected by the jobs backend (writer 3). Reached explicitly. */\nexport interface QueueClientLike {\n enqueue(name: string, input: unknown): void | Promise<void>\n}\n\n/**\n * Opt-in augmentation for handlers that read `ctx.queue`. A route that uses the jobs queue annotates\n * its ctx as `JobsAugmentedCtx<MyCtx>` — making the jobs dependency explicit in the type, instead of\n * silently assuming `ctx.queue` exists on every route (which would lie when `jobs.backend` is unset).\n */\nexport type JobsAugmentedCtx<TValue extends Record<string, unknown> = Record<string, unknown>> =\n TValue & { queue: QueueClientLike }\n\n/**\n * The three runtime ctx writers, named for documentation + the type-test. This is the reconciliation\n * artifact the plan requires as a deliverable (not a footnote).\n */\nexport const CTX_WRITERS = {\n /** Writer 1 — user `context.ts` factory. THE typed surface (`TCtx`). execute.ts:131 */\n contextFactory: 'context.ts',\n /** Writer 2 — plugin `decorateRequest`. Untyped on the route surface. execute.ts:124,136 */\n pluginDecorations: 'pluginRunner.applyDecorations',\n /** Writer 3 — jobs backend `ctx.queue`. Reached via JobsAugmentedCtx, not TCtx. execute.ts:141-150 */\n jobsQueue: 'jobBackend',\n} as const\n","/**\n * theokit/server — DEPRECATED umbrella barrel.\n *\n * **Per plan theokit-arch-gaps-implementation T2.5 (M1) + EC-2:**\n *\n * Importing from `theokit/server` is DEPRECATED as of this release. The\n * 16 sub-domain exports (auth, jobs, http, security, observability, etc.)\n * are now individually addressable via `package.json#exports`:\n *\n * import { defineAuth } from 'theokit/server/auth'\n * import { defineJob } from 'theokit/server/jobs'\n * import { defineRoute, defineAction } from 'theokit/server/define'\n * // ...etc per `packages/theo/package.json` exports field\n *\n * This umbrella barrel will continue to work for ONE minor cycle\n * (0.x → 0.x+1) with a single runtime warning printed on first import.\n * Final removal in 0.x+2 per CHANGELOG.\n *\n * Why: `export *` wildcards across 16 sub-domains violate ISP at the\n * package-surface level (consumers pay for 376 transitive exports when\n * they wanted 6). See `architecture-output/consolidated_final_report.md`\n * M1 finding + blueprint Q4 D4 (Hono-shape exports field adoption).\n *\n * Migration codemod (provided in this release):\n * pnpm exec theokit migrate server-umbrella-to-subpaths\n *\n * For body-parser, serialization, transformer, webhook helpers, trace context\n * propagation, error pages, plugin types, and config/env helpers — re-exported\n * inline because they don't fit a single sub-barrel cleanly. Those will land\n * in a `theokit/server/runtime` sub-path in the 0.x+2 cleanup.\n */\n\n// One-time deprecation warning. Fires on first import in the process and\n// is silenced afterwards via a module-scoped flag. Tree-shake-safe: the\n// IIFE body executes on module load (no DCE), but the cost is one\n// console.warn at startup — negligible. Apps that grep for this string\n// see exactly which entry point logged it.\nif (typeof globalThis !== 'undefined') {\n const WARN_KEY = '__theokit_server_umbrella_warn_emitted__'\n const g = globalThis as Record<string, unknown>\n if (g[WARN_KEY] !== true) {\n g[WARN_KEY] = true\n\n console.warn(\n '[theokit] umbrella import \"theokit/server\" is DEPRECATED. ' +\n 'Use sub-paths (theokit/server/<domain>): auth, jobs, http, security, ' +\n 'observability, etc. See packages/theo/package.json#exports for the ' +\n 'full list. Removal scheduled for 0.x+2.',\n )\n }\n}\n\n// Core defines + low-level pipeline primitives (used by adapter templates)\nexport * from './define/index.js'\nexport * from './http/index.js'\nexport * from './scan/index.js'\n\n// G3 action protocol: ActionError + ActionInputError + helpers, re-exported\n// from core/contracts for consumer ergonomics (`from 'theokit/server'`).\nexport {\n ActionError,\n ActionInputError,\n extractUniversalIssues,\n isActionError,\n isInputError,\n type ActionErrorCode,\n type ActionManifestEntry,\n type ActionResult,\n type SerializedActionResult,\n type UniversalZodIssue,\n} from '../core/contracts/action-protocol.js'\n\n// Subdomain sub-barrels (consumers can also import direct: theokit/server/<sub>)\n// (server/agent had only the proprietary surface — removed in the M3 clean break;\n// its survivors mount-agent/provider-resolver/configure-agent-registry are internal.)\nexport * from './auth/index.js'\nexport * from './cost/index.js'\nexport * from './cron/index.js'\nexport * from './jobs/index.js'\nexport * from './observability/index.js'\nexport * from './plugins/index.js'\nexport * from './rate-limit/index.js'\nexport * from './realtime/index.js'\nexport * from './security/index.js'\nexport * from './storage/index.js'\nexport * from './webhook/index.js'\nexport * from './openapi/index.js'\n\n// Cross-module: cache lives at packages/theo/src/cache/ (not server/cache)\nexport * from '../cache/index.js'\n\n// Agent-tool adapters — wrap an external runtime (coding agent, SDK workflow) as a `CustomTool`.\n// M26 — SDK `Workflow` as a tool (thin adapter; the engine is the SDK's). M17 — coding agent (ACP).\nexport { createWorkflowTool } from './agent/workflow-tool.js'\nexport type { WorkflowLike, WorkflowToolConfig } from './agent/workflow-tool.js'\nexport { createACPTool, NodeAcpTransport } from './agent/acp-tool.js'\nexport type { AcpToolConfig } from './agent/acp-tool.js'\n// M28 — third-party agent SDK (Claude/OpenAI/Cursor) as a tool (vendor runtime stays theirs).\nexport { createVendorAgentTool } from './agent/vendor-agent-tool.js'\nexport type { VendorAgentClient, VendorAgentToolConfig } from './agent/vendor-agent-tool.js'\n// M29 — code-mode sandbox: agent composes tools in code run inside an INJECTED isolation boundary.\nexport { createCodeMode, CodeModePermissionDeniedError } from './agent/code-mode.js'\nexport type { Sandbox, CodeModeApi, CodeModeConfig, CodeModePermission } from './agent/code-mode.js'\n// M27 — channel webhook routes (Slack/Telegram/Discord) with per-platform signature validation.\nexport { handleChannelWebhook, parseChannelPath, isChannelPath } from './agent/channel-webhook.js'\nexport type { ChannelMessage, ChannelWebhookConfig } from './agent/channel-webhook.js'\n// M35 — in-process agent-turn seam (Model A): the Ink TUI / Tauri drive an agent turn in ONE process\n// (no HTTP loopback, no port, no CSRF), reusing streamAgentUIMessages with inline HITL resolution.\nexport {\n streamAgentTurnInProcess,\n InProcessApprovalRequiredError,\n} from './agent/stream-agent-turn-in-process.js'\nexport type {\n StreamAgentTurnInProcessInput,\n StreamAgentTurnDeps,\n InProcessApprovalRequest,\n InProcessAwaitApproval,\n} from './agent/stream-agent-turn-in-process.js'\n// M30 — MCP App `ui://` HTML resources served by the MCP server (rendered in a sandboxed iframe).\n// MCP stdio transport — expose an agent as a stdio MCP server (sibling of the HTTP route).\nexport { serveMcpStdio, handleMcpStdioLine, type StdioStreams } from './agent/mcp-stdio.js'\nexport {\n defineAppResource,\n buildResourceDescriptors,\n readAppResource,\n extractAppResources,\n} from './agent/mcp-app-resources.js'\nexport type {\n AppResource,\n AppResourceInput,\n McpResourceDescriptor,\n McpResourceContents,\n} from './agent/mcp-app-resources.js'\n\n// Inline re-exports — items that don't belong to a single sub-barrel\nexport { parseRequestBody, FileTooLargeError } from './body-parser.js'\nexport type { UploadedFile, ParsedBody, BodyParserOptions } from './body-parser.js'\n\nexport { serializeResponse, deserializeResponse } from './serialization.js'\nexport type { SerializedResponse } from './serialization.js'\n\nexport { superjsonTransformer, jsonTransformer, resolveTransformer } from './transformer.js'\nexport type { TheoTransformer } from './transformer.js'\n\n// T5a.2 Phase A — Web-Standards entry-point (R3a per ADR-0028). Accepts\n// a native Web Request and returns a native Web Response. Narrow scope:\n// method dispatch + Zod validation + envelope-shaped errors. Plugin\n// runner / CSRF / CORS / middleware integration deferred to Phase B-G\n// per docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md.\nexport { executeWebRequest } from './web-handler.js'\n\n// M33 — the in-process typed caller (the seam TUI/Tauri/MCP surfaces use to invoke route logic\n// WITHOUT synthesizing an HTTP Request). Shares the one Zod validation pipeline with the HTTP path.\nexport {\n callProcedure,\n ProcedureInputError,\n ProcedureOutputError,\n type ProcedureInput,\n} from './http/in-process-caller.js'\nexport {\n validateRouteInput,\n type RouteInputSchemas,\n type RouteInputChannel,\n type RouteInputValidation,\n type RawRouteInput,\n} from './http/validate-route-input.js'\nexport {\n type ContextValue,\n type JobsAugmentedCtx,\n type QueueClientLike,\n CTX_WRITERS,\n} from './http/ctx-reconciliation.js'\n\n// Plugin types (used by definePlugin + extension authors)\nexport type {\n TheoPlugin,\n TheoApp,\n PluginContext,\n PluginErrorContext,\n HookName,\n HookResult,\n OnRequestHook,\n PreHandlerHook,\n OnResponseHook,\n OnErrorHook,\n RunHookOptions,\n} from './plugin-types.js'\n// M31 builder-only: `plugin()` is the public authoring surface; `definePlugin`/`defineTheoPlugin`\n// are now internal (the plugin() builder's `.build()` delegates to them via source path).\n\n// Config helpers — auto-load .env for standalone server scripts (Telegram bots,\n// queue consumers, cron jobs) that bypass the CLI.\nexport { loadEnv, _resetEnvCache } from '../config/load-env.js'\nexport type { LoadEnvOptions, LoadEnvResult } from '../config/load-env-types.js'\n\n// Wave 2 — Polyglot services orchestration types (types only — runtime in services/)\nexport type {\n ServiceDefinition,\n ServicesConfig,\n ServicesConfigInput,\n ServicesConfigOutput,\n} from '../services/index.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,SAAS,YAAY,cAAc,gBAAgB;AACnD,SAAS,eAAe;AAexB,IAAM,iBAAiB,KAAK,OAAO;AACnC,IAAM,cAAc;AAMb,SAAS,qBAAqB,OAA2B,CAAC,GAAG;AAClE,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,WAAW,KAAK,mBAAmB;AACzC,QAAM,cAAc,KAAK,gBAAgB;AACzC,QAAM,QAAQ,KAAK,aAAa;AAChC,QAAM,MAAM,KAAK,UAAU;AAO3B,MAAI,iBAAiB,WAAW,GAAG;AACjC,UAAM,IAAI,MAAM,kEAAkE,WAAW,EAAE;AAAA,EACjG;AACA,QAAM,WAAW,QAAQ,WAAW;AAEpC,SAAO,CAAC,YAAsC;AAC5C,QAAI,QAAQ,WAAW,MAAO,QAAO;AAErC,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAE/B,QAAI,IAAI,aAAa,UAAU;AAC7B,YAAM,UAAU,IAAI,IAAI,GAAG,EAAE;AAC7B,aAAO,IAAI,SAAS,iBAAiB,OAAO,UAAU,GAAG,GAAG;AAAA,QAC1D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,2BAA2B,mCAAmC,OAAO,4DAA4D,OAAO,2BAA2B,OAAO,wBAAwB,OAAO;AAAA,QAC3M;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,IAAI,aAAa,UAAU;AAC7B,aAAO,cAAc,QAAQ;AAAA,IAC/B;AAEA,WAAO;AAAA,EACT;AACF;AAGA,SAAS,iBAAiB,GAAoB;AAC5C,SAAO,EAAE,MAAM,OAAO,EAAE,SAAS,IAAI;AACvC;AAIA,SAAS,WAAW,GAAmB;AACrC,SAAO,EACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,SAAS,iBAAiB,OAAe,SAAiB,QAAwB;AAChF,SAAO;AAAA;AAAA;AAAA;AAAA,WAIE,WAAW,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,yCAIa,WAAW,OAAO,CAAC;AAAA,iBAC3C,WAAW,MAAM,CAAC;AAAA;AAAA;AAGnC;AAIA,SAAS,cAAc,UAA4B;AACjD,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,WAAO,aAAa,KAAK;AAAA,MACvB,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI;AACF,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,KAAK,OAAO,gBAAgB;AAC9B,aAAO,aAAa,KAAK;AAAA,QACvB,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS,qBAAqB,iBAAiB,OAAO,IAAI;AAAA,QAC5D;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,WAAO,IAAI,SAAS,SAAS;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,iBAAiB,WAAW;AAAA,IAC7E,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,WAAO,aAAa,KAAK;AAAA,MACvB,OAAO,EAAE,MAAM,uBAAuB,QAAQ;AAAA,IAChD,CAAC;AAAA,EACH;AACF;AAEA,SAAS,aAAa,QAAgB,MAAyB;AAC7D,SAAO,IAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AAAA,IACxC;AAAA,IACA,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;;;AC7IO,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAC5B,IAAM,gBAAgB;AAEtB,IAAM,kBAAkB;AACxB,IAAM,yBAAyB;;;ACQ/B,SAAS,aAAa,MAAe,aAA+C;AAEzF,MAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,UAAM,SAAmC;AAAA,MACvC,OAAO,CAAC;AAAA,MACR,SAAS,CAAC,EAAE,OAAO,MAAM,QAAQ,uBAAuB,OAAO,IAAI,GAAG,CAAC;AAAA,IACzE;AACA,gBAAY,QAAQ,WAAW;AAC/B,WAAO;AAAA,EACT;AAIA,QAAM,SAAoB;AAC1B,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAgD,CAAC;AAEvD,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,QAAI,MAAM,UAAU,qBAAqB;AACvC,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,gBAAQ,KAAK,EAAE,OAAO,OAAO,CAAC,GAAG,QAAQ,0BAA0B,CAAC;AAAA,MACtE;AACA;AAAA,IACF;AACA,UAAM,MAAe,OAAO,CAAC;AAC7B,QAAI,OAAO,QAAQ,UAAU;AAC3B,cAAQ,KAAK,EAAE,OAAO,KAAK,QAAQ,iCAAiC,CAAC;AACrE;AAAA,IACF;AACA,QAAI,IAAI,SAAS,sBAAsB;AACrC,cAAQ,KAAK;AAAA,QACX,OAAO;AAAA,QACP,QAAQ,0BAA0B,oBAAoB;AAAA,MACxD,CAAC;AACD;AAAA,IACF;AACA,QAAI,IAAI,WAAW,aAAa,GAAG;AACjC,cAAQ,KAAK;AAAA,QACX,OAAO;AAAA,QACP,QAAQ,oBAAoB,aAAa;AAAA,MAC3C,CAAC;AACD;AAAA,IACF;AACA,UAAM,KAAK,GAAG;AAAA,EAChB;AAEA,cAAY,EAAE,OAAO,QAAQ,GAAG,WAAW;AAC3C,SAAO,EAAE,OAAO,QAAQ;AAC1B;AAOO,SAAS,eAAe,QAAiB,aAA6B;AAC3E,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,KAAK,UAAU,GAAG;AACxE,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAAA,IACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,QAAQ,WAAW;AAAA,EAC9D;AACF;AAMO,SAAS,eACd,QACA,YACA,aACoB;AACpB,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,OAAO,WAAW,YAAY,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AACxE,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,QAAQ,WAAW;AAAA,IAC9D;AAAA,EACF;AACA,MAAI,eAAe,UAAa,SAAS,YAAY;AACnD,UAAM,IAAI;AAAA,MACR,kBAAkB,MAAM,OAAO,WAAW,iDAAiD,UAAU;AAAA,IACvG;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,QAAkC,aAA2B;AAChF,MAAI,OAAO,QAAQ,WAAW,EAAG;AACjC,UAAQ,KAAK,mBAAmB,WAAW,aAAa,OAAO,QAAQ,MAAM,kBAAkB;AAC/F,aAAW,EAAE,OAAO,OAAO,KAAK,OAAO,SAAS;AAC9C,YAAQ,KAAK,OAAO,KAAK,UAAU,KAAK,CAAC,KAAK,MAAM,EAAE;AAAA,EACxD;AACF;;;AC3EO,SAAS,qBACd,QACA,IACA,MACgC;AAChC,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,WAAW,GAAG;AAC3D,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACA,QAAM,SAAS,eAAe,KAAK,QAAQ,wBAAwB,KAAK,IAAI,GAAG;AAC/E,QAAM,MAAM,eAAe,KAAK,KAAK,QAAQ,wBAAwB,KAAK,IAAI,GAAG;AAEjF,QAAM,SAAS,MAAM,KAAK,IAAI;AAE9B,WAAS,eAAe,MAAqB;AAC3C,UAAM,OAAO,KAAK,SAAS,KAAK,OAAO,GAAG,IAAI,IAAI,KAAK,UAAU,IAAI;AACrE,WAAO,GAAG,MAAM,IAAI,IAAI;AAAA,EAC1B;AAEA,WAAS,YAAY,MAAuB;AAC1C,UAAM,MAAM,OAAO,KAAK,SAAS,aAAa,KAAK,KAAK,GAAG,IAAI,IAAK,KAAK,QAAQ,CAAC;AAClF,UAAM,EAAE,MAAM,IAAI,aAAa,KAAK,wBAAwB,KAAK,IAAI,GAAG;AACxE,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,UAAU,SAAgB;AACzC,UAAM,MAAM,eAAe,IAAI;AAC/B,UAAM,OAAO,YAAY,IAAI;AAC7B,QAAI;AACF,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,aAAsB,KAAK,YAAY,GAAG,GAAG,IAAI,GAAG;AAAA,QACjF;AAAA,QACA,KAAK,OAAO,SAAS;AAAA,QACrB;AAAA,QACA,cAAc,KAAK;AAAA,QACnB,WAAW,KAAK;AAAA,QAChB,UAAU,KAAK;AAAA,MACjB,CAAC;AACD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,WAAK,UAAU,KAAK,EAAE,KAAK,CAAC;AAC5B,YAAM;AAAA,IACR;AAAA,EACF;AAEA,UAAQ,aAAa,UAAU,SAAgB;AAC7C,UAAM,MAAM,eAAe,IAAI;AAC/B,UAAM,OAAO,WAAW,GAAG;AAAA,EAC7B;AAEA,SAAO;AACT;;;AC9EA,IAAM,kBAAkB;AAWjB,SAAS,sBAAsB,OAAkC;AACtE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,UAAW,OAAM,KAAK,SAAS;AACzC,QAAM,KAAK,YAAY,MAAM,MAAM,EAAE;AACrC,MAAI,MAAM,QAAQ,UAAa,MAAM,MAAM,GAAG;AAC5C,UAAM,KAAK,0BAA0B,MAAM,GAAG,EAAE;AAAA,EAClD;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACxBO,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAwBA,eAAsBA,WAAU,KAAc,OAA6B,CAAC,GAAoB;AAC9F,MAAI,KAAK,QAAQ;AACf,UAAM,IAAI,MAAM,KAAK,OAAO,GAAG;AAC/B,QAAI,OAAO,MAAM,UAAU;AACzB,YAAM,IAAI,MAAM,oCAAoC,OAAO,CAAC,EAAE;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,cAAc,iBAAiB,KAAK,IAAI;AAC9C,QAAM,OAAO,GAAG,KAAK,SAAS,KAAK,SAAS,MAAM,EAAE,GAAG,IAAI,QAAQ,KAAK,IAAI,SAAS,YAAY,CAAC,GAAG,IAAI,QAAQ,GAAG,cAAc,MAAM,cAAc,EAAE;AAExJ,MAAI,CAAC,KAAK,UAAU,KAAK,OAAO,WAAW,EAAG,QAAO;AACrD,QAAM,QAAkB,CAAC;AACzB,aAAW,UAAU,KAAK,QAAQ;AAChC,UAAM,KAAK,GAAG,MAAM,IAAI,IAAI,QAAQ,IAAI,MAAM,KAAK,EAAE,EAAE;AAAA,EACzD;AACA,SAAO,OAAO,OAAO,MAAM,KAAK,IAAI;AACtC;AAEA,SAAS,iBAAiB,KAAU,MAAoC;AACtE,QAAM,SAAS,IAAI,gBAAgB,IAAI,YAAY;AACnD,QAAM,UAAU,KAAK,gBAAgB;AACrC,QAAM,aAAa,IAAI,IAAI,OAAO;AAClC,aAAW,OAAO,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG;AACpC,QAAI,WAAW,IAAI,GAAG,EAAG,QAAO,OAAO,GAAG;AAAA,EAC5C;AACA,MAAI,KAAK,cAAc,MAAO,QAAO,KAAK;AAC1C,SAAO,OAAO,SAAS;AACzB;;;AC7EO,IAAM,yBAAyB,KAAK,OAAO;AAClD,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,YAAY,CAAC;AAuCvD,IAAM,wBAAwB,oBAAI,QAAQ;AAC1C,IAAM,2BAA2B,oBAAI,QAAQ;AAC7C,IAAM,wBAAwB,oBAAI,QAAQ;AAsBnC,SAAS,kBAMd,QACA,QACqD;AACrD,QAAM,EAAE,OAAO,SAAS,GAAG,KAAK,IAAI;AAEpC,QAAM,SAAS,eAAe,MAAM,QAAQ,mBAAmB;AAC/D,QAAM,MAAM,eAAe,MAAM,KAAK,QAAQ,mBAAmB;AACjE,MAAI,MAAM,iBAAiB,UAAa,MAAM,iBAAiB,IAAI;AACjE,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AAEA,QAAM,eAAe,MAAM,gBAAgB;AAC3C,MAAI,CAAC,OAAO,SAAS,YAAY,KAAK,eAAe,GAAG;AACtD,UAAM,IAAI;AAAA,MACR,yBAAyB,OAAO,MAAM,YAAY,CAAC;AAAA,IACrD;AAAA,EACF;AACA,QAAM,UAAU,IAAI,KAAK,MAAM,WAAW,CAAC,OAAO,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACtF,QAAM,WAAW,aAAa,MAAM,QAAQ,CAAC,GAAG,mBAAmB,EAAE;AAGrE,QAAM,YAAY,MAAM,UAAU,CAAC;AACnC,QAAM,cAAc,UAAU,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AACxD,QAAM,gBAAgB,YAAY,KAAK,CAAC,MAAM,eAAe,IAAI,CAAC,CAAC;AACnE,QAAM,aAAa,YAAY,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC;AACnE,MAAI,iBAAiB,CAAC,yBAAyB,IAAI,MAAM,GAAG;AAC1D,6BAAyB,IAAI,MAAM;AACnC,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,QAML;AAGvB,UAAM,aAAa,aAAa,IAAI,OAAO;AAE3C,QAAI,CAAC,QAAQ,IAAI,WAAW,OAAO,YAAY,CAAC,GAAG;AACjD,aAAO,wBAAwB,SAAS,GAAG;AAAA,IAC7C;AACA,QAAI,MAAM,cAAe,MAAM,MAAM,WAAW,UAAU,GAAI;AAC5D,aAAO,wBAAwB,SAAS,GAAG;AAAA,IAC7C;AACA,QAAI,WAAW,GAAG;AAChB,aAAO,wBAAwB,SAAS,GAAG;AAAA,IAC7C;AAEA,UAAM,MAAM,MAAMC,WAAU,YAAY;AAAA,MACtC,QAAQ,WAAW,WAAW,OAAO,YAAY;AAAA,MACjD,QAAQ;AAAA,MACR,QAAQ,MAAM;AAAA,IAChB,CAAC;AAGD,UAAM,SAAS,MAAM,OAAO,cAA+B,KAAK;AAAA,MAC9D,cAAc,MAAM;AAAA,IACtB,CAAC;AAGD,UAAM,gBAA+B;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,QAAQ;AACV,UAAI,OAAO,WAAW,OAAO;AAC3B,eAAO,uBAAuB,OAAO,OAAO,OAAO,QAAQ,GAAG;AAAA,MAChE;AAGA,8BAAwB,eAAe,SAAS,GAAG;AACnD,aAAO,uBAAuB,OAAO,OAAO,SAAS,QAAQ,GAAG;AAAA,IAClE;AAGA,UAAM,WAAW,MAAM,wBAAwB,SAAS,GAAG;AAC3D,WAAO,iBAAiB,eAAe,QAAQ;AAAA,EACjD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS;AAAA,EACX;AACF;AA2BA,SAAS,qBAAqB,OAAwB,KAAgC;AACpF,QAAM,UAAU,gBAAgB,IAAI,IAAI,IAAI,WAAW,GAAG,EAAE;AAC5D,SAAO;AAAA,IACL,MAAM,KAAK,UAAU,KAAK;AAAA,IAC1B,QAAQ;AAAA,IACR,SAAS,CAAC;AAAA,IACV,UAAU,KAAK,IAAI;AAAA,IACnB,QAAQ,IAAI;AAAA,IACZ,KAAK,IAAI,OAAO,IAAI,SAAS;AAAA,IAC7B,MAAM,CAAC,GAAG,IAAI,UAAU,OAAO;AAAA,IAC/B,cAAc,IAAI,MAAM;AAAA,EAC1B;AACF;AAEA,eAAe,iBAAiB,KAAoB,UAAuC;AACzF,QAAM,kBAAkB,MAAM;AAAA,IAC5B;AAAA,IACA,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AACA,MAAI,CAAC,iBAAiB;AAEpB,WAAO;AAAA,EACT;AACA,QAAM,IAAI,OAAO,IAAI,IAAI,KAAK,qBAAqB,iBAAiB,GAAG,CAAC;AACxE,SAAO,uBAAuB,iBAAiB,QAAQ,IAAI,QAAQ,IAAI,GAAG;AAC5E;AAEA,SAAS,wBACP,KACA,SACA,YACM;AACN,QAAM,YAAY;AAChB,QAAI;AACF,YAAM,WAAW,MAAM,wBAAwB,SAAS,UAAU;AAClE,YAAM,SAAS,MAAM,iBAAiB,UAAU,IAAI,OAAO,IAAI,aAAa,IAAI,YAAY;AAC5F,UAAI,CAAC,OAAQ;AACb,YAAM,IAAI,OAAO,IAAI,IAAI,KAAK,qBAAqB,QAAQ,GAAG,CAAC;AAAA,IACjE,QAAQ;AAAA,IAER;AAAA,EACF,GAAG;AACL;AAmBA,SAAS,aAAa,KAAyC;AAE7D,MAAI,OAAQ,IAAgB,UAAU,cAAe,IAAgB,mBAAmB,SAAS;AAC/F,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AACb,QAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,WAAW,KAAK,QAAQ,OAAO,SAAS;AACnF,QAAM,WAAW,KAAK,QAAQ,YAAY,UAAU;AACpD,QAAM,OAAO,KAAK,OAAO;AACzB,QAAM,MAAM,KAAK,WAAW,MAAM,IAAI,OAAO,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI;AACzE,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACjD,QAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,iBAAW,QAAQ,EAAG,SAAQ,OAAO,GAAG,IAAI;AAAA,IAC9C,WAAW,OAAO,MAAM,UAAU;AAChC,cAAQ,IAAI,GAAG,CAAC;AAAA,IAClB;AAAA,EACF;AACA,SAAO,IAAI,QAAQ,KAAK;AAAA,IACtB,SAAS,KAAK,UAAU,OAAO,YAAY;AAAA,IAC3C;AAAA,EACF,CAAC;AACH;AAEA,eAAe,wBACb,SACA,KACmB;AACnB,QAAM,MAAM,MAAM,QAAQ,GAAG;AAC7B,MAAI,eAAe,SAAU,QAAO;AACpC,SAAO,SAAS,KAAK,GAAG;AAC1B;AAMA,eAAe,iBACb,UACA,OACA,aACA,cACsC;AAEtC,MAAI,SAAS,QAAQ,IAAI,YAAY,GAAG;AACtC,QAAI,CAAC,sBAAsB,IAAI,WAAW,GAAG;AAC3C,4BAAsB,IAAI,WAAW;AACrC,cAAQ,KAAK,0EAAqE;AAAA,IACpF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,MAAI,YAAY,SAAS,mBAAmB,EAAG,QAAO;AAMtD,MAAI,SAAS,QAAQ,IAAI,mBAAmB,GAAG,YAAY,MAAM,WAAW;AAC1E,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,UAAU,OAAO,CAAC,MAAM,YAAa,QAAO;AAEzD,MAAI,MAAM,aAAa,CAAC,MAAM,UAAU,QAAQ,EAAG,QAAO;AAG1D,QAAM,OAAO,MAAM,SAAS,MAAM,EAAE,KAAK;AAGzC,MAAI,KAAK,SAAS,cAAc;AAC9B,QAAI,CAAC,sBAAsB,IAAI,WAAW,GAAG;AAC3C,4BAAsB,IAAI,WAAW;AACrC,cAAQ;AAAA,QACN,iCAAiC,KAAK,MAAM,+BAA+B,YAAY;AAAA,MACzF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAA8B,CAAC;AACrC,WAAS,QAAQ,QAAQ,CAAC,GAAG,MAAM;AACjC,QAAI,EAAE,YAAY,MAAM,aAAc;AACtC,YAAQ,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,EACrB,CAAC;AACD,SAAO,EAAE,MAAM,MAAM,QAAQ,SAAS,QAAQ,QAAQ;AACxD;AAEA,SAAS,uBACP,OACA,QACA,QACA,KACU;AACV,QAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,MAAI,CAAC,QAAQ,IAAI,eAAe,GAAG;AACjC,YAAQ,IAAI,iBAAiB,sBAAsB,EAAE,QAAQ,KAAK,OAAO,SAAS,GAAG,CAAC,CAAC;AAAA,EACzF;AACA,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,oBAA8C;AAClD,QAAI,WAAW,MAAO,qBAAoB;AAAA,aACjC,WAAW,QAAS,qBAAoB;AACjD,YAAQ,IAAI,gBAAgB,iBAAiB;AAAA,EAC/C;AACA,SAAO,IAAI,SAAS,MAAM,MAAM,EAAE,QAAQ,MAAM,QAAQ,QAAQ,CAAC;AACnE;;;ACnSO,SAAS,kBAAkB,MAAuC;AACvE,QAAM,EAAE,SAAS,QAAQ,IAAI;AAC7B,QAAM,WAAW,oBAAI,IAA8B;AACnD,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,wBAAwB,oBAAI,IAAY;AAE9C,iBAAe,aACb,KACA,IACA,SAC4C;AAE5C,UAAM,UAAU,SAAS,IAAI,GAAG;AAChC,QAAI,SAAS;AACX,YAAM,QAAS,MAAM;AACrB,aAAO,EAAE,OAAO,QAAQ,OAAO;AAAA,IACjC;AAGA,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO;AAAA,QAAY;AAAA,QAAK;AAAA,QAAI;AAAA;AAAA,QAAyB;AAAA,MAAI;AAAA,IAC3D;AAGA,WAAO,YAAY,KAAK,IAAI,SAAS,KAAK;AAAA,EAC5C;AAMA,WAAS,YACP,KACA,IACA,SACA,WAC4C;AAC5C,QAAI;AACJ,QAAI;AACJ,UAAM,eAAe,IAAI,QAAW,CAACC,UAAS,WAAW;AACvD,qBAAeA;AACf,oBAAc;AAAA,IAChB,CAAC;AAED,SAAK,aAAa,MAAM,MAAM;AAAA,IAE9B,CAAC;AACD,aAAS,IAAI,KAAK,YAAY;AAE9B,UAAM,QAAQ,YAAwD;AACpE,UAAI;AACF,YAAI,CAAC,WAAW;AACd,gBAAM,SAAS,MAAM,cAAiB,KAAK,OAAO;AAClD,cAAI,QAAQ;AAEV,yBAAa,OAAO,KAAK;AACzB,gBAAI,OAAO,WAAW,SAAS;AAC7B,2CAA6B,KAAK,IAAI,OAAO;AAAA,YAC/C;AACA,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,cAAM,QAAQ,MAAM,UAAU,KAAK,IAAI,SAAS,SAAS;AACzD,qBAAa,KAAK;AAClB,eAAO,EAAE,OAAO,QAAQ,OAAgB;AAAA,MAC1C,SAAS,KAAK;AACZ,oBAAY,GAAG;AACf,cAAM;AAAA,MACR,UAAE;AACA,iBAAS,OAAO,GAAG;AAAA,MACrB;AAAA,IACF,GAAG;AAEH,WAAO;AAAA,EACT;AAMA,iBAAe,cACb,KACA,SACwD;AACxD,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,IAAI,GAAG;AAAA,IAC/B,SAAS,KAAK;AACZ,gBAAU,KAAK,EAAE,OAAO,OAAO,IAAI,CAAC;AACpC,aAAO;AAAA,IACT;AACA,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,QAAQ,iBAAiB,UAAa,MAAM,iBAAiB,QAAQ,cAAc;AACrF,aAAO;AAAA,IACT;AACA,QAAI,OAAO,MAAM,SAAS,SAAU,QAAO;AAC3C,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,MAAM,IAAI;AAAA,IAChC,SAAS,KAAK;AACZ,gBAAU,KAAK,EAAE,OAAO,OAAO,IAAI,CAAC;AACpC,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ,UAAU;AACpB,UAAI;AACF,YAAI,CAAC,QAAQ,SAAS,MAAM,EAAG,QAAO;AAAA,MACxC,SAAS,KAAK;AACZ,kBAAU,KAAK,EAAE,OAAO,OAAO,IAAI,CAAC;AACpC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,MAAM,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,YAAY,GAAI;AAC5D,QAAI,OAAO,MAAM,QAAQ;AACvB,YAAM,QAAQ,QAAQ,YAAY,QAAQ,UAAU,MAAM,IAAI;AAC9D,aAAO,EAAE,OAAO,QAAQ,MAAM;AAAA,IAChC;AACA,QAAI,OAAO,MAAM,SAAS,MAAM,KAAK;AACnC,YAAM,QAAQ,QAAQ,YAAY,QAAQ,UAAU,MAAM,IAAI;AAC9D,aAAO,EAAE,OAAO,QAAQ,QAAQ;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAKA,iBAAe,UACb,KACA,IACA,SACA,YAAY,OACA;AACZ,UAAM,MAAM,MAAM,GAAG;AACrB,UAAM,QAAQ,QAAQ,YAAY,QAAQ,UAAU,GAAG,IAAI;AAE3D,QAAI,UAAW,QAAO;AAGtB,QAAI,QAAQ,gBAAgB,KAAK,EAAG,QAAO;AAG3C,QAAI,QAAQ,UAAU;AACpB,UAAI,UAAU;AACd,UAAI;AACF,kBAAU,QAAQ,SAAS,KAAK;AAAA,MAClC,SAAS,KAAK;AACZ,kBAAU,KAAK,EAAE,OAAO,OAAO,IAAI,CAAC;AACpC,eAAO;AAAA,MACT;AACA,UAAI,CAAC,QAAS,QAAO;AAAA,IACvB;AAGA,QAAI,UAAU,QAAW;AACvB,UAAI,CAAC,sBAAsB,IAAI,GAAG,GAAG;AACnC,8BAAsB,IAAI,GAAG;AAC7B,gBAAQ,KAAK,sDAAsD,GAAG,qBAAqB;AAAA,MAC7F;AACA,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,QAAoB;AAAA,QACxB,MAAM,KAAK,UAAU,KAAK;AAAA,QAC1B,QAAQ;AAAA,QACR,SAAS,CAAC;AAAA,QACV,UAAU,KAAK,IAAI;AAAA,QACnB,QAAQ,QAAQ;AAAA,QAChB,KAAK,QAAQ,OAAO;AAAA,QACpB,MAAM,QAAQ,QAAQ,CAAC;AAAA,QACvB,cAAc,QAAQ;AAAA,MACxB;AACA,YAAM,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC9B,SAAS,KAAK;AACZ,gBAAU,KAAK,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAEA,WAAS,6BACP,KACA,IACA,SACM;AACN,QAAI,WAAW,IAAI,GAAG,EAAG;AACzB,eAAW,IAAI,GAAG;AAClB,SAAK,UAAU,KAAK,IAAI,OAAO,EAC5B,MAAM,CAAC,QAAiB;AACvB,gBAAU,KAAK,EAAE,OAAO,cAAc,IAAI,CAAC;AAAA,IAC7C,CAAC,EACA,QAAQ,MAAM;AACb,iBAAW,OAAO,GAAG;AAAA,IACvB,CAAC;AAAA,EACL;AAEA,SAAO;AAAA,IACL;AAAA,IAEA;AAAA,IAEA,MAAM,cACJ,KACAC,OAC4D;AAI5D,YAAM,SAAS,MAAM,cAAiB,KAAK;AAAA,QACzC,GAAGA;AAAA,QACH,QAAQ;AAAA;AAAA,MACV,CAAC;AACD,UAAI,CAAC,OAAQ,QAAO;AACpB,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,IAAI,KAAK,OAAO;AACpB,YAAM,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC9B;AAAA,IAEA,MAAM,WAAW,KAAK;AAEpB,eAAS,OAAO,GAAG;AACnB,aAAO,QAAQ,OAAO,GAAG;AAAA,IAC3B;AAAA,IAEA,MAAM,cAAc,KAAK;AACvB,aAAO,QAAQ,YAAY,GAAG;AAAA,IAChC;AAAA,IAEA,MAAM,eAAe,MAAM,MAAM;AAC/B,YAAM,MAAM,gBAAgB,QAAQ,OAAO,MAAM,OAAO;AACxD,aAAO,QAAQ,YAAY,GAAG;AAAA,IAChC;AAAA,EACF;AACF;;;ACzSO,IAAM,uBAAN,MAA0D;AAAA,EACtD,OAAO;AAAA,EACP,WAAW,oBAAI,IAAwB;AAAA,EACvC,YAAY,oBAAI,IAAyB;AAAA,EACzC;AAAA,EAET,YAAY,OAAoC,CAAC,GAAG;AAClD,SAAK,cAAc,KAAK,cAAc;AAAA,EACxC;AAAA,EAEA,MAAM,IAAI,KAA8C;AACtD,UAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AACnC,QAAI,UAAU,OAAW,QAAO;AAEhC,SAAK,SAAS,OAAO,GAAG;AACxB,SAAK,SAAS,IAAI,KAAK,KAAK;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,KAAa,OAAkC;AAEvD,UAAM,WAAW,KAAK,SAAS,IAAI,GAAG;AACtC,QAAI,UAAU;AACZ,WAAK,uBAAuB,KAAK,SAAS,IAAI;AAC9C,WAAK,SAAS,OAAO,GAAG;AAAA,IAC1B,WAAW,KAAK,SAAS,QAAQ,KAAK,aAAa;AAEjD,YAAM,aAAa,KAAK,SAAS,KAAK,EAAE,KAAK;AAC7C,UAAI,CAAC,WAAW,MAAM;AACpB,cAAM,YAAY,WAAW;AAC7B,cAAM,cAAc,KAAK,SAAS,IAAI,SAAS;AAC/C,YAAI,aAAa;AACf,eAAK,uBAAuB,WAAW,YAAY,IAAI;AAAA,QACzD;AACA,aAAK,SAAS,OAAO,SAAS;AAAA,MAChC;AAAA,IACF;AACA,SAAK,SAAS,IAAI,KAAK,KAAK;AAC5B,eAAW,OAAO,MAAM,MAAM;AAC5B,UAAI,SAAS,KAAK,UAAU,IAAI,GAAG;AACnC,UAAI,CAAC,QAAQ;AACX,iBAAS,oBAAI,IAAI;AACjB,aAAK,UAAU,IAAI,KAAK,MAAM;AAAA,MAChC;AACA,aAAO,IAAI,GAAG;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAA+B;AAC1C,UAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AACnC,QAAI,CAAC,MAAO,QAAO;AACnB,SAAK,uBAAuB,KAAK,MAAM,IAAI;AAC3C,SAAK,SAAS,OAAO,GAAG;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,KAA8B;AAC9C,UAAM,SAAS,KAAK,UAAU,IAAI,GAAG;AACrC,QAAI,CAAC,UAAU,OAAO,SAAS,EAAG,QAAO;AACzC,UAAM,OAAO,CAAC,GAAG,MAAM;AACvB,eAAW,OAAO,MAAM;AACtB,YAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AACnC,UAAI,OAAO;AACT,aAAK,sBAAsB,KAAK,MAAM,MAAM,GAAG;AAAA,MACjD;AACA,WAAK,SAAS,OAAO,GAAG;AAAA,IAC1B;AACA,SAAK,UAAU,OAAO,GAAG;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAwB;AAC5B,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,SAAS,MAAM;AACpB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,OAAO,KAAK,QAAgD;AAC1D,eAAW,OAAO,KAAK,SAAS,KAAK,GAAG;AACtC,UAAI,UAAU,CAAC,IAAI,WAAW,MAAM,EAAG;AACvC,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,uBAAuB,KAAa,MAAsB;AACxD,eAAW,OAAO,MAAM;AACtB,YAAM,SAAS,KAAK,UAAU,IAAI,GAAG;AACrC,UAAI,CAAC,OAAQ;AACb,aAAO,OAAO,GAAG;AACjB,UAAI,OAAO,SAAS,EAAG,MAAK,UAAU,OAAO,GAAG;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,sBAAsB,KAAa,MAAgB,SAAuB;AACxE,eAAW,YAAY,MAAM;AAC3B,UAAI,aAAa,QAAS;AAC1B,YAAM,cAAc,KAAK,UAAU,IAAI,QAAQ;AAC/C,UAAI,CAAC,YAAa;AAClB,kBAAY,OAAO,GAAG;AACtB,UAAI,YAAY,SAAS,EAAG,MAAK,UAAU,OAAO,QAAQ;AAAA,IAC5D;AAAA,EACF;AACF;;;AChHA,IAAI;AAMG,SAAS,gBACd,QACA,QAA6C,CAAC,GACjC;AACb,MAAI,SAAS;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,UACJ,OAAO,YAAY,WACf,IAAI,qBAAqB,EAAE,YAAY,OAAO,WAAW,CAAC,IAC1D,OAAO;AACb,YAAU,kBAAkB;AAAA,IAC1B,SAAS;AAAA,IACT,UAAU,OAAO;AAAA,IACjB,SAAS,MAAM;AAAA,EACjB,CAAC;AACD,SAAO;AACT;AAOO,SAAS,iBAA8B;AAC5C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,oBAA0B;AACxC,YAAU;AACZ;;;ACtDA,eAAsB,cACpB,KACA,MAC2B;AAC3B,MAAI,MAAM,WAAW,UAAa,KAAK,SAAS,GAAG;AACjD,IAAAC;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,EAAE,MAAM,IAAI,aAAa,CAAC,GAAG,GAAG,eAAe;AACrD,MAAI,MAAM,WAAW,EAAG,QAAO,EAAE,SAAS,EAAE;AAC5C,QAAM,SAAS,eAAe;AAC9B,QAAM,UAAU,MAAM,OAAO,cAAc,MAAM,CAAC,CAAC;AACnD,SAAO,EAAE,QAAQ;AACnB;AAOA,eAAsB,UAAU,KAAwC;AACtE,QAAM,EAAE,MAAM,IAAI,aAAa,CAAC,GAAG,GAAG,WAAW;AACjD,MAAI,MAAM,WAAW,EAAG,QAAO,EAAE,SAAS,EAAE;AAC5C,QAAM,SAAS,eAAe;AAC9B,QAAM,UAAU,MAAM,OAAO,cAAc,MAAM,CAAC,CAAC;AACnD,SAAO,EAAE,QAAQ;AACnB;AAMA,eAAsB,eACpB,MACA,MAC2B;AAC3B,MAAI,MAAM,WAAW,UAAa,KAAK,SAAS,GAAG;AACjD,IAAAA;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAS,eAAe;AAC9B,QAAM,UAAU,MAAM,OAAO,eAAe,MAAM,MAAM,IAAI;AAC5D,SAAO,EAAE,QAAQ;AACnB;AAEA,IAAM,aAAa,oBAAI,IAAY;AACnC,SAASA,UAAS,KAAa,SAAuB;AACpD,MAAI,WAAW,IAAI,GAAG,EAAG;AACzB,aAAW,IAAI,GAAG;AAClB,UAAQ,KAAK,OAAO;AACtB;;;ACpEA,OAAO,eAAe;AAuBf,SAAS,kBAAkB,OAAwC;AACxE,SAAO,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO;AAAA,IACrD,SAAS,UAAU,SAAS,EAAE,KAAK,KAAK,CAAC;AAAA,IACzC;AAAA,IACA;AAAA,EACF,EAAE;AACJ;AAKO,SAAS,iBACd,MACA,UACuB;AACvB,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,QAAQ,IAAI,EAAG,QAAO,EAAE;AAAA,EAChC;AACA,SAAO;AACT;;;ACjCA,SAAS,SAAS;AAuBlB,IAAM,mBAAmB,oBAAI,IAAI,CAAC,UAAU,SAAS,aAAa,UAAU,CAAC;AAOtE,SAAS,mBAAmB,UAAwB,QAAwC;AACjG,QAAM,QAAS,UAAmD;AAClE,MAAI,OAAO,UAAU,YAAY;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,QAAM,cAAc,OAAO,eAAe,EAAE,YAAY,CAAC,CAAC;AAE1D,SAAO,gBAAgB;AAAA,IACrB,MAAM,OAAO;AAAA,IACb,aAAa,OAAO;AAAA,IACpB;AAAA,IACA,SAAS,OAAO,UAAoC;AAClD,YAAM,MAAM,MAAM,SAAS,IAAI,KAAK;AACpC,UAAI,iBAAiB,IAAI,IAAI,MAAM,GAAG;AACpC,cAAM,IAAI;AAAA,UACR,sBAAsB,KAAK,UAAU,OAAO,IAAI,CAAC,mBAC/C,IAAI,QAAQ,IAAI,IAAI,KAAK,OAAO,EAClC,uBAAuB,IAAI,MAAM;AAAA,QACnC;AAAA,MACF;AACA,aAAO,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS,KAAK,UAAU,IAAI,MAAM;AAAA,IAChF;AAAA,EACF,CAAC;AACH;;;AC1DA,SAAS,aAAuC;AAGhD,SAAS,iBAAoC;AAC7C,SAAS,wBAAwB;AAI1B,IAAM,mBAAN,MAA+C;AAAA;AAAA,EAEnC;AAAA,EAEjB,YAAY,SAAiB,OAAiB,CAAC,GAAG,KAAc;AAC9D,SAAK,OAAO,MAAM,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,QAAQ,QAAQ,SAAS,EAAE,CAAC;AAAA,EAC9E;AAAA,EAEA,KAAK,MAAoB;AACvB,SAAK,KAAK,MAAM,MAAM,IAAI;AAAA,EAC5B;AAAA,EAEA,UAAU,QAAuC;AAC/C,SAAK,KAAK,OAAO,GAAG,QAAQ,CAAC,QAAgB;AAC3C,aAAO,IAAI,SAAS,MAAM,CAAC;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,SAAK,KAAK,KAAK;AAAA,EACjB;AACF;AAsBA,SAAS,iBAAiB,QAAqC;AAC7D,SAAO,IAAI,iBAAiB,OAAO,SAAS,OAAO,MAAM,OAAO,GAAG;AACrE;AAGO,SAAS,cAAc,QAAmC;AAC/D,MAAI,OAAO,OAAO,wBAAwB,YAAY;AACpD,UAAM,IAAI,MAAM,oGAA+F;AAAA,EACjH;AACA,QAAM,gBAAgB,OAAO,oBAAoB;AACjD,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,aAAa,OAAO;AAAA,IACpB,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,aAAa,wCAAwC,EAAE;AAAA,MAChG,UAAU,CAAC,SAAS;AAAA,IACtB;AAAA,IACA,SAAS,OAAO,UAAoD;AAClE,YAAM,UAAU,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;AACpE,YAAM,SAAS,IAAI,UAAU,cAAc,MAAM,CAAC;AAClD,aAAO,UAAU,8BAA8B,CAAC,WAAW,OAAO,oBAAoB,MAAM,CAAC;AAC7F,YAAM,SAAU,MAAM,OAAO,QAAQ,kBAAkB,EAAE,QAAQ,CAAC;AAClE,aAAO,OAAO,QAAQ;AAAA,IACxB;AAAA,EACF;AACF;;;ACxCO,SAAS,sBAAsB,QAA2C;AAC/E,MAAI,CAAC,OAAO,UAAU,OAAO,OAAO,WAAW,GAAG;AAChD,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AACA,QAAM,UAAW,OAAO,QAAmD;AAC3E,MAAI,OAAO,YAAY,YAAY;AACjC,UAAM,IAAI;AAAA,MACR,yBAAyB,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,IAExD;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,QAAQ,GAAG,OAAO,MAAM;AAC5C,QAAM,cACJ,OAAO,eAAe,0BAA0B,OAAO,MAAM;AAE/D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,QAAQ,EAAE,MAAM,UAAU,aAAa,wCAAwC;AAAA,QAC/E,iBAAiB;AAAA,UACf,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,IACrB;AAAA,IACA,SAAS,OAAO,UAAoD;AAClE,YAAM,SAAS,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AACjE,YAAM,kBACJ,OAAO,MAAM,oBAAoB,WAAW,MAAM,kBAAkB;AACtE,YAAM,SAAS,MAAM,OAAO,OAAO;AAAA,QACjC;AAAA,QACA,oBAAoB,SAAY,EAAE,gBAAgB,IAAI;AAAA,MACxD;AACA,UAAI,OAAO,cAAc,UAAa,OAAO,UAAW,QAAO,UAAU,OAAO,SAAS;AACzF,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACF;;;AC9BO,IAAM,gCAAN,cAA4C,MAAM;AAAA,EACvD,YAAYC,OAAc,QAAiB;AACzC,UAAM,SAAS,SAAS,KAAK,MAAM,KAAK;AACxC,UAAM,oBAAoBA,KAAI,8BAA8B,MAAM,EAAE;AACpE,SAAK,OAAO;AAAA,EACd;AACF;AAOO,SAAS,eAAe,QAAoC;AACjE,MAAI,OAAO,OAAO,wBAAwB,YAAY;AACpD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,aAAc,OAAO,SAAkD;AAC7E,MAAI,OAAO,eAAe,YAAY;AACpC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAmB,CAAC;AAC1B,aAAWA,SAAQ,OAAO,OAAO;AAC/B,QAAIA,MAAK,IAAI,IAAI,OAAO,SAAoC;AAC1D,YAAM,WAAW,MAAM,OAAO,oBAAoB,EAAE,MAAMA,MAAK,MAAM,KAAK,CAAC;AAC3E,UAAI,CAAC,SAAS,QAAS,OAAM,IAAI,8BAA8BA,MAAK,MAAM,SAAS,MAAM;AACzF,aAAOA,MAAK,QAAQ,IAA+B;AAAA,IACrD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,OAAO,QAAQ;AAAA,IACrB,aACE,OAAO,eACP;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,aAAa,kCAAkC,EAAE;AAAA,MACvF,UAAU,CAAC,MAAM;AAAA,IACnB;AAAA,IACA,SAAS,OAAO,UAAoD;AAClE,YAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,YAAM,SAAS,MAAM,OAAO,QAAQ,IAAI,MAAM,GAAG;AACjD,aAAO,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;AAAA,IACpE;AAAA,EACF;AACF;;;ACjGA,IAAM,eAAe;AAGd,SAAS,iBAAiB,SAA6D;AAC5F,QAAM,QAAQ,aAAa,KAAK,OAAO;AACvC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,EAAE,OAAO,mBAAmB,MAAM,CAAC,CAAC,GAAG,UAAU,mBAAmB,MAAM,CAAC,CAAC,EAAE;AACvF;AAGO,SAAS,cAAc,SAA0B;AACtD,SAAO,aAAa,KAAK,OAAO;AAClC;AAiBA,SAAS,UAAU,QAAgB,MAAc,SAA2B;AAC1E,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,EAAE,MAAM,QAAQ,EAAE,CAAC,GAAG;AAAA,IAChE;AAAA,IACA,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;AASA,eAAsB,qBACpB,SACA,SACA,QACmB;AACnB,QAAM,SAAS,iBAAiB,OAAO;AACvC,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,OAAO,OAAO,OAAO,YAAY,OAAO,QAAQ,GAAG;AACtD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,yCAAyC,OAAO,QAAQ;AAAA,IAC1D;AAAA,EACF;AACA,QAAM,SAAS,OAAO,WAAW,OAAO,QAAQ;AAGhD,QAAM,eAAe,MAAM,OAAO,QAAQ,MAAM,CAAC;AACjD,MAAI,CAAC,aAAa,IAAI;AACpB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,gCAAgC,aAAa,MAAM;AAAA,IACrD;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,QAAQ,KAAK;AAAA,EAC/B,QAAQ;AACN,WAAO,UAAU,KAAK,eAAe,4BAA4B;AAAA,EACnE;AAEA,QAAM,OAAO,UAAU,EAAE,OAAO,OAAO,OAAO,UAAU,OAAO,UAAU,QAAQ,CAAC;AAClF,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,IAAI,KAAK,CAAC,GAAG;AAAA,IAChD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;;;AC9EA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAwCA,IAAM,iCAAN,cAA6C,MAAM;AAAA,EACxD,YAAY,WAA8B;AACxC;AAAA,MACE,iCAAiC,UAAU,KAAK,IAAI,CAAC;AAAA,IAGvD;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAQO,SAAS,yBACd,KACA,QACA,OACA,OAA4B,EAAE,QAAQ,sBAAsB,GAC5B;AAChC,QAAM,WAAW,mBAAmB,KAAK,MAAM,MAAM;AACrD,QAAM,QAAQ,SAAS;AAIvB,MAAI,SAAS,MAAM,OAAO,KAAK,CAAC,MAAM,eAAe;AACnD,UAAM,IAAI,+BAA+B,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC;AAAA,EAC5D;AACA,QAAMC,WAAU,MAAM;AAItB,QAAM,OACJ,SAAS,MAAM,OAAO,KAAKA,WACvB;AAAA,IACE;AAAA,IACA,eAAe,CAAC,YAAoB,MAA6B,aAC/DA,SAAQ,EAAE,YAAY,UAAU,KAAK,CAAC;AAAA,EAC1C,IACA;AAEN,QAAM,YAAY,MAAM,aAAa,OAAO,WAAW;AAMvD,UAAQ,mBAAmB;AACzB,QAAI,SAAS,gBAAgB;AAC3B,YAAM,UAAU,MAAM,qBAAqB,SAAS,gBAAgB,SAAS,cAAc,CAAC,CAAC;AAC7F,UAAI,YAAY,OAAW,UAAS,SAAS,EAAE,SAAS,YAAY,KAAK;AAAA,IAC3E;AACA,WAAO,KAAK,OAAO,UAAU,QAAQ;AAAA,MACnC,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA,QAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH,GAAG;AACL;;;AC9GA,eAAsB,mBACpB,MACA,KACA,MACA,eAAuC,CAAC,GAChB;AACxB,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,OAAO,EAAE,MAAM,QAAQ,SAAS,cAAc;AAAA,IAChD,CAAC;AAAA,EACH;AACA,QAAM,WAAW,MAAM,iBAAiB,KAAK,MAAM,MAAM,YAAY;AACrE,QAAM,UAAmB,MAAM,SAAS,KAAK;AAC7C,SAAO,KAAK,UAAU,OAAO;AAC/B;AAcA,eAAsB,cACpB,KACA,MACA,cACA,SACe;AACf,mBAAiB,QAAQ,QAAQ,OAAO;AACtC,UAAM,MAAM,MAAM,mBAAmB,MAAM,KAAK,MAAM,YAAY;AAClE,QAAI,QAAQ,KAAM,SAAQ,MAAM,GAAG,GAAG;AAAA,CAAI;AAAA,EAC5C;AACF;;;AChEA,OAAO,eAAe;AAUf,SAAS,kBAAkB,MAAmC;AACnE,SAAO,UAAU,UAAU,IAAI;AACjC;AAKO,SAAS,oBAAoB,YAAyC;AAC3E,SAAO,UAAU,YAAY,UAAyD;AACxF;;;ACeO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC;AAAA,EACA;AAAA,EACT,YAAY,SAA4B,OAAmB;AACzD,UAAM,WAAW,OAAO,mCAAmC,MAAM,OAAO,EAAE;AAC1E,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;AAMO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EACrC;AAAA,EACT,YAAY,OAAmB;AAC7B,UAAM,2DAA2D,MAAM,OAAO,EAAE;AAChF,SAAK,OAAO;AACZ,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;AAGA,SAAS,mBAA4B;AACnC,SAAO,IAAI,QAAQ,+BAA+B,EAAE,QAAQ,OAAO,CAAC;AACtE;AAaA,eAAsB,cAGpB,QACA,QAAwB,CAAC,GACzB,KACkB;AAClB,QAAM,YAAY,mBAAmB,QAAQ,KAAK;AAClD,MAAI,CAAC,UAAU,GAAI,OAAM,IAAI,oBAAoB,UAAU,SAAS,UAAU,KAAK;AAEnF,QAAM,SAAS,MAAM,OAAO,QAAQ;AAAA,IAClC,OAAO,UAAU;AAAA,IACjB,MAAM,UAAU;AAAA,IAChB,QAAQ,UAAU;AAAA,IAClB,SAAS,iBAAiB;AAAA,IAC1B;AAAA,EACF,CAAC;AAID,QAAM,iBAAiB,OAAO;AAC9B,MAAI,mBAAmB,UAAa,EAAE,kBAAkB,WAAW;AACjE,UAAM,SAAS,eAAe,UAAU,MAAM;AAC9C,QAAI,CAAC,OAAO,QAAS,OAAM,IAAI,qBAAqB,OAAO,KAAK;AAChE,WAAO,OAAO;AAAA,EAChB;AACA,SAAO;AACT;;;AC1CO,IAAM,cAAc;AAAA;AAAA,EAEzB,gBAAgB;AAAA;AAAA,EAEhB,mBAAmB;AAAA;AAAA,EAEnB,WAAW;AACb;;;AC7BA,IAAI,OAAO,eAAe,aAAa;AACrC,QAAM,WAAW;AACjB,QAAM,IAAI;AACV,MAAI,EAAE,QAAQ,MAAM,MAAM;AACxB,MAAE,QAAQ,IAAI;AAEd,YAAQ;AAAA,MACN;AAAA,IAIF;AAAA,EACF;AACF;","names":["deriveKey","deriveKey","resolve","opts","warnOnce","tool","resolve"]}
1
+ {"version":3,"sources":["../../src/server/openapi/serve-docs.ts","../../src/cache/constants.ts","../../src/cache/validation.ts","../../src/cache/define-cached-function.ts","../../src/cache/cache-control-header.ts","../../src/cache/key-derivation.ts","../../src/cache/define-cached-route.ts","../../src/cache/cache-engine.ts","../../src/cache/in-memory-adapter.ts","../../src/cache/engine-singleton.ts","../../src/cache/revalidate.ts","../../src/cache/route-rules.ts","../../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","../../src/server/serialization.ts","../../src/server/http/in-process-caller.ts","../../src/server/http/ctx-reconciliation.ts","../../src/server/index.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename -- paths derived from build-time cwd, not user input */\n/**\n * Built-in OpenAPI docs — serves Scalar UI at /api/docs and the JSON spec\n * at /api/docs/openapi.json. Zero npm deps (Scalar loaded via CDN).\n *\n * Absorbed from @theokit/plugin-openapi (theokit-plugins sibling repo).\n * Core already emits the spec via vite-plugin/openapi-emit/ — this module\n * adds the runtime serving layer.\n *\n * Security: XSS-safe HTML escaping, CSP header for CDN host, GET-only,\n * 10MB filesize cap, path-traversal defense on specFilePath.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport interface OpenApiDocsOptions {\n /** Path to serve Scalar UI (default: '/api/docs'). */\n docsPath?: string\n /** Path to serve the JSON spec (default: '/api/docs/openapi.json'). */\n openapiJsonPath?: string\n /** Path to the spec file on disk (default: '.theokit/openapi.json'). */\n specFilePath?: string\n /** Page title (default: 'API Reference'). */\n pageTitle?: string\n /** Scalar CDN URL (default: jsdelivr). Must be HTTPS. */\n cdnUrl?: string\n}\n\nconst MAX_SPEC_BYTES = 10 * 1024 * 1024 // 10MB cap (DoS defense)\nconst DEFAULT_CDN = 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'\n\n/**\n * Creates a request handler that serves OpenAPI docs.\n * Returns `null` for non-matching requests (passthrough).\n */\nexport function createOpenApiHandler(opts: OpenApiDocsOptions = {}) {\n const docsPath = opts.docsPath ?? '/api/docs'\n const jsonPath = opts.openapiJsonPath ?? '/api/docs/openapi.json'\n const rawSpecFile = opts.specFilePath ?? '.theokit/openapi.json'\n const title = opts.pageTitle ?? 'API Reference'\n const cdn = opts.cdnUrl ?? DEFAULT_CDN\n\n // Path-traversal defense — validate the RAW input, BEFORE resolve().\n // resolve() normalizes `..` away (e.g. '../../../etc/passwd' becomes an\n // absolute path with no '..' left), so checking the resolved string is a\n // dead guard. Reject any `..` path segment in the input instead; absolute\n // paths without traversal segments stay allowed.\n if (hasDotDotSegment(rawSpecFile)) {\n throw new Error(`[theokit:openapi] specFilePath must not contain \"..\" segments: ${rawSpecFile}`)\n }\n const specFile = resolve(rawSpecFile)\n\n return (request: Request): Response | null => {\n if (request.method !== 'GET') return null\n\n const url = new URL(request.url)\n\n if (url.pathname === docsPath) {\n const cdnHost = new URL(cdn).host\n return new Response(renderScalarHtml(title, jsonPath, cdn), {\n status: 200,\n headers: {\n 'content-type': 'text/html; charset=utf-8',\n 'content-security-policy': `script-src 'self' 'unsafe-eval' ${cdnHost}; style-src 'self' 'unsafe-inline'; img-src 'self' data: ${cdnHost}; font-src 'self' data: ${cdnHost}; connect-src 'self' ${cdnHost}`,\n },\n })\n }\n\n if (url.pathname === jsonPath) {\n return serveSpecFile(specFile)\n }\n\n return null\n }\n}\n\n/** True if the raw path contains a `..` segment (POSIX `/` or Windows `\\` separator). */\nfunction hasDotDotSegment(p: string): boolean {\n return p.split(/[/\\\\]/).includes('..')\n}\n\n// ── HTML renderer ──\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n}\n\nfunction renderScalarHtml(title: string, specUrl: string, cdnUrl: string): string {\n return `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <title>${escapeHtml(title)}</title>\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n</head>\n<body>\n <script id=\"api-reference\" data-url=\"${escapeHtml(specUrl)}\"></script>\n <script src=\"${escapeHtml(cdnUrl)}\"></script>\n</body>\n</html>`\n}\n\n// ── Spec file server ──\n\nfunction serveSpecFile(filePath: string): Response {\n if (!existsSync(filePath)) {\n return jsonResponse(503, {\n error: {\n code: 'OPENAPI_NOT_EMITTED',\n message: 'OpenAPI spec not generated yet. Start the dev server and visit a route first.',\n },\n })\n }\n\n try {\n const stat = statSync(filePath)\n if (stat.size > MAX_SPEC_BYTES) {\n return jsonResponse(413, {\n error: {\n code: 'OPENAPI_TOO_LARGE',\n message: `Spec file exceeds ${MAX_SPEC_BYTES / 1024 / 1024}MB limit`,\n },\n })\n }\n\n const content = readFileSync(filePath, 'utf-8')\n return new Response(content, {\n status: 200,\n headers: { 'content-type': 'application/json', 'cache-control': 'no-cache' },\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to read OpenAPI spec file'\n return jsonResponse(500, {\n error: { code: 'OPENAPI_READ_FAILED', message },\n })\n }\n}\n\nfunction jsonResponse(status: number, body: unknown): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n","/**\n * Single source of truth for cache subsystem constants.\n * Limits mirror Next.js (NEXT_CACHE_TAG_MAX_LENGTH / NEXT_CACHE_TAG_MAX_ITEMS)\n * — see reference doc §3.2 and ADR D6 of caching-and-revalidation-plan.md.\n */\n\nexport const CACHE_TAG_MAX_LENGTH = 256\nexport const CACHE_TAG_MAX_ITEMS = 128\nexport const THEO_T_PREFIX = '_THEO_T_'\n\nexport const DEFAULT_MAX_AGE = 1\nexport const DEFAULT_SWR_MULTIPLIER = 60\n","import {\n CACHE_TAG_MAX_ITEMS,\n CACHE_TAG_MAX_LENGTH,\n DEFAULT_MAX_AGE,\n THEO_T_PREFIX,\n} from './constants.js'\n\nexport interface ValidationResult<T> {\n valid: T[]\n dropped: { value: unknown; reason: string }[]\n}\n\n/**\n * Validate an array of cache tags.\n * Drops invalid entries (type / length / reserved-prefix / overflow) with warn log.\n * NEVER throws on runtime input — caller-facing safety.\n *\n * EC-1: defensive guard for non-array input (e.g., undefined from optional chain).\n */\nexport function validateTags(tags: unknown, description: string): ValidationResult<string> {\n // EC-1 guard\n if (!Array.isArray(tags)) {\n const result: ValidationResult<string> = {\n valid: [],\n dropped: [{ value: tags, reason: `expected array, got ${typeof tags}` }],\n }\n warnDropped(result, description)\n return result\n }\n\n // Array.isArray narrows to `any[]` (TS limitation). Re-type as unknown[]\n // so each element flows through explicit type guards below.\n const tagArr: unknown[] = tags as unknown[]\n const valid: string[] = []\n const dropped: { value: unknown; reason: string }[] = []\n\n for (let i = 0; i < tagArr.length; i++) {\n if (valid.length >= CACHE_TAG_MAX_ITEMS) {\n for (let j = i; j < tagArr.length; j++) {\n dropped.push({ value: tagArr[j], reason: 'overflow (max 128 tags)' })\n }\n break\n }\n const tag: unknown = tagArr[i]\n if (typeof tag !== 'string') {\n dropped.push({ value: tag, reason: 'invalid type, must be a string' })\n continue\n }\n if (tag.length > CACHE_TAG_MAX_LENGTH) {\n dropped.push({\n value: tag,\n reason: `exceeded max length of ${CACHE_TAG_MAX_LENGTH}`,\n })\n continue\n }\n if (tag.startsWith(THEO_T_PREFIX)) {\n dropped.push({\n value: tag,\n reason: `reserved prefix \"${THEO_T_PREFIX}\"`,\n })\n continue\n }\n valid.push(tag)\n }\n\n warnDropped({ valid, dropped }, description)\n return { valid, dropped }\n}\n\n/**\n * Validate a `maxAge` value in seconds.\n * Throws on invalid input (config-time validation).\n * Returns DEFAULT_MAX_AGE when undefined.\n */\nexport function validateMaxAge(maxAge: unknown, description: string): number {\n if (maxAge === undefined) return DEFAULT_MAX_AGE\n if (typeof maxAge === 'number' && Number.isFinite(maxAge) && maxAge >= 0) {\n return maxAge\n }\n throw new Error(\n `Invalid maxAge \"${JSON.stringify(maxAge)}\" in ${description}, must be a non-negative finite number`,\n )\n}\n\n/**\n * Validate an `expire` value in seconds, optionally cross-checked against `revalidate`.\n * Throws on invalid input (config-time validation).\n */\nexport function validateExpire(\n expire: unknown,\n revalidate: number | undefined,\n description: string,\n): number | undefined {\n if (expire === undefined) return undefined\n if (typeof expire !== 'number' || !Number.isFinite(expire) || expire < 0) {\n throw new Error(\n `Invalid expire \"${JSON.stringify(expire)}\" in ${description}, must be a non-negative finite number`,\n )\n }\n if (revalidate !== undefined && expire < revalidate) {\n throw new Error(\n `Invalid expire ${expire} in ${description}, must be greater than or equal to revalidate ${revalidate}`,\n )\n }\n return expire\n}\n\nfunction warnDropped(result: ValidationResult<string>, description: string): void {\n if (result.dropped.length === 0) return\n console.warn(`[theokit:cache] ${description}: dropped ${result.dropped.length} invalid tag(s):`)\n for (const { value, reason } of result.dropped) {\n console.warn(` - ${JSON.stringify(value)}: ${reason}`)\n }\n}\n","import type { CacheEngine } from './cache-engine.js'\nimport { validateExpire, validateMaxAge, validateTags } from './validation.js'\n\nexport interface DefineCachedFunctionOptions<TArgs extends unknown[], TReturn> {\n /** Required cache namespace; appears in keys as \"fn:${name}:...\" */\n name: string\n /** seconds; defaults to DEFAULT_MAX_AGE (1) */\n maxAge?: number\n /** seconds; stale-while-revalidate window */\n swr?: number\n /** Custom key derivation from args. Default: JSON.stringify(args). */\n getKey?: (...args: TArgs) => string\n /** Static or dynamic tags. */\n tags?: string[] | ((...args: TArgs) => string[])\n /** Version stamp; bump to invalidate all entries under this name. */\n cacheVersion?: string\n /** Transform returned value before caching. */\n transform?: (raw: TReturn) => TReturn\n /** Skip cache if validate returns false (treats existing entry as miss). */\n validate?: (raw: TReturn) => boolean\n /** Called on any error in the cache pipeline. */\n onError?: (err: unknown, ctx: { args: TArgs }) => void\n}\n\nexport type CachedFunction<TArgs extends unknown[], TReturn> = ((\n ...args: TArgs\n) => Promise<TReturn>) & {\n /** Bust the cache entry for these specific args. */\n invalidate: (...args: TArgs) => Promise<void>\n}\n\n/**\n * Wrap an async function with cache semantics.\n * Returns a callable that memoizes by `(name + args)` and exposes `.invalidate(args)`.\n *\n * The engine is supplied by the caller (avoids module-level singleton coupling\n * during testing; framework wiring provides it in production).\n */\nexport function defineCachedFunction<TArgs extends unknown[], TReturn>(\n engine: CacheEngine,\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n opts: DefineCachedFunctionOptions<TArgs, TReturn>,\n): CachedFunction<TArgs, TReturn> {\n if (typeof opts.name !== 'string' || opts.name.length === 0) {\n throw new Error('defineCachedFunction: opts.name is required (non-empty string)')\n }\n const maxAge = validateMaxAge(opts.maxAge, `defineCachedFunction(${opts.name})`)\n const swr = validateExpire(opts.swr, maxAge, `defineCachedFunction(${opts.name})`)\n\n const prefix = `fn:${opts.name}`\n\n function deriveCacheKey(args: TArgs): string {\n const tail = opts.getKey ? opts.getKey(...args) : JSON.stringify(args)\n return `${prefix}:${tail}`\n }\n\n function resolveTags(args: TArgs): string[] {\n const raw = typeof opts.tags === 'function' ? opts.tags(...args) : (opts.tags ?? [])\n const { valid } = validateTags(raw, `defineCachedFunction(${opts.name})`)\n return valid\n }\n\n const wrapped = (async (...args: TArgs) => {\n const key = deriveCacheKey(args)\n const tags = resolveTags(args)\n try {\n const { value } = await engine.getOrCompute<TReturn>(key, async () => fn(...args), {\n maxAge,\n swr: swr ?? maxAge * 60,\n tags,\n cacheVersion: opts.cacheVersion,\n transform: opts.transform,\n validate: opts.validate,\n })\n return value\n } catch (err) {\n opts.onError?.(err, { args })\n throw err\n }\n }) as CachedFunction<TArgs, TReturn>\n\n wrapped.invalidate = async (...args: TArgs) => {\n const key = deriveCacheKey(args)\n await engine.invalidate(key)\n }\n\n return wrapped\n}\n","export interface CacheControlInput {\n /** seconds; 0 forces no-cache */\n maxAge: number\n /** stale-while-revalidate window in seconds; 0 or undefined omits directive */\n swr?: number\n /** emit `private,` prefix (skips shared CDN caching) */\n isPrivate?: boolean\n}\n\nconst NO_CACHE_HEADER = 'private, no-cache, no-store, max-age=0, must-revalidate'\n\n/**\n * Build a canonical Cache-Control header value.\n *\n * `maxAge === 0` always yields the strict no-cache directive regardless\n * of `swr` or `isPrivate` — defensive default.\n *\n * EC-13: pure function intentional — caller is responsible for input\n * validation (see validateMaxAge / validateExpire in validation.ts).\n */\nexport function getCacheControlHeader(input: CacheControlInput): string {\n if (input.maxAge === 0) return NO_CACHE_HEADER\n const parts: string[] = []\n if (input.isPrivate) parts.push('private')\n parts.push(`s-maxage=${input.maxAge}`)\n if (input.swr !== undefined && input.swr > 0) {\n parts.push(`stale-while-revalidate=${input.swr}`)\n }\n return parts.join(', ')\n}\n","/**\n * Default tracking/analytics query parameters excluded from cache keys.\n * Mirrors Astro's DEFAULT_EXCLUDED_PARAMS list (memory-provider.ts:117).\n * Set as exact-match (not glob) for KISS + zero-dep.\n */\nexport const DEFAULT_EXCLUDED_QUERY_PARAMS = [\n 'utm_source',\n 'utm_medium',\n 'utm_campaign',\n 'utm_term',\n 'utm_content',\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'dclid',\n 'msclkid',\n 'twclid',\n 'li_fat_id',\n 'mc_cid',\n 'mc_eid',\n '_ga',\n '_gl',\n '_hsenc',\n '_hsmi',\n '_ke',\n 'oly_anon_id',\n 'oly_enc_id',\n 'rb_clickid',\n 's_cid',\n 'vero_id',\n 'wickedid',\n 'yclid',\n '__s',\n 'ref',\n]\n\nexport interface KeyDerivationOptions {\n /** Total override — when provided, bypasses all internal logic. */\n getKey?: (req: Request) => string | Promise<string>\n /** Exact-match query param names to drop. Defaults to DEFAULT_EXCLUDED_QUERY_PARAMS. */\n excludeQuery?: string[]\n /** Whether to sort query params alphabetically. Defaults to true. */\n sortQuery?: boolean\n /** Header names whose values are appended as `\\0name=value` suffix. */\n varies?: string[]\n /** Namespace prefix (e.g., route name). */\n prefix?: string\n}\n\n/**\n * Derive a deterministic cache key from a Request.\n *\n * Default behaviour: `${prefix?}${protocol}//${lower(host)}${path}${?sortedFilteredQuery}` + Vary suffix.\n * `\\0` separator chosen because it cannot appear in URLs or HTTP header values.\n *\n * EC-6: malformed URL on getKey path is caller's responsibility.\n * EC-7: enforces getKey returns string.\n */\nexport async function deriveKey(req: Request, opts: KeyDerivationOptions = {}): Promise<string> {\n if (opts.getKey) {\n const k = await opts.getKey(req)\n if (typeof k !== 'string') {\n throw new Error(`getKey must return a string, got ${typeof k}`)\n }\n return k\n }\n\n const url = new URL(req.url)\n const queryString = buildQueryString(url, opts)\n const base = `${opts.prefix ? opts.prefix + ':' : ''}${url.protocol}//${url.hostname.toLowerCase()}${url.pathname}${queryString ? '?' + queryString : ''}`\n\n if (!opts.varies || opts.varies.length === 0) return base\n const parts: string[] = []\n for (const header of opts.varies) {\n parts.push(`${header}=${req.headers.get(header) ?? ''}`)\n }\n return base + '\\0' + parts.join('\\0')\n}\n\nfunction buildQueryString(url: URL, opts: KeyDerivationOptions): string {\n const params = new URLSearchParams(url.searchParams)\n const exclude = opts.excludeQuery ?? DEFAULT_EXCLUDED_QUERY_PARAMS\n const excludeSet = new Set(exclude)\n for (const key of [...params.keys()]) {\n if (excludeSet.has(key)) params.delete(key)\n }\n if (opts.sortQuery !== false) params.sort()\n return params.toString()\n}\n","import type { z } from 'zod'\n\nimport type { RouteConfig } from '../core/contracts/route-config.js'\n\nimport { getCacheControlHeader } from './cache-control-header.js'\nimport type { CacheEngine, CacheStatus } from './cache-engine.js'\nimport { THEO_T_PREFIX } from './constants.js'\nimport { deriveKey } from './key-derivation.js'\nimport type { CacheEntry } from './storage-adapter.js'\nimport { validateExpire, validateMaxAge, validateTags } from './validation.js'\n\n/** Default 10 MB cap per cached route entry (EC-3). */\nexport const DEFAULT_MAX_ENTRY_SIZE = 10 * 1024 * 1024\nconst VARIES_IGNORED = new Set(['cookie', 'set-cookie'])\n\nexport interface RouteCacheOptions {\n maxAge?: number\n swr?: number\n tags?: string[]\n varies?: string[]\n getKey?: (req: Request) => string | Promise<string>\n bypassWhen?: (req: Request) => boolean | Promise<boolean>\n cacheVersion?: string\n cacheErrors?: boolean\n methods?: string[]\n cacheable?: (response: Response) => boolean\n /** Max body bytes (EC-3); default DEFAULT_MAX_ENTRY_SIZE. */\n maxEntrySize?: number\n}\n\nexport interface CachedRouteConfig<\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> extends Omit<RouteConfig<TQuery, TBody, TParams, TCtx>, 'handler'> {\n cache: RouteCacheOptions\n handler: (ctx: {\n query: z.infer<TQuery>\n body: z.infer<TBody>\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n }) => unknown\n}\n\ninterface RouteCacheValue {\n body: string\n status: number\n headers: [string, string][]\n}\n\nconst setCookieWarnedRoutes = new WeakSet()\nconst variesCookieWarnedRoutes = new WeakSet()\nconst oversizedWarnedRoutes = new WeakSet()\n\n/**\n * Wrap a `RouteConfig` with cache-aware handler logic.\n *\n * Architecture: wraps the user `handler` so cache lookup happens AT\n * handler-invocation time, AFTER router middleware (auth/csrf/etc) ran.\n * This structurally satisfies EC-4 (cache-after-auth) without modifying\n * the router internals.\n *\n * Algorithm per request:\n * 1. Method check + bypassWhen + maxAge=0 → call handler raw\n * 2. Derive key (path + sortedQuery + varies, prefix by method)\n * 3. Cache lookup → HIT/STALE return cached Response\n * 4. Miss → run handler, check cacheability (Set-Cookie / status / size / SSE / streaming)\n * 5. Cacheable → write entry + return Response with X-Theo-Cache: MISS (dev)\n * 6. Not cacheable → return original Response unchanged\n *\n * Concurrent dedupe is INTENTIONALLY NOT used for routes — Response objects\n * cannot be safely shared across concurrent callers (body is single-use stream).\n * Each request that misses runs the handler independently.\n */\nexport function defineCachedRoute<\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>(\n engine: CacheEngine,\n config: CachedRouteConfig<TQuery, TBody, TParams, TCtx>,\n): RouteConfig<TQuery, TBody, TParams, TCtx, Response> {\n const { cache, handler, ...rest } = config\n\n const maxAge = validateMaxAge(cache.maxAge, 'defineCachedRoute')\n const swr = validateExpire(cache.swr, maxAge, 'defineCachedRoute')\n if (cache.cacheVersion !== undefined && cache.cacheVersion === '') {\n throw new Error('defineCachedRoute: cacheVersion must be non-empty if provided')\n }\n // EC-19: maxEntrySize validation\n const maxEntrySize = cache.maxEntrySize ?? DEFAULT_MAX_ENTRY_SIZE\n if (!Number.isFinite(maxEntrySize) || maxEntrySize < 0) {\n throw new Error(\n `Invalid maxEntrySize \"${String(cache.maxEntrySize)}\" in defineCachedRoute, must be a non-negative finite number`,\n )\n }\n const methods = new Set((cache.methods ?? ['GET', 'HEAD']).map((m) => m.toUpperCase()))\n const baseTags = validateTags(cache.tags ?? [], 'defineCachedRoute').valid\n\n // EC-2: filter cookie/set-cookie from varies + warn-once per route\n const variesRaw = cache.varies ?? []\n const variesLower = variesRaw.map((v) => v.toLowerCase())\n const hadCookieVary = variesLower.some((v) => VARIES_IGNORED.has(v))\n const safeVaries = variesLower.filter((v) => !VARIES_IGNORED.has(v))\n if (hadCookieVary && !variesCookieWarnedRoutes.has(config)) {\n variesCookieWarnedRoutes.add(config)\n console.warn(\n `[theokit:cache] defineCachedRoute: 'cookie'/'set-cookie' removed from varies — they fragment cache to zero hit rate (EC-2)`,\n )\n }\n\n const wrappedHandler = async (ctx: {\n query: z.infer<TQuery>\n body: z.infer<TBody>\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n }): Promise<Response> => {\n // TheoKit's dispatcher may pass a Node IncomingMessage (not a Web Request).\n // Normalize to a Web Request so deriveKey / bypassWhen / URL parsing work uniformly.\n const webRequest = toWebRequest(ctx.request)\n\n if (!methods.has(webRequest.method.toUpperCase())) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n if (cache.bypassWhen && (await cache.bypassWhen(webRequest))) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n if (maxAge === 0) {\n return invokeHandlerAsResponse(handler, ctx)\n }\n\n const key = await deriveKey(webRequest, {\n prefix: 'route:' + webRequest.method.toUpperCase(),\n varies: safeVaries,\n getKey: cache.getKey,\n })\n\n // ---- Cache lookup (T4.2 DRY — delegates to engine canonical) ----\n const cached = await engine.tryReadCached<RouteCacheValue>(key, {\n cacheVersion: cache.cacheVersion,\n })\n\n // T4.3 — build options bag once; pass to all helpers (≤ 4 params each).\n const routeCacheCtx: RouteCacheCtx = {\n engine,\n key,\n cache,\n routeConfig: config,\n maxEntrySize,\n maxAge,\n swr,\n baseTags,\n webRequest,\n }\n\n if (cached) {\n if (cached.status === 'hit') {\n return buildResponseFromCache(cached.value, 'hit', maxAge, swr)\n }\n // Only 'stale' remains (engine never returns 'miss' from tryReadCached).\n // Stale: schedule background refresh + return stale immediately.\n scheduleRouteRevalidate(routeCacheCtx, handler, ctx)\n return buildResponseFromCache(cached.value, 'stale', maxAge, swr)\n }\n\n // ---- Miss: run handler ----\n const response = await invokeHandlerAsResponse(handler, ctx)\n return persistAndReturn(routeCacheCtx, response)\n }\n\n return {\n ...rest,\n handler: wrappedHandler,\n }\n}\n\n// T4.2 (PV-5 DRY): tryReadCacheEntry was removed — duplicated the engine's\n// canonical tryReadCached (staleness check, version check, JSON parse,\n// clock-skew clamp). Route wrapper now delegates to `engine.tryReadCached`.\n\n/**\n * T4.3 options-bag context (PV-6 — Clean Code consensus ≤ 4 params).\n * Collapses 10/11 positional params of `persistAndReturn` and\n * `scheduleRouteRevalidate` to 2 params each (ctx + payload).\n *\n * Some fields are derived from `cache` config (EC-22 documented redundancy) —\n * the trade-off is O(1) construction per request for vastly simpler call\n * sites and safer additions of new fields without reordering args.\n */\ninterface RouteCacheCtx {\n engine: CacheEngine\n key: string\n cache: RouteCacheOptions\n routeConfig: object\n maxEntrySize: number\n maxAge: number\n swr: number | undefined\n baseTags: string[]\n webRequest: Request\n}\n\nfunction buildRouteCacheEntry(value: RouteCacheValue, ctx: RouteCacheCtx): CacheEntry {\n const pathTag = THEO_T_PREFIX + new URL(ctx.webRequest.url).pathname\n return {\n body: JSON.stringify(value),\n status: 200,\n headers: [],\n storedAt: Date.now(),\n maxAge: ctx.maxAge,\n swr: ctx.swr ?? ctx.maxAge * 60,\n tags: [...ctx.baseTags, pathTag],\n cacheVersion: ctx.cache.cacheVersion,\n }\n}\n\nasync function persistAndReturn(ctx: RouteCacheCtx, response: Response): Promise<Response> {\n const cacheableResult = await tryCacheResponse(\n response,\n ctx.cache,\n ctx.routeConfig,\n ctx.maxEntrySize,\n )\n if (!cacheableResult) {\n // Not cached — return original response unchanged\n return response\n }\n await ctx.engine.set(ctx.key, buildRouteCacheEntry(cacheableResult, ctx))\n return buildResponseFromCache(cacheableResult, 'miss', ctx.maxAge, ctx.swr)\n}\n\nfunction scheduleRouteRevalidate<THandlerCtx>(\n ctx: RouteCacheCtx,\n handler: (handlerCtx: THandlerCtx) => unknown,\n handlerCtx: THandlerCtx,\n): void {\n void (async () => {\n try {\n const response = await invokeHandlerAsResponse(handler, handlerCtx)\n const result = await tryCacheResponse(response, ctx.cache, ctx.routeConfig, ctx.maxEntrySize)\n if (!result) return\n await ctx.engine.set(ctx.key, buildRouteCacheEntry(result, ctx))\n } catch {\n // Stale entry remains; future request retries on its own stale-check\n }\n })()\n}\n\n/**\n * Type for Node.js IncomingMessage (subset we read).\n * Avoids a direct `node:http` import which would block edge runtimes.\n */\ninterface NodeLikeRequest {\n url?: string\n method?: string\n headers: Record<string, string | string[] | undefined>\n socket?: { encrypted?: boolean }\n}\n\n/**\n * Adapt either a Web Request or a Node IncomingMessage to a Web Request.\n * TheoKit's runtime dispatch may pass either depending on the adapter.\n */\n\n// Node IncomingMessage) inside one function so the call sites stay shape-blind.\nfunction toWebRequest(req: Request | NodeLikeRequest): Request {\n // Web Request fast-path\n if (typeof (req as Request).clone === 'function' && (req as Request).headers instanceof Headers) {\n return req as Request\n }\n const node = req as NodeLikeRequest\n const host = (typeof node.headers.host === 'string' ? node.headers.host : null) ?? 'localhost'\n const protocol = node.socket?.encrypted ? 'https' : 'http'\n const path = node.url ?? '/'\n const url = path.startsWith('http') ? path : `${protocol}://${host}${path}`\n const headers = new Headers()\n for (const [k, v] of Object.entries(node.headers)) {\n if (Array.isArray(v)) {\n for (const item of v) headers.append(k, item)\n } else if (typeof v === 'string') {\n headers.set(k, v)\n }\n }\n return new Request(url, {\n method: (node.method ?? 'GET').toUpperCase(),\n headers,\n })\n}\n\nasync function invokeHandlerAsResponse<TCtx>(\n handler: (ctx: TCtx) => unknown,\n ctx: TCtx,\n): Promise<Response> {\n const raw = await handler(ctx)\n if (raw instanceof Response) return raw\n return Response.json(raw)\n}\n\n/**\n * Decide whether `response` is cacheable. Returns serialized form on yes; undefined on no.\n * Order matters: cheap checks first, body read last (only for cacheable candidates).\n */\nasync function tryCacheResponse(\n response: Response,\n cache: RouteCacheOptions,\n routeConfig: object,\n maxEntrySize: number,\n): Promise<RouteCacheValue | undefined> {\n // D7 / EC-2: Set-Cookie auto-bypass\n if (response.headers.has('set-cookie')) {\n if (!setCookieWarnedRoutes.has(routeConfig)) {\n setCookieWarnedRoutes.add(routeConfig)\n console.warn('[theokit:cache] response has Set-Cookie — skipping cache write (D7)')\n }\n return undefined\n }\n // SSE\n const contentType = response.headers.get('content-type') ?? ''\n if (contentType.includes('text/event-stream')) return undefined\n // EC-11: chunked streaming (transfer-encoding: chunked OR no content-length on a\n // user-constructed Response — i.e., a Response built from a ReadableStream that\n // wasn't via Response.json/text helpers). We detect via the explicit\n // transfer-encoding header since Response.json() also uses a ReadableStream\n // body internally and we don't want to refuse those.\n if (response.headers.get('transfer-encoding')?.toLowerCase() === 'chunked') {\n return undefined\n }\n // D9: status >= 400 not cached unless opt-in\n if (response.status >= 400 && !cache.cacheErrors) return undefined\n // Custom predicate (overrides built-ins)\n if (cache.cacheable && !cache.cacheable(response)) return undefined\n\n // Read body (clone to preserve the response for downstream)\n const text = await response.clone().text()\n\n // EC-3: oversized bypass\n if (text.length > maxEntrySize) {\n if (!oversizedWarnedRoutes.has(routeConfig)) {\n oversizedWarnedRoutes.add(routeConfig)\n console.warn(\n `[theokit:cache] response body ${text.length} bytes exceeds maxEntrySize ${maxEntrySize}; skipping cache (EC-3)`,\n )\n }\n return undefined\n }\n\n const headers: [string, string][] = []\n response.headers.forEach((v, k) => {\n if (k.toLowerCase() === 'set-cookie') return // defense-in-depth\n headers.push([k, v])\n })\n return { body: text, status: response.status, headers }\n}\n\nfunction buildResponseFromCache(\n value: RouteCacheValue,\n status: CacheStatus,\n maxAge: number,\n swr: number | undefined,\n): Response {\n const headers = new Headers(value.headers)\n if (!headers.has('cache-control')) {\n headers.set('cache-control', getCacheControlHeader({ maxAge, swr: swr ?? maxAge * 60 }))\n }\n if (process.env.NODE_ENV !== 'production') {\n let cacheStatusHeader: 'HIT' | 'STALE' | 'MISS' = 'MISS'\n if (status === 'hit') cacheStatusHeader = 'HIT'\n else if (status === 'stale') cacheStatusHeader = 'STALE'\n headers.set('X-Theo-Cache', cacheStatusHeader)\n }\n return new Response(value.body, { status: value.status, headers })\n}\n","import { THEO_T_PREFIX } from './constants.js'\nimport type { CacheEntry, CacheStorageAdapter } from './storage-adapter.js'\n\nexport type CacheStatus = 'hit' | 'stale' | 'miss'\n\nexport interface CacheEngineOptions {\n storage: CacheStorageAdapter\n defaults?: {\n maxAge?: number\n swr?: number\n cacheVersion?: string\n }\n onError?: (err: unknown, ctx: { phase: 'get' | 'set' | 'revalidate'; key: string }) => void\n}\n\nexport interface GetOrComputeOptions<T> {\n maxAge: number\n swr?: number\n tags?: string[]\n cacheVersion?: string\n transform?: (raw: T) => T\n validate?: (raw: T) => boolean\n /**\n * When `true`, the value is returned but NOT written to cache.\n * Used by route middleware to bypass cache for uncacheable responses\n * (Set-Cookie, oversized body, status >= 400 with cacheErrors=false).\n */\n skipCacheWhen?: (raw: T) => boolean\n}\n\nexport interface CacheEngine {\n getOrCompute<T>(\n key: string,\n fn: () => Promise<T>,\n opts: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus }>\n\n /**\n * Public canonical cache read (T4.2 of architecture-review-remediation-plan,\n * PV-5 DRY consolidation). Returns the parsed value + status (`hit` | `stale`)\n * for callers that DON'T want to bind a loader function (e.g., HTTP route\n * middleware that may want to bypass on miss instead of running a loader).\n *\n * Returns undefined when:\n * - Entry not present in storage\n * - `opts.cacheVersion` mismatch with entry\n * - Body is not a JSON string (parse failed)\n * - `opts.validate` returns false (or throws — caller's onError invoked)\n * - Entry is fully expired (past maxAge + swr)\n */\n tryReadCached<T>(\n key: string,\n opts: { cacheVersion?: string; validate?: (v: T) => boolean },\n ): Promise<{ value: T; status: 'hit' | 'stale' } | undefined>\n\n set(key: string, entry: CacheEntry): Promise<void>\n invalidate(key: string): Promise<boolean>\n invalidateTag(tag: string): Promise<number>\n revalidatePath(path: string, type?: 'layout' | 'page'): Promise<number>\n\n /** Storage adapter passthrough (read-only access for diagnostics). */\n readonly storage: CacheStorageAdapter\n}\n\n/**\n * Build a cache engine wrapping a storage adapter.\n *\n * Implements:\n * - SWR (fresh / stale / expired branching) — Astro `memory-provider.ts:423`-style.\n * - In-flight dedupe via `Map<key, Promise>` — Next.js `pendingRevalidates` pattern.\n * - Tag-based invalidation via adapter's deleteByTag.\n * - Path-as-tag encoding (revalidatePath sugar) — Next.js `revalidate.ts:105`.\n *\n * EC-8: Math.max(0, age) guards clock skew.\n * EC-9: validate callback wrapped in try/catch.\n * EC-10: loader returning undefined skips cache write + warns once.\n *\n * NOTE on max-lines-per-function disable below: createCacheEngine is a factory\n * closure that owns the in-flight/bg/warned maps. Splitting would force the\n * helpers across modules and re-introduce the shared mutable state through\n * parameter lists.\n */\n// eslint-disable-next-line max-lines-per-function\nexport function createCacheEngine(opts: CacheEngineOptions): CacheEngine {\n const { storage, onError } = opts\n const inFlight = new Map<string, Promise<unknown>>()\n const bgInFlight = new Set<string>()\n const undefinedLoaderWarned = new Set<string>()\n\n async function getOrCompute<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus }> {\n // Dedupe: concurrent first-miss shares the loader promise\n const pending = inFlight.get(key)\n if (pending) {\n const value = (await pending) as T\n return { value, status: 'miss' }\n }\n\n // maxAge=0 → always miss, never cache\n if (options.maxAge === 0) {\n return claimAndRun(key, fn, options, /* skipWrite */ true)\n }\n\n // Atomically claim the in-flight slot BEFORE any await (dedupe race fix).\n return claimAndRun(key, fn, options, false)\n }\n\n /**\n * Claims the in-flight slot synchronously, then performs the get/loader work\n * inside. Concurrent callers awaiting the same key share this slot.\n */\n function claimAndRun<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n skipWrite: boolean,\n ): Promise<{ value: T; status: CacheStatus }> {\n let resolveOuter!: (v: T) => void\n let rejectOuter!: (e: unknown) => void\n const outerPromise = new Promise<T>((resolve, reject) => {\n resolveOuter = resolve\n rejectOuter = reject\n })\n // Prevent unhandled-rejection when no concurrent awaiter exists\n void outerPromise.catch(() => {\n /* swallow — the leader handles via work promise */\n })\n inFlight.set(key, outerPromise)\n\n const work = (async (): Promise<{ value: T; status: CacheStatus }> => {\n try {\n if (!skipWrite) {\n const cached = await tryReadCached<T>(key, options)\n if (cached) {\n // HIT or STALE — value already resolved\n resolveOuter(cached.value)\n if (cached.status === 'stale') {\n scheduleBackgroundRevalidate(key, fn, options)\n }\n return cached\n }\n }\n // Miss path: run loader\n const value = await runLoader(key, fn, options, skipWrite)\n resolveOuter(value)\n return { value, status: 'miss' as const }\n } catch (err) {\n rejectOuter(err)\n throw err\n } finally {\n inFlight.delete(key)\n }\n })()\n\n return work\n }\n\n // One inline staleness machine; each guard (version check, parse, validate,\n // age, swr window) is one short branch. Extracting per-step would dilute,\n // not clarify.\n // eslint-disable-next-line complexity\n async function tryReadCached<T>(\n key: string,\n options: GetOrComputeOptions<T>,\n ): Promise<{ value: T; status: CacheStatus } | undefined> {\n let entry: CacheEntry | undefined\n try {\n entry = await storage.get(key)\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n if (!entry) return undefined\n if (options.cacheVersion !== undefined && entry.cacheVersion !== options.cacheVersion) {\n return undefined\n }\n if (typeof entry.body !== 'string') return undefined\n let parsed: T\n try {\n parsed = JSON.parse(entry.body) as T\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n // EC-9: validate wrapped in try/catch\n if (options.validate) {\n try {\n if (!options.validate(parsed)) return undefined\n } catch (err) {\n onError?.(err, { phase: 'get', key })\n return undefined\n }\n }\n // EC-8: clamp age to non-negative (clock skew)\n const age = Math.max(0, (Date.now() - entry.storedAt) / 1000)\n if (age <= entry.maxAge) {\n const value = options.transform ? options.transform(parsed) : parsed\n return { value, status: 'hit' }\n }\n if (age <= entry.maxAge + entry.swr) {\n const value = options.transform ? options.transform(parsed) : parsed\n return { value, status: 'stale' }\n }\n return undefined\n }\n\n // runLoader always returns `value` by design: loader output is the caller's\n // contract; every branch short-circuits a *write*, never the return path.\n // eslint-disable-next-line sonarjs/no-invariant-returns, complexity\n async function runLoader<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n skipWrite = false,\n ): Promise<T> {\n const raw = await fn()\n const value = options.transform ? options.transform(raw) : raw\n\n if (skipWrite) return value\n\n // skipCacheWhen sentinel — caller-controlled skip-write\n if (options.skipCacheWhen?.(value)) return value\n\n // EC-9: validate during write\n if (options.validate) {\n let isValid = true\n try {\n isValid = options.validate(value)\n } catch (err) {\n onError?.(err, { phase: 'set', key })\n return value\n }\n if (!isValid) return value\n }\n\n // EC-10: undefined return → warn-once + skip cache\n if (value === undefined) {\n if (!undefinedLoaderWarned.has(key)) {\n undefinedLoaderWarned.add(key)\n console.warn(`[theokit:cache] loader returned undefined for key \"${key}\"; entry not cached`)\n }\n return value\n }\n\n try {\n const entry: CacheEntry = {\n body: JSON.stringify(value),\n status: 200,\n headers: [],\n storedAt: Date.now(),\n maxAge: options.maxAge,\n swr: options.swr ?? 0,\n tags: options.tags ?? [],\n cacheVersion: options.cacheVersion,\n }\n await storage.set(key, entry)\n } catch (err) {\n onError?.(err, { phase: 'set', key })\n }\n return value\n }\n\n function scheduleBackgroundRevalidate<T>(\n key: string,\n fn: () => Promise<T>,\n options: GetOrComputeOptions<T>,\n ): void {\n if (bgInFlight.has(key)) return\n bgInFlight.add(key)\n void runLoader(key, fn, options)\n .catch((err: unknown) => {\n onError?.(err, { phase: 'revalidate', key })\n })\n .finally(() => {\n bgInFlight.delete(key)\n })\n }\n\n return {\n storage,\n\n getOrCompute,\n\n async tryReadCached<T>(\n key: string,\n opts: { cacheVersion?: string; validate?: (v: T) => boolean },\n ): Promise<{ value: T; status: 'hit' | 'stale' } | undefined> {\n // Delegate to internal impl (which uses the broader GetOrComputeOptions\n // type). tryReadCached never returns status: 'miss' — that codepath\n // returns undefined. Narrow the type via assertion.\n const result = await tryReadCached<T>(key, {\n ...opts,\n maxAge: 0, // unused by tryReadCached\n })\n if (!result) return undefined\n return result as { value: T; status: 'hit' | 'stale' }\n },\n\n async set(key, entry) {\n await storage.set(key, entry)\n },\n\n async invalidate(key) {\n // Best-effort: clear in-flight too so next request starts fresh\n inFlight.delete(key)\n return storage.delete(key)\n },\n\n async invalidateTag(tag) {\n return storage.deleteByTag(tag)\n },\n\n async revalidatePath(path, type) {\n const tag = THEO_T_PREFIX + path + (type ? '/' + type : '')\n return storage.deleteByTag(tag)\n },\n }\n}\n","import type { CacheEntry, CacheStorageAdapter } from './storage-adapter.js'\n\nexport interface InMemoryCacheAdapterOptions {\n /** Maximum number of entries before LRU eviction. Default 1000. */\n maxEntries?: number\n}\n\n/**\n * In-memory cache adapter with LRU eviction + reverse tag index.\n *\n * Uses Map insertion-order for O(1) LRU (Astro LRUMap pattern).\n * Reverse index `tagIndex: Map<tag, Set<key>>` makes deleteByTag O(matched-keys).\n *\n * Invariants:\n * - `entries.size <= maxEntries` post-set.\n * - `tagIndex[tag].has(key)` ↔ `entries.get(key)?.tags.includes(tag)`.\n *\n * eslint-disable @typescript-eslint/require-await — the CacheStorageAdapter\n * interface is intentionally async so Redis/file/external adapters fit. The\n * in-memory variant returns immediately but keeps the async signature to\n * satisfy the contract.\n */\n/* eslint-disable @typescript-eslint/require-await */\nexport class InMemoryCacheAdapter implements CacheStorageAdapter {\n readonly name = 'memory'\n readonly #entries = new Map<string, CacheEntry>()\n readonly #tagIndex = new Map<string, Set<string>>()\n readonly #maxEntries: number\n\n constructor(opts: InMemoryCacheAdapterOptions = {}) {\n this.#maxEntries = opts.maxEntries ?? 1000\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = this.#entries.get(key)\n if (entry === undefined) return undefined\n // LRU bump\n this.#entries.delete(key)\n this.#entries.set(key, entry)\n return entry\n }\n\n async set(key: string, entry: CacheEntry): Promise<void> {\n // Overwrite case: clean old tags first\n const existing = this.#entries.get(key)\n if (existing) {\n this.#removeKeyFromTagIndex(key, existing.tags)\n this.#entries.delete(key)\n } else if (this.#entries.size >= this.#maxEntries) {\n // LRU eviction\n const oldestIter = this.#entries.keys().next()\n if (!oldestIter.done) {\n const oldestKey = oldestIter.value\n const oldestEntry = this.#entries.get(oldestKey)\n if (oldestEntry) {\n this.#removeKeyFromTagIndex(oldestKey, oldestEntry.tags)\n }\n this.#entries.delete(oldestKey)\n }\n }\n this.#entries.set(key, entry)\n for (const tag of entry.tags) {\n let bucket = this.#tagIndex.get(tag)\n if (!bucket) {\n bucket = new Set()\n this.#tagIndex.set(tag, bucket)\n }\n bucket.add(key)\n }\n }\n\n async delete(key: string): Promise<boolean> {\n const entry = this.#entries.get(key)\n if (!entry) return false\n this.#removeKeyFromTagIndex(key, entry.tags)\n this.#entries.delete(key)\n return true\n }\n\n async deleteByTag(tag: string): Promise<number> {\n const bucket = this.#tagIndex.get(tag)\n if (!bucket || bucket.size === 0) return 0\n const keys = [...bucket]\n for (const key of keys) {\n const entry = this.#entries.get(key)\n if (entry) {\n this.#unindexFromOtherTags(key, entry.tags, tag)\n }\n this.#entries.delete(key)\n }\n this.#tagIndex.delete(tag)\n return keys.length\n }\n\n async size(): Promise<number> {\n return this.#entries.size\n }\n\n async clear(): Promise<void> {\n this.#entries.clear()\n this.#tagIndex.clear()\n }\n\n async *keys(prefix?: string): AsyncIterableIterator<string> {\n for (const key of this.#entries.keys()) {\n if (prefix && !key.startsWith(prefix)) continue\n yield key\n }\n }\n\n #removeKeyFromTagIndex(key: string, tags: string[]): void {\n for (const tag of tags) {\n const bucket = this.#tagIndex.get(tag)\n if (!bucket) continue\n bucket.delete(key)\n if (bucket.size === 0) this.#tagIndex.delete(tag)\n }\n }\n\n #unindexFromOtherTags(key: string, tags: string[], skipTag: string): void {\n for (const otherTag of tags) {\n if (otherTag === skipTag) continue\n const otherBucket = this.#tagIndex.get(otherTag)\n if (!otherBucket) continue\n otherBucket.delete(key)\n if (otherBucket.size === 0) this.#tagIndex.delete(otherTag)\n }\n }\n}\n","import type { CacheEngine, CacheEngineOptions } from './cache-engine.js'\nimport { createCacheEngine } from './cache-engine.js'\nimport { InMemoryCacheAdapter } from './in-memory-adapter.js'\nimport type { CacheStorageAdapter } from './storage-adapter.js'\n\nexport interface NormalizedCacheConfig {\n enabled: boolean\n storage: 'memory' | CacheStorageAdapter\n maxEntries: number\n defaults: {\n maxAge: number\n swr?: number\n cacheErrors: boolean\n }\n}\n\nlet _engine: CacheEngine | undefined\n\n/**\n * Initialize the singleton cache engine for this process.\n * Throws if called twice; tests should call `_resetCacheEngine()` between.\n */\nexport function initCacheEngine(\n config: NormalizedCacheConfig,\n hooks: Pick<CacheEngineOptions, 'onError'> = {},\n): CacheEngine {\n if (_engine) {\n throw new Error(\n 'Cache engine already initialized — call _resetCacheEngine() in tests, or check init order in production.',\n )\n }\n if (!config.enabled) {\n throw new Error(\n 'initCacheEngine: config.enabled is false. Skip this call entirely when cache is disabled.',\n )\n }\n const adapter =\n config.storage === 'memory'\n ? new InMemoryCacheAdapter({ maxEntries: config.maxEntries })\n : config.storage\n _engine = createCacheEngine({\n storage: adapter,\n defaults: config.defaults,\n onError: hooks.onError,\n })\n return _engine\n}\n\n/**\n * Resolve the singleton cache engine.\n * Throws a clear error if not initialized — usually means the framework\n * bootstrap missed calling initCacheEngine, or cache.enabled is false.\n */\nexport function getCacheEngine(): CacheEngine {\n if (!_engine) {\n throw new Error(\n 'Cache engine not initialized. Ensure theo.config.ts has `cache.enabled: true` and the framework bootstrap called initCacheEngine.',\n )\n }\n return _engine\n}\n\n/**\n * Test-only: clear the singleton so the next test can re-init.\n * Production code MUST NOT call this.\n */\nexport function _resetCacheEngine(): void {\n _engine = undefined\n}\n","import { getCacheEngine } from './engine-singleton.js'\nimport { validateTags } from './validation.js'\n\nexport interface RevalidateResult {\n deleted: number\n}\n\n/**\n * Invalidate all cache entries carrying the given tag.\n * Safe to call from any context (route handler, action, webhook).\n *\n * `opts.expire` accepted for API compatibility with Next.js; at MVP we delete\n * immediately (no SWR-with-expire semantics). A non-zero value emits one warn.\n */\nexport async function revalidateTag(\n tag: string,\n opts?: { expire?: number },\n): Promise<RevalidateResult> {\n if (opts?.expire !== undefined && opts.expire > 0) {\n warnOnce(\n 'revalidateTag-expire',\n '[theokit:cache] revalidateTag opts.expire is accepted but not honored at MVP (entries are deleted immediately).',\n )\n }\n const { valid } = validateTags([tag], 'revalidateTag')\n if (valid.length === 0) return { deleted: 0 }\n const engine = getCacheEngine()\n const deleted = await engine.invalidateTag(valid[0])\n return { deleted }\n}\n\n/**\n * Immediate invalidation (no SWR), Server-Action-safe.\n * Same semantics as revalidateTag at MVP; kept as separate name for\n * call-site clarity (\"I want fresh data NOW\").\n */\nexport async function updateTag(tag: string): Promise<RevalidateResult> {\n const { valid } = validateTags([tag], 'updateTag')\n if (valid.length === 0) return { deleted: 0 }\n const engine = getCacheEngine()\n const deleted = await engine.invalidateTag(valid[0])\n return { deleted }\n}\n\n/**\n * Invalidate cached entries for a route path.\n * Sugar over `revalidateTag('_THEO_T_/${path}/${type?}')`.\n */\nexport async function revalidatePath(\n path: string,\n opts?: { type?: 'layout' | 'page'; expire?: number },\n): Promise<RevalidateResult> {\n if (opts?.expire !== undefined && opts.expire > 0) {\n warnOnce(\n 'revalidatePath-expire',\n '[theokit:cache] revalidatePath opts.expire is accepted but not honored at MVP.',\n )\n }\n const engine = getCacheEngine()\n const deleted = await engine.revalidatePath(path, opts?.type)\n return { deleted }\n}\n\nconst warnedKeys = new Set<string>()\nfunction warnOnce(key: string, message: string): void {\n if (warnedKeys.has(key)) return\n warnedKeys.add(key)\n console.warn(message)\n}\n","import picomatch from 'picomatch'\n\nexport interface RouteRule {\n maxAge?: number\n swr?: number\n tags?: string[]\n}\n\nexport type RouteRules = Record<string, RouteRule>\n\nexport interface CompiledRouteRule {\n matcher: (path: string) => boolean\n rule: RouteRule\n /** Original glob pattern (for debugging). */\n pattern: string\n}\n\n/**\n * Compile route-rule glob patterns into matcher functions.\n * First-match-wins semantics (preserves insertion order).\n *\n * EC-5: picomatch is a direct production dependency (see plan T7.2).\n */\nexport function compileRouteRules(rules: RouteRules): CompiledRouteRule[] {\n return Object.entries(rules).map(([pattern, rule]) => ({\n matcher: picomatch(pattern, { dot: true }),\n rule,\n pattern,\n }))\n}\n\n/**\n * Resolve the first matching rule for `path`, or `undefined` if none match.\n */\nexport function resolveRouteRule(\n path: string,\n compiled: CompiledRouteRule[],\n): RouteRule | undefined {\n for (const c of compiled) {\n if (c.matcher(path)) return c.rule\n }\n return undefined\n}\n","/**\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","import superjson from 'superjson'\n\nexport interface SerializedResponse {\n json: unknown\n meta?: unknown\n}\n\n/**\n * Serialize data using superjson for rich type support (Date, Map, Set, BigInt, etc.)\n */\nexport function serializeResponse(data: unknown): SerializedResponse {\n return superjson.serialize(data)\n}\n\n/**\n * Deserialize data that was serialized with superjson.\n */\nexport function deserializeResponse(serialized: SerializedResponse): unknown {\n return superjson.deserialize(serialized as Parameters<typeof superjson.deserialize>[0])\n}\n","/**\n * M33 Phase 1 — `callProcedure`, the in-process typed caller.\n *\n * The load-bearing seam for non-HTTP surfaces (TUI / Tauri / MCP-tools): invoke a route's shared\n * logic with STRUCTURED input, WITHOUT going through the HTTP transport (no URL/body parsing, no\n * middleware chain, no Response). It reuses the SAME Zod validation pipeline as the HTTP path\n * (`validateRouteInput`) so there is no drift, and reuses the SAME `config.response` server-fault\n * check. Failures throw typed errors (there is no HTTP status off-web).\n *\n * Prior art: tRPC `callProcedure` / `createCallerFactory`\n * (`.claude/knowledge-base/references/trpc/packages/server/src/unstable-core-do-not-import/router.ts:401,441`).\n *\n * Design (ADR-0044 / blueprint §5.4): the AUTHOR passes structured input `{query?, body?, params?}`\n * — never synthesizes a Request. A minimal in-process `Request` is provided to the handler ONLY so\n * handlers that read `request.headers`/`request.url` still work (opencode's proven pattern); the\n * input itself is NOT parsed from it.\n */\nimport type { z } from 'zod'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport {\n validateRouteInput,\n type RawRouteInput,\n type RouteInputChannel,\n} from './validate-route-input.js'\n\n/** Structured input for an in-process procedure call — one object per declared channel. */\nexport type ProcedureInput = RawRouteInput\n\n/**\n * Thrown when structured input fails the route's Zod validation. The in-process analog of the HTTP\n * 400 — carries the failing channel + the Zod issues (typed error, not a magic value; Rule 8).\n */\nexport class ProcedureInputError extends Error {\n readonly channel: RouteInputChannel\n readonly issues: z.core.$ZodIssue[]\n constructor(channel: RouteInputChannel, error: z.ZodError) {\n super(`Invalid ${channel} for in-process procedure call: ${error.message}`)\n this.name = 'ProcedureInputError'\n this.channel = channel\n this.issues = error.issues\n }\n}\n\n/**\n * Thrown when the handler's plain-object return drifts from `config.response` — a SERVER fault\n * (the handler violated its own declared contract), mirroring the HTTP path's 500 as a throw.\n */\nexport class ProcedureOutputError extends Error {\n readonly issues: z.core.$ZodIssue[]\n constructor(error: z.ZodError) {\n super(`In-process procedure output failed its response schema: ${error.message}`)\n this.name = 'ProcedureOutputError'\n this.issues = error.issues\n }\n}\n\n/** A minimal, stable in-process Request for handlers that read `request.*`. Never parsed for input. */\nfunction inProcessRequest(): Request {\n return new Request('theo://in-process/procedure', { method: 'POST' })\n}\n\n/**\n * Invoke a route/procedure's handler in-process with structured, Zod-validated input.\n *\n * @param config the `RouteConfig` (what `route().build()` produces).\n * @param input structured `{query?, body?, params?}` — validated by the route's schemas.\n * @param ctx the typed run-context the handler receives (built by the CALLER — a TUI/Tauri/MCP\n * surface supplies its own ctx factory; there is no HTTP middleware chain here).\n * @returns the handler's result (validated against `config.response` when declared).\n * @throws ProcedureInputError on invalid structured input (the off-web analog of a 400).\n * @throws ProcedureOutputError on a handler output that drifts from `config.response` (server fault).\n */\nexport async function callProcedure(\n // Accept ANY RouteConfig regardless of its per-channel schema generics — a caller passes a concrete\n // `route().body(z.object(...)).build()` whose generics differ from the `ZodUndefined` defaults.\n config: RouteConfig<z.ZodType, z.ZodType, z.ZodType>,\n input: ProcedureInput = {},\n ctx?: unknown,\n): Promise<unknown> {\n const validated = validateRouteInput(config, input)\n if (!validated.ok) throw new ProcedureInputError(validated.channel, validated.error)\n\n const result = await config.handler({\n query: validated.query,\n body: validated.body,\n params: validated.params,\n request: inProcessRequest(),\n ctx: ctx,\n })\n\n // Server-fault response validation (parity with the HTTP path) — only for plain values, and only\n // when a response schema is declared. `Response` instances are pass-through (unusual off-web).\n const responseSchema = config.response\n if (responseSchema !== undefined && !(result instanceof Response)) {\n const parsed = responseSchema.safeParse(result)\n if (!parsed.success) throw new ProcedureOutputError(parsed.error)\n return parsed.data\n }\n return result\n}\n","/**\n * M33 Phase 1 — the ctx reconciliation contract (ADR-0044 D4 / blueprint §5.2, §8.5).\n *\n * ## The problem the deep research verified against our own code\n *\n * At runtime (`execute.ts:122-165`) the handler's `ctx` is written by THREE sources, not one:\n *\n * 1. **the user `context.ts` factory** — via `runMiddlewareAndContext` (`execute.ts:131`). This is\n * the ONLY writer the author controls + declares a shape for. **This is the typed surface.**\n * 2. **plugin decorations** — `pluginRunner.applyDecorations(ctx)` (`execute.ts:124,136`). Plugins\n * add arbitrary keys (`decorateRequest`) whose types the route author does not see.\n * 3. **the jobs backend** — `ctx.queue` injected when `jobs.backend` is configured (`execute.ts:141-150`).\n *\n * A naive \"infer `TCtx` from everything on `ctx`\" would LIE — it cannot see writers (2) and (3), so\n * `ctx.queue` / plugin keys would be typed as present when they are not (or vice-versa). That is the\n * exact Hono/global-augmentation failure the blueprint refuted (§8.5). oRPC/tRPC avoid it only\n * because middleware is their SOLE ctx writer; TheoKit is multi-writer.\n *\n * ## The reconciliation (what this contract locks)\n *\n * The typed `TCtx` a route handler sees reflects **only writer (1)** — the user `context.ts` factory\n * (`ContextValue` below). Writers (2) and (3) are **explicitly untyped** on the route surface:\n *\n * - `ctx.queue` (jobs) is reached through the dedicated {@link JobsAugmentedCtx} helper, NOT the\n * inferred `TCtx` — a handler that needs the queue opts into the augmented type explicitly.\n * - plugin-decorated keys are `unknown` by design (a plugin is a cross-cutting, per-app concern;\n * typing them into every route's `TCtx` would couple routes to plugin internals — G5).\n *\n * This keeps the LOCKED 5-arity `RouteConfig` generic (`route-config-generic-arity.test.ts`, GAP-4)\n * intact — `TCtx` stays the single typed ctx slot; we only define WHICH writer it corresponds to,\n * so `runtime ⊇ type` holds honestly (the type is a sound subset of the runtime ctx, never a lie).\n *\n * Type-tests proving this live in `tests/ctx-reconciliation.test-d.ts`.\n */\n\n/**\n * The typed run-context a route handler sees = the return of the user `context.ts` factory.\n * `TValue` is inferred from that factory at the web adapter seam; it EXCLUDES plugin decorations and\n * `ctx.queue` (those are not part of the author-declared shape).\n */\nexport type ContextValue<TValue extends Record<string, unknown> = Record<string, unknown>> = TValue\n\n/** The `ctx.queue` client shape injected by the jobs backend (writer 3). Reached explicitly. */\nexport interface QueueClientLike {\n enqueue(name: string, input: unknown): void | Promise<void>\n}\n\n/**\n * Opt-in augmentation for handlers that read `ctx.queue`. A route that uses the jobs queue annotates\n * its ctx as `JobsAugmentedCtx<MyCtx>` — making the jobs dependency explicit in the type, instead of\n * silently assuming `ctx.queue` exists on every route (which would lie when `jobs.backend` is unset).\n */\nexport type JobsAugmentedCtx<TValue extends Record<string, unknown> = Record<string, unknown>> =\n TValue & { queue: QueueClientLike }\n\n/**\n * The three runtime ctx writers, named for documentation + the type-test. This is the reconciliation\n * artifact the plan requires as a deliverable (not a footnote).\n */\nexport const CTX_WRITERS = {\n /** Writer 1 — user `context.ts` factory. THE typed surface (`TCtx`). execute.ts:131 */\n contextFactory: 'context.ts',\n /** Writer 2 — plugin `decorateRequest`. Untyped on the route surface. execute.ts:124,136 */\n pluginDecorations: 'pluginRunner.applyDecorations',\n /** Writer 3 — jobs backend `ctx.queue`. Reached via JobsAugmentedCtx, not TCtx. execute.ts:141-150 */\n jobsQueue: 'jobBackend',\n} as const\n","/**\n * theokit/server — DEPRECATED umbrella barrel.\n *\n * **Per plan theokit-arch-gaps-implementation T2.5 (M1) + EC-2:**\n *\n * Importing from `theokit/server` is DEPRECATED as of this release. The\n * 16 sub-domain exports (auth, jobs, http, security, observability, etc.)\n * are now individually addressable via `package.json#exports`:\n *\n * import { defineAuth } from 'theokit/server/auth'\n * import { defineJob } from 'theokit/server/jobs'\n * import { defineRoute, defineAction } from 'theokit/server/define'\n * // ...etc per `packages/theo/package.json` exports field\n *\n * This umbrella barrel will continue to work for ONE minor cycle\n * (0.x → 0.x+1) with a single runtime warning printed on first import.\n * Final removal in 0.x+2 per CHANGELOG.\n *\n * Why: `export *` wildcards across 16 sub-domains violate ISP at the\n * package-surface level (consumers pay for 376 transitive exports when\n * they wanted 6). See `architecture-output/consolidated_final_report.md`\n * M1 finding + blueprint Q4 D4 (Hono-shape exports field adoption).\n *\n * Migration codemod (provided in this release):\n * pnpm exec theokit migrate server-umbrella-to-subpaths\n *\n * For body-parser, serialization, transformer, webhook helpers, trace context\n * propagation, error pages, plugin types, and config/env helpers — re-exported\n * inline because they don't fit a single sub-barrel cleanly. Those will land\n * in a `theokit/server/runtime` sub-path in the 0.x+2 cleanup.\n */\n\n// One-time deprecation warning. Fires on first import in the process and\n// is silenced afterwards via a module-scoped flag. Tree-shake-safe: the\n// IIFE body executes on module load (no DCE), but the cost is one\n// console.warn at startup — negligible. Apps that grep for this string\n// see exactly which entry point logged it.\nif (typeof globalThis !== 'undefined') {\n const WARN_KEY = '__theokit_server_umbrella_warn_emitted__'\n const g = globalThis as Record<string, unknown>\n if (g[WARN_KEY] !== true) {\n g[WARN_KEY] = true\n\n console.warn(\n '[theokit] umbrella import \"theokit/server\" is DEPRECATED. ' +\n 'Use sub-paths (theokit/server/<domain>): auth, jobs, http, security, ' +\n 'observability, etc. See packages/theo/package.json#exports for the ' +\n 'full list. Removal scheduled for 0.x+2.',\n )\n }\n}\n\n// Core defines + low-level pipeline primitives (used by adapter templates)\nexport * from './define/index.js'\nexport * from './http/index.js'\nexport * from './scan/index.js'\n\n// G3 action protocol: ActionError + ActionInputError + helpers, re-exported\n// from core/contracts for consumer ergonomics (`from 'theokit/server'`).\nexport {\n ActionError,\n ActionInputError,\n extractUniversalIssues,\n isActionError,\n isInputError,\n type ActionErrorCode,\n type ActionManifestEntry,\n type ActionResult,\n type SerializedActionResult,\n type UniversalZodIssue,\n} from '../core/contracts/action-protocol.js'\n\n// Subdomain sub-barrels (consumers can also import direct: theokit/server/<sub>)\n// (server/agent had only the proprietary surface — removed in the M3 clean break;\n// its survivors mount-agent/provider-resolver/configure-agent-registry are internal.)\nexport * from './auth/index.js'\nexport * from './cost/index.js'\nexport * from './cron/index.js'\nexport * from './jobs/index.js'\nexport * from './observability/index.js'\nexport * from './plugins/index.js'\nexport * from './rate-limit/index.js'\nexport * from './realtime/index.js'\nexport * from './security/index.js'\nexport * from './storage/index.js'\nexport * from './webhook/index.js'\nexport * from './openapi/index.js'\n\n// Cross-module: cache lives at packages/theo/src/cache/ (not server/cache)\nexport * from '../cache/index.js'\n\n// Agent-tool adapters — wrap an external runtime (coding agent, SDK workflow) as a `CustomTool`.\n// M26 — SDK `Workflow` as a tool (thin adapter; the engine is the SDK's). M17 — coding agent (ACP).\nexport { createWorkflowTool } from './agent/workflow-tool.js'\nexport type { WorkflowLike, WorkflowToolConfig } from './agent/workflow-tool.js'\nexport { createACPTool, NodeAcpTransport } from './agent/acp-tool.js'\nexport type { AcpToolConfig } from './agent/acp-tool.js'\n// M28 — third-party agent SDK (Claude/OpenAI/Cursor) as a tool (vendor runtime stays theirs).\nexport { createVendorAgentTool } from './agent/vendor-agent-tool.js'\nexport type { VendorAgentClient, VendorAgentToolConfig } from './agent/vendor-agent-tool.js'\n// M29 — code-mode sandbox: agent composes tools in code run inside an INJECTED isolation boundary.\nexport { createCodeMode, CodeModePermissionDeniedError } from './agent/code-mode.js'\nexport type { Sandbox, CodeModeApi, CodeModeConfig, CodeModePermission } from './agent/code-mode.js'\n// M27 — channel webhook routes (Slack/Telegram/Discord) with per-platform signature validation.\nexport { handleChannelWebhook, parseChannelPath, isChannelPath } from './agent/channel-webhook.js'\nexport type { ChannelMessage, ChannelWebhookConfig } from './agent/channel-webhook.js'\n// M35 — in-process agent-turn seam (Model A): the Ink TUI / Tauri drive an agent turn in ONE process\n// (no HTTP loopback, no port, no CSRF), reusing streamAgentUIMessages with inline HITL resolution.\nexport {\n streamAgentTurnInProcess,\n InProcessApprovalRequiredError,\n} from './agent/stream-agent-turn-in-process.js'\nexport type {\n StreamAgentTurnInProcessInput,\n StreamAgentTurnDeps,\n InProcessApprovalRequest,\n InProcessAwaitApproval,\n} from './agent/stream-agent-turn-in-process.js'\n// M30 — MCP App `ui://` HTML resources served by the MCP server (rendered in a sandboxed iframe).\n// MCP stdio transport — expose an agent as a stdio MCP server (sibling of the HTTP route).\nexport { serveMcpStdio, handleMcpStdioLine, type StdioStreams } from './agent/mcp-stdio.js'\nexport {\n defineAppResource,\n buildResourceDescriptors,\n readAppResource,\n extractAppResources,\n} from './agent/mcp-app-resources.js'\nexport type {\n AppResource,\n AppResourceInput,\n McpResourceDescriptor,\n McpResourceContents,\n} from './agent/mcp-app-resources.js'\n\n// Inline re-exports — items that don't belong to a single sub-barrel\nexport { parseRequestBody, FileTooLargeError } from './body-parser.js'\nexport type { UploadedFile, ParsedBody, BodyParserOptions } from './body-parser.js'\n\nexport { serializeResponse, deserializeResponse } from './serialization.js'\nexport type { SerializedResponse } from './serialization.js'\n\nexport { superjsonTransformer, jsonTransformer, resolveTransformer } from './transformer.js'\nexport type { TheoTransformer } from './transformer.js'\n\n// T5a.2 Phase A — Web-Standards entry-point (R3a per ADR-0028). Accepts\n// a native Web Request and returns a native Web Response. Narrow scope:\n// method dispatch + Zod validation + envelope-shaped errors. Plugin\n// runner / CSRF / CORS / middleware integration deferred to Phase B-G\n// per docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md.\nexport { executeWebRequest } from './web-handler.js'\n\n// M33 — the in-process typed caller (the seam TUI/Tauri/MCP surfaces use to invoke route logic\n// WITHOUT synthesizing an HTTP Request). Shares the one Zod validation pipeline with the HTTP path.\nexport {\n callProcedure,\n ProcedureInputError,\n ProcedureOutputError,\n type ProcedureInput,\n} from './http/in-process-caller.js'\nexport {\n validateRouteInput,\n type RouteInputSchemas,\n type RouteInputChannel,\n type RouteInputValidation,\n type RawRouteInput,\n} from './http/validate-route-input.js'\nexport {\n type ContextValue,\n type JobsAugmentedCtx,\n type QueueClientLike,\n CTX_WRITERS,\n} from './http/ctx-reconciliation.js'\n\n// Plugin types (used by definePlugin + extension authors)\nexport type {\n TheoPlugin,\n TheoApp,\n PluginContext,\n PluginErrorContext,\n HookName,\n HookResult,\n OnRequestHook,\n PreHandlerHook,\n OnResponseHook,\n OnErrorHook,\n RunHookOptions,\n} from './plugin-types.js'\n// M31 builder-only: `plugin()` is the public authoring surface; `definePlugin`/`defineTheoPlugin`\n// are now internal (the plugin() builder's `.build()` delegates to them via source path).\n\n// Config helpers — auto-load .env for standalone server scripts (Telegram bots,\n// queue consumers, cron jobs) that bypass the CLI.\nexport { loadEnv, _resetEnvCache } from '../config/load-env.js'\nexport type { LoadEnvOptions, LoadEnvResult } from '../config/load-env-types.js'\n\n// Wave 2 — Polyglot services orchestration types (types only — runtime in services/)\nexport type {\n ServiceDefinition,\n ServicesConfig,\n ServicesConfigInput,\n ServicesConfigOutput,\n} from '../services/index.js'\n"],"mappings":"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","names":["deriveKey","deriveKey","resolve","opts","warnOnce","tool","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theokit",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "Apache-2.0",