theokit 0.1.0-alpha.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions-virtual-module-E6PU47GV.js +175 -0
- package/dist/actions-virtual-module-E6PU47GV.js.map +1 -0
- package/dist/actions-virtual-module-E7IELVHL.js +174 -0
- package/dist/actions-virtual-module-E7IELVHL.js.map +1 -0
- package/dist/add-2ZFFGGE4.js +0 -0
- package/dist/app-typed-client-4L4L4BWD.js +289 -0
- package/dist/app-typed-client-4L4L4BWD.js.map +1 -0
- package/dist/app-typed-client-6PAT6VOL.js +289 -0
- package/dist/app-typed-client-6PAT6VOL.js.map +1 -0
- package/dist/aws-lambda-PONVF3UX.js +0 -0
- package/dist/broadcast-QOQGUNNK.js +0 -0
- package/dist/{build-IQQYCA3B.js → build-EWZDEDT3.js} +37 -11
- package/dist/build-EWZDEDT3.js.map +1 -0
- package/dist/build-request-body-preview-EOP2Y4F3.js +52 -0
- package/dist/build-request-body-preview-EOP2Y4F3.js.map +1 -0
- package/dist/build-request-body-preview-II2235E6.js +54 -0
- package/dist/build-request-body-preview-II2235E6.js.map +1 -0
- package/dist/bun-DITMZMKL.js +0 -0
- package/dist/check-PZR67OY5.js +0 -0
- package/dist/{chunk-GQSTRXXB.js → chunk-2BQYEBCK.js} +77 -68
- package/dist/chunk-2BQYEBCK.js.map +1 -0
- package/dist/{chunk-FRBYJANT.js → chunk-4W447H7M.js} +195 -41
- package/dist/chunk-4W447H7M.js.map +1 -0
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/chunk-7DHGV77J.js +140 -0
- package/dist/chunk-7DHGV77J.js.map +1 -0
- package/dist/{chunk-WQCPKA2L.js → chunk-C27AZN46.js} +570 -165
- package/dist/chunk-C27AZN46.js.map +1 -0
- package/dist/chunk-ERAZNHHR.js +73 -0
- package/dist/chunk-ERAZNHHR.js.map +1 -0
- package/dist/chunk-F3TG5FJV.js +97 -0
- package/dist/chunk-F3TG5FJV.js.map +1 -0
- package/dist/chunk-KJVEJILQ.js +109 -0
- package/dist/chunk-KJVEJILQ.js.map +1 -0
- package/dist/chunk-KT3MWNZG.js +0 -0
- package/dist/{chunk-MCP6Y5BA.js → chunk-M23FP2AS.js} +25 -1
- package/dist/chunk-M23FP2AS.js.map +1 -0
- package/dist/{chunk-S3JBIFKS.js → chunk-MG7H3LAW.js} +2 -2
- package/dist/chunk-MOT42NAH.js +165 -0
- package/dist/chunk-MOT42NAH.js.map +1 -0
- package/dist/chunk-O7335ZGH.js +0 -0
- package/dist/{chunk-OEB3OIYP.js → chunk-OJHO2X7C.js} +497 -168
- package/dist/chunk-OJHO2X7C.js.map +1 -0
- package/dist/chunk-QLGES2HC.js +189 -0
- package/dist/chunk-QLGES2HC.js.map +1 -0
- package/dist/{chunk-JZ5WEG3S.js → chunk-SEVYARIU.js} +9 -5
- package/dist/chunk-SEVYARIU.js.map +1 -0
- package/dist/{chunk-ZK5JCE5J.js → chunk-TFECHXR5.js} +201 -43
- package/dist/chunk-TFECHXR5.js.map +1 -0
- package/dist/chunk-WSJKACWB.js +17 -0
- package/dist/chunk-WSJKACWB.js.map +1 -0
- package/dist/chunk-WZ7CPVQB.js +0 -0
- package/dist/chunk-XMS5VRIK.js +0 -0
- package/dist/chunk-Y5KE6YFP.js +0 -0
- package/dist/{chunk-3Q36SEDK.js → chunk-ZBWROIIO.js} +43 -2
- package/dist/{chunk-3Q36SEDK.js.map → chunk-ZBWROIIO.js.map} +1 -1
- package/dist/chunk-ZOXNJV2O.js +358 -0
- package/dist/chunk-ZOXNJV2O.js.map +1 -0
- package/dist/cli/index.js +22 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.d.ts +31 -1
- package/dist/client/index.js +100 -0
- package/dist/client/index.js.map +1 -1
- package/dist/cloudflare-RBANU3SE.js +0 -0
- package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
- package/dist/deno-deploy-J7LI6HNL.js +0 -0
- package/dist/{dev-VN6WS3CM.js → dev-74KPI5C5.js} +15 -7
- package/dist/dev-74KPI5C5.js.map +1 -0
- package/dist/dev-emit-3CHM73TV.js +390 -0
- package/dist/dev-emit-3CHM73TV.js.map +1 -0
- package/dist/dev-emit-I3CKOHML.js +44 -0
- package/dist/dev-emit-I3CKOHML.js.map +1 -0
- package/dist/devtools/entry.js +653 -243
- package/dist/devtools/entry.js.map +1 -1
- package/dist/dispatcher-AQJGI3HU.js +8 -0
- package/dist/dispatcher-E6QV32BO.js +83 -0
- package/dist/dispatcher-E6QV32BO.js.map +1 -0
- package/dist/{dist-UZV7J3YI.js → dist-R2Q7GVDW.js} +10412 -11961
- package/dist/dist-R2Q7GVDW.js.map +1 -0
- package/dist/docker-EZDA5FT7.js +0 -0
- package/dist/{generate-SIO4JSKJ.js → generate-DT4IIAHF.js} +88 -22
- package/dist/generate-DT4IIAHF.js.map +1 -0
- package/dist/index.d.ts +108 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/{info-B3UOXFUF.js → info-VM7EK4JC.js} +3 -3
- package/dist/lib-NST3PNZX.js +0 -0
- package/dist/netlify-IFY6ZGFV.js +0 -0
- package/dist/node-KWZI3CKV.js +0 -0
- package/dist/openapi-CBASKC7W.js +84 -0
- package/dist/openapi-CBASKC7W.js.map +1 -0
- package/dist/proper-lockfile-MVKMQGFK.js +0 -0
- package/dist/{registry-BB3UYAOG.js → registry-QGSNLJKJ.js} +2 -2
- package/dist/{routes-CAGFZKUK.js → routes-7O4NUDYS.js} +9 -7
- package/dist/{routes-CAGFZKUK.js.map → routes-7O4NUDYS.js.map} +1 -1
- package/dist/scan-C2BOKLSY.js +0 -0
- package/dist/{schema-Cxq2qqwh.d.ts → schema-CjVly9c_.d.ts} +43 -1
- package/dist/{schema-MVB2FVK6.js → schema-JAKF23GR.js} +2 -2
- package/dist/server/cost/index.d.ts +7 -0
- package/dist/server/cost/index.js +1 -1
- package/dist/server/index.d.ts +219 -47
- package/dist/server/index.js +101 -114
- package/dist/server/index.js.map +1 -1
- package/dist/services-typed-client-ZX5JUHH3.js +0 -0
- package/dist/sqlite-vec-54KB4RD3.js +0 -0
- package/dist/{start-CSLJQXV3.js → start-5JTFWF4T.js} +20 -14
- package/dist/start-5JTFWF4T.js.map +1 -0
- package/dist/{static-BH6JQNM2.js → static-6PZZBY7G.js} +4 -4
- package/dist/storage-manager-D5KBXXKB.js +0 -0
- package/dist/theo-cloud-3K4DGB3S.js +0 -0
- package/dist/{upgrade-readiness-OHL36FQL.js → upgrade-readiness-Q46KTG2J.js} +6 -1
- package/dist/upgrade-readiness-Q46KTG2J.js.map +1 -0
- package/dist/vercel-RHADE5IP.js +0 -0
- package/dist/vite-plugin/index.d.ts +25 -1
- package/dist/vite-plugin/index.js +5 -2
- package/dist/{vite-plugin-WA3G45YY.js → vite-plugin-3EQP2JYM.js} +7 -6
- package/dist/vite-plugin-3EQP2JYM.js.map +1 -0
- package/package.json +10 -8
- package/LICENSE +0 -201
- package/dist/build-IQQYCA3B.js.map +0 -1
- package/dist/chunk-FRBYJANT.js.map +0 -1
- package/dist/chunk-GQSTRXXB.js.map +0 -1
- package/dist/chunk-JZ5WEG3S.js.map +0 -1
- package/dist/chunk-MCP6Y5BA.js.map +0 -1
- package/dist/chunk-OEB3OIYP.js.map +0 -1
- package/dist/chunk-WQCPKA2L.js.map +0 -1
- package/dist/chunk-ZK5JCE5J.js.map +0 -1
- package/dist/dev-VN6WS3CM.js.map +0 -1
- package/dist/dist-UZV7J3YI.js.map +0 -1
- package/dist/generate-SIO4JSKJ.js.map +0 -1
- package/dist/start-CSLJQXV3.js.map +0 -1
- package/dist/upgrade-readiness-OHL36FQL.js.map +0 -1
- /package/dist/{chunk-S3JBIFKS.js.map → chunk-MG7H3LAW.js.map} +0 -0
- /package/dist/{schema-MVB2FVK6.js.map → dispatcher-AQJGI3HU.js.map} +0 -0
- /package/dist/{info-B3UOXFUF.js.map → info-VM7EK4JC.js.map} +0 -0
- /package/dist/{registry-BB3UYAOG.js.map → registry-QGSNLJKJ.js.map} +0 -0
- /package/dist/{vite-plugin-WA3G45YY.js.map → schema-JAKF23GR.js.map} +0 -0
- /package/dist/{static-BH6JQNM2.js.map → static-6PZZBY7G.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vite-plugin/index.ts","../src/devtools/server-side/route-manifest.ts","../src/router/entry-server.ts","../src/router/entry.ts","../src/router/generate.ts","../src/router/scan.ts","../src/router/types.ts","../src/vite-plugin/action-middleware.ts","../src/vite-plugin/api-middleware.ts","../src/config/load-config.ts","../src/config/errors.ts","../src/config/schema.ts","../src/vite-plugin/theoui-detect.ts","../src/vite-plugin/config-resolve.ts","../src/vite-plugin/inject-devtools.ts","../src/vite-plugin/inject-entry-client.ts","../src/vite-plugin/inject-stylesheets.ts","../src/vite-plugin/integrate-ui.ts","../src/vite-plugin/auto-detect.ts","../src/vite-plugin/resolve-theo-root.ts","../src/vite-plugin/ssr-dev-middleware.ts","../src/vite-plugin/ws-upgrade.ts","../src/vite-plugin/integrations.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Vite plugin entry. Reads `package.json` + checks for ts vs js source\n * layout under `theoSrcDir` (build-time literal). No HTTP input.\n */\nimport { existsSync } from 'node:fs'\nimport { resolve, basename, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport type { Plugin } from 'vite'\n\nimport { broadcastRouteManifest } from '../devtools/server-side/route-manifest.js'\nimport { generateEntryServer } from '../router/entry-server.js'\nimport { generateEntryClient } from '../router/entry.js'\nimport { generateRouteManifest } from '../router/generate.js'\nimport { scanRoutes } from '../router/scan.js'\nimport { isRouteFile } from '../router/types.js'\nimport type { CorsConfig } from '../server/http/cors.js'\nimport type { AuditLogger } from '../server/observability/audit-log.js'\nimport type { PluginRunner } from '../server/plugins/plugin-runner.js'\nimport type { RateLimitConfig } from '../server/rate-limit/rate-limit.js'\nimport type { DisallowedConfig } from '../server/security/csrf.js'\nimport type { SecurityHeadersConfig } from '../server/security/security-headers.js'\nimport type { TheoTransformer } from '../server/transformer.js'\nimport { buildServicesProxyConfig, type ServicesConfig } from '../services/index.js'\n\nimport { createActionMiddleware } from './action-middleware.js'\nimport { createApiMiddleware } from './api-middleware.js'\n// T2.1-T2.3 (architecture-medium-deferrals) — sibling extractions.\nimport { resolvePluginConfig } from './config-resolve.js'\nimport {\n DEVTOOLS_RESOLVED_ID,\n DEVTOOLS_VIRTUAL_ID,\n injectDevtoolsScript,\n} from './inject-devtools.js'\nimport { injectEntryClient } from './inject-entry-client.js'\nimport { injectStylesheets } from './inject-stylesheets.js'\nimport { integrateUseTheoUI } from './integrate-ui.js'\nimport { resolveTheoRootDir } from './resolve-theo-root.js'\nimport { setupSsrDevMiddleware } from './ssr-dev-middleware.js'\nimport type { TheoUiDetectResult } from './theoui-detect.js'\nimport { setupWsUpgrade } from './ws-upgrade.js'\n\nexport {\n defineTheoIntegration,\n createIntegrationRegistry,\n IntegrationRouteCollisionError,\n IntegrationVirtualModulePrefixError,\n} from './integrations.js'\nexport type {\n TheoIntegration,\n HookName as IntegrationHookName,\n Hook as IntegrationHook,\n HookContext as IntegrationHookContext,\n IntegrationRegistry,\n IntegrationRegistryOptions,\n IntegrationRoute,\n RouteHandler as IntegrationRouteHandler,\n} from './integrations.js'\n\nconst VIRTUAL_ENTRY_ID = '/@theo/entry-client'\nconst RESOLVED_ENTRY_ID = '\\0@theo/entry-client'\nconst VIRTUAL_MANIFEST_ID = '/@theo/route-manifest'\nconst RESOLVED_MANIFEST_ID = '\\0@theo/route-manifest'\nconst VIRTUAL_ENTRY_SERVER_ID = '/@theo/entry-server'\nconst RESOLVED_ENTRY_SERVER_ID = '\\0@theo/entry-server'\nconst VIRTUAL_RUNTIME_CONFIG_ID = '/@theo/runtime-config'\nconst RESOLVED_RUNTIME_CONFIG_ID = '\\0@theo/runtime-config'\n\nexport interface TheoPluginOptions {\n root?: string\n rateLimit?: RateLimitConfig\n ssr?: boolean\n ssrStreaming?: boolean\n /**\n * Wave 2 (T3.1) — polyglot services config. When passed, the\n * services-typed-client plugin is wired and generates `clients/<name>.ts`\n * per service with an OpenAPI URL. Empty `{}` → no-op.\n */\n services?: ServicesConfig\n}\n\n/**\n * T3.3 — Find a consumer-side config file (`tailwind.config.*`, `postcss.config.*`)\n * by walking from projectRoot up to 3 levels. Returns the absolute path on the\n * first hit, or `undefined`. Used to defer to consumer's manual config (D3).\n */\nfunction findConsumerConfig(projectRoot: string, basename: string): string | undefined {\n const extensions = ['.ts', '.js', '.mjs', '.cjs']\n let dir = projectRoot\n for (let level = 0; level < 3; level++) {\n for (const ext of extensions) {\n const candidate = resolve(dir, `${basename}${ext}`)\n if (existsSync(candidate)) return candidate\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return undefined\n}\n\n/**\n * Async factory companion. Returns `[theoPlugin, ...autoChainedPlugins]`.\n *\n * Why this exists alongside the sync `theoPlugin()` factory: Vite does NOT\n * reliably merge plugins returned from a child plugin's `config()` hook\n * (verified empirically 2026-05-23 — plugins were silently dropped from\n * the resolved chain despite being returned correctly). The canonical\n * Vite pattern for plugin-from-plugin is to return `Plugin[]` from the\n * plugin factory itself, which Vite flattens into the consumer's\n * `plugins` array.\n *\n * Consumers should prefer `await theoPluginAsync(...)` over `theoPlugin(...)`\n * when they want @usetheo/ui + @tailwindcss/vite auto-chaining. The sync\n * factory remains for backward compatibility and tests.\n */\nexport async function theoPluginAsync(\n rootOrOptions?: string | TheoPluginOptions,\n): Promise<Plugin[]> {\n const options =\n typeof rootOrOptions === 'string' ? { root: rootOrOptions } : (rootOrOptions ?? {})\n const projectRoot = options.root ?? process.cwd()\n\n const consumerTailwindConfig = findConsumerConfig(projectRoot, 'tailwind.config')\n const consumerPostcssConfig = findConsumerConfig(projectRoot, 'postcss.config')\n const uiPlugins = await integrateUseTheoUI(projectRoot, {\n consumerTailwindConfig,\n consumerPostcssConfig,\n })\n\n // Wave 2 (T3.1) — typed-client plugin wired only when services declared.\n // Empty `services: {}` (default) → plugin is a no-op (no fetch fired).\n const servicesPlugins: Plugin[] = []\n if (options.services && Object.keys(options.services).length > 0) {\n const { servicesTypedClientPlugin } = await import('./services-typed-client.js')\n servicesPlugins.push(\n servicesTypedClientPlugin({\n cwd: projectRoot,\n services: options.services,\n }),\n )\n }\n\n return [theoPlugin(rootOrOptions), ...uiPlugins, ...servicesPlugins]\n}\n\n// eslint-disable-next-line max-lines-per-function -- Vite plugin factory: state setup + hooks live together by Vite convention\nexport function theoPlugin(rootOrOptions?: string | TheoPluginOptions): Plugin {\n const options =\n typeof rootOrOptions === 'string' ? { root: rootOrOptions } : (rootOrOptions ?? {})\n const projectRoot = options.root ?? process.cwd()\n const appDir = resolve(projectRoot, 'app')\n const ssrEnabled = options.ssr ?? false\n\n // Resolve paths for SSR module loading. Pure helper extracted for T1.3\n // regression test — see resolve-theo-root.ts for branch documentation.\n const currentDir = dirname(fileURLToPath(import.meta.url))\n const theoSrcDir = resolveTheoRootDir(currentDir)\n\n // EC-1: plugin runner cached in module closure. Instantiated in configResolved\n // (non-HMR-able). theo.config.ts edits during dev emit a warn but do NOT\n // re-instantiate — user must restart dev server for plugin changes.\n let pluginRunner: PluginRunner | undefined\n let transformer: TheoTransformer | undefined\n let resolvedBatching: { max?: number } | undefined\n let theoUi: TheoUiDetectResult | undefined\n let csrfMode: 'off' | 'warn' | 'strict' = 'strict'\n let securityHeaders: SecurityHeadersConfig | undefined\n let disallowed: DisallowedConfig | undefined\n // T1.2 — CORS config resolved from theo.config.ts; passed to api-middleware.\n let cors: CorsConfig | undefined\n // T4.1 — Audit logger from theo.config.ts.audit.logger\n let auditLogger: AuditLogger | undefined\n // T1.2 — devtools opt-out. `false` skips injection; anything else enables (dev only).\n let devtoolsEnabled = true\n // Dev mode flag set in configureServer. transformIndexHtml runs in both\n // dev and build; we only want to inject during dev.\n let isDevMode = false\n let configLoadedOnce = false\n\n return {\n name: 'theo',\n\n async configResolved() {\n // T2.1 (architecture-medium-deferrals, ADR D2) — config-load logic\n // extracted to `config-resolve.ts`. This hook owns only the one-shot\n // semantic and the closure-variable assignment.\n if (configLoadedOnce) return\n configLoadedOnce = true\n const resolved = await resolvePluginConfig(projectRoot)\n pluginRunner = resolved.pluginRunner\n transformer = resolved.transformer\n resolvedBatching = resolved.resolvedBatching\n theoUi = resolved.theoUi\n csrfMode = resolved.csrfMode\n securityHeaders = resolved.securityHeaders\n disallowed = resolved.disallowed\n cors = resolved.cors\n auditLogger = resolved.auditLogger\n devtoolsEnabled = resolved.devtoolsEnabled\n },\n\n // Vite calls this hook (sync return is fine — no awaits left after\n // the auto-chain moved to theoPluginAsync). The @usetheo/ui +\n // @tailwindcss/vite auto-chain lives in `theoPluginAsync` because\n // Vite drops plugins returned from a child plugin's config() hook.\n config() {\n // Detect whether we're running from source (.ts) or compiled dist (.js)\n const ext = existsSync(resolve(theoSrcDir, 'index.ts')) ? '.ts' : '.js'\n\n // Perf: pre-bundle heavy deps at server startup (not on first request).\n // Without this, a cold `pnpm dev` takes ~10s before serving `/` because\n // Vite discovers @usetheo/ui mid-request and stops to bundle it.\n // Measured 2026-05-22: cold first GET / = 10s → ~1s with includes wired.\n // See https://vite.dev/guide/dep-pre-bundling — \"lazy dependency\n // discovery\" is the canonical mitigation.\n const optimizeDepsInclude: string[] = []\n if (existsSync(resolve(projectRoot, 'node_modules', '@usetheo', 'ui'))) {\n optimizeDepsInclude.push('@usetheo/ui')\n }\n if (existsSync(resolve(projectRoot, 'node_modules', 'lucide-react'))) {\n optimizeDepsInclude.push('lucide-react')\n }\n\n // Perf: warm up the app's critical-path files so Vite transforms them\n // before the browser asks. Cuts the visible LCP when these files\n // import heavy barrels (TheoUI).\n const warmupClientFiles: string[] = []\n for (const candidate of ['app/layout.tsx', 'app/page.tsx', 'app/page.jsx']) {\n const full = resolve(projectRoot, candidate)\n if (existsSync(full)) warmupClientFiles.push(`./${candidate}`)\n }\n\n // Wave 2 completion T1.1 — translate `services: {}` into Vite proxy.\n // Empty services → empty record → Vite proxy unaffected.\n const servicesProxy =\n options.services && Object.keys(options.services).length > 0\n ? buildServicesProxyConfig(options.services)\n : undefined\n\n return {\n envPrefix: 'THEO_PUBLIC_',\n optimizeDeps: optimizeDepsInclude.length > 0 ? { include: optimizeDepsInclude } : undefined,\n server: {\n ...(warmupClientFiles.length > 0 ? { warmup: { clientFiles: warmupClientFiles } } : {}),\n ...(servicesProxy !== undefined ? { proxy: servicesProxy } : {}),\n // Skip watching gitignored heavy dirs to avoid hitting ENOSPC\n // (inotify watcher exhaustion). `referencias/` are deep-research\n // clones; `.theokit/` is per-conversation cache; `.theo/` is\n // build output. None should trigger HMR.\n watch: {\n ignored: [\n '**/referencias/**',\n '**/.theokit/**',\n '**/.theo/**',\n '**/dist/**',\n '**/node_modules/**',\n ],\n },\n },\n resolve: {\n alias: [\n // Order matters: most-specific first so `theokit/X` doesn't\n // get matched by the bare `theokit` alias.\n { find: 'theokit/server', replacement: resolve(theoSrcDir, `server/index${ext}`) },\n { find: 'theokit/client', replacement: resolve(theoSrcDir, `client/index${ext}`) },\n {\n find: 'theokit/react-query',\n replacement: resolve(theoSrcDir, `react-query/index${ext}`),\n },\n {\n find: 'theokit/vite-plugin',\n replacement: resolve(theoSrcDir, `vite-plugin/index${ext}`),\n },\n {\n find: 'theokit/adapters/web-shim',\n replacement: resolve(theoSrcDir, `adapters/web-shim${ext}`),\n },\n {\n find: 'theokit/adapters/ws-shim',\n replacement: resolve(theoSrcDir, `adapters/ws-shim${ext}`),\n },\n // T1.2 — devtools entry (DEV only; tree-shaken in build because\n // the script tag is never injected by inject-devtools.ts in build mode)\n {\n find: 'theokit/devtools/entry',\n replacement: resolve(theoSrcDir, `devtools/entry${ext === '.ts' ? '.tsx' : '.js'}`),\n },\n { find: 'theokit', replacement: resolve(theoSrcDir, `index${ext}`) },\n ],\n },\n }\n },\n\n // Auto-inject the entry-client `<script>` into every served HTML\n // (Phase 2 of nextjs-maturity plan). Runs BEFORE Vite's own\n // transform so the injection lands inside <body>, not after\n // Vite-injected content. Idempotent: if the user already wrote\n // the script tag, the HTML is returned unchanged.\n transformIndexHtml: {\n order: 'pre' as const,\n handler(html: string): string {\n // 1. entry-client (always)\n const entry = injectEntryClient(html)\n if (entry.warning) console.warn(entry.warning)\n let next = entry.html\n\n // 2. devtools (dev only, respecting config.devtools = false)\n const devtools = injectDevtoolsScript(next, {\n isDev: isDevMode,\n enabled: devtoolsEnabled,\n })\n if (devtools.warning) console.warn(devtools.warning)\n next = devtools.html\n\n // 3. Stylesheet link (dev only) — fixes LCP. Without the\n // <link rel=\"stylesheet\">, CSS only loads after the JS bundle\n // executes `import 'styles.css'`, causing FOUC + LCP > 9s.\n // Production builds rely on Vite's SSR bundle for the\n // correctly-hashed <link>. Font preload was tried + reverted\n // (see inject-stylesheets.ts comment); CLS was hydration\n // mismatch, not font swap.\n const styles = injectStylesheets(next, {\n isDev: isDevMode,\n hasPackage: (name) =>\n existsSync(resolve(projectRoot, 'node_modules', ...name.split('/'))),\n })\n next = styles.html\n\n return next\n },\n },\n\n resolveId(id: string) {\n if (id === VIRTUAL_ENTRY_ID) return RESOLVED_ENTRY_ID\n if (id === VIRTUAL_MANIFEST_ID) return RESOLVED_MANIFEST_ID\n if (id === VIRTUAL_ENTRY_SERVER_ID) return RESOLVED_ENTRY_SERVER_ID\n if (id === VIRTUAL_RUNTIME_CONFIG_ID) return RESOLVED_RUNTIME_CONFIG_ID\n // T1.2 — devtools virtual module. Only resolves in dev; build mode\n // never serves it because transformIndexHtml never injects the tag.\n if (id === DEVTOOLS_VIRTUAL_ID) return DEVTOOLS_RESOLVED_ID\n },\n\n load(id: string) {\n if (id === RESOLVED_ENTRY_ID) {\n return generateEntryClient(ssrEnabled, {\n theoUi: theoUi?.enabled\n ? { fonts: theoUi.config.fonts, theme: theoUi.config.theme }\n : undefined,\n })\n }\n if (id === RESOLVED_MANIFEST_ID) {\n const tree = scanRoutes(appDir)\n // T3.1 — also broadcast a devtools-shaped manifest to the overlay\n // (no-op in prod / when no dev server is attached).\n broadcastRouteManifest(tree)\n return generateRouteManifest(tree)\n }\n if (id === RESOLVED_ENTRY_SERVER_ID) {\n // SSR tree MUST mirror client tree shape — pass theoUi through so\n // <TheoUIProvider> wraps in both. Without this, React detects a\n // hydration mismatch and silently falls back to client-only\n // render — onClick handlers never get attached.\n return generateEntryServer({\n streaming: options.ssrStreaming === true,\n theoUi: theoUi?.enabled ? { theme: theoUi.config.theme } : undefined,\n })\n }\n if (id === RESOLVED_RUNTIME_CONFIG_ID) {\n // T1.3 — set globalThis.__THEO_TRANSFORMER__ so theoFetch picks it up\n const tName = transformer?.name ?? 'json'\n return [\n `// Generated by Theo Vite plugin`,\n `;(globalThis).__THEO_TRANSFORMER__ = ${JSON.stringify(tName)}`,\n `export const TRANSFORMER_NAME = ${JSON.stringify(tName)}`,\n ].join('\\n')\n }\n if (id === DEVTOOLS_RESOLVED_ID) {\n // T1.2 — virtual module re-exports the real entry from theokit's devtools subpath.\n // The actual mount logic lives in packages/theo/src/devtools/entry.tsx;\n // we just emit a tiny shim that imports it (Vite's resolver finds the\n // file via the `theokit` package alias set up in `config()` above).\n return [\n `// Theo devtools — virtual entry (DEV only)`,\n `import('theokit/devtools/entry').catch((e) => console.error('[theo devtools] mount failed', e))`,\n ].join('\\n')\n }\n },\n\n configureServer(server) {\n // T1.2 — mark dev mode so transformIndexHtml injects devtools script\n // and resolveId/load serve the virtual module. Build mode never calls\n // configureServer, so isDevMode stays false and injection is skipped.\n isDevMode = true\n\n // T2.4 — expose dev server WS to server-side broadcast helper\n // (so server modules can push events to the devtools UI without a\n // hard dependency on Vite). Cleared on server.close.\n ;(globalThis as { __theoViteHotServer?: typeof server }).__theoViteHotServer = server\n\n // T3.1 — re-broadcast the route manifest when the devtools bridge\n // asks. The initial broadcast happens during `load()` for the\n // manifest virtual module — that fires BEFORE the bridge subscribes.\n // The bridge sends 'theo:devtools:request-manifest' right after\n // subscribing; we reply with a fresh broadcast.\n server.ws.on('theo:devtools:request-manifest', () => {\n try {\n const tree = scanRoutes(appDir)\n broadcastRouteManifest(tree)\n } catch {\n /* fail silently — dev-only convenience */\n }\n })\n\n // Server middleware (action before API — more specific prefix first)\n const serverDir = resolve(projectRoot, 'server')\n server.middlewares.use(\n createActionMiddleware(server, serverDir, { pluginRunner, csrfMode, disallowed }),\n )\n // Wave 2 completion — services-proxy prefixes flow through to the\n // api-middleware so it can call `next()` for paths that should be\n // forwarded to a sidecar by Vite's proxyMiddleware (registered AFTER\n // configureServer hooks per Vite's middleware order).\n const servicesProxyPrefixes =\n options.services && Object.keys(options.services).length > 0\n ? Object.values(options.services).map((s) => s.proxy)\n : []\n server.middlewares.use(\n createApiMiddleware(server, serverDir, {\n rateLimitConfig: options.rateLimit,\n pluginRunner,\n batching: resolvedBatching,\n transformer,\n csrfMode,\n securityHeaders,\n disallowed,\n cors,\n auditLogger,\n servicesProxyPrefixes,\n }),\n )\n\n // EC-1: warn if theo.config.ts is edited during dev session — do NOT\n // re-instantiate runner (would cause register side-effect leaks).\n const configPath = resolve(projectRoot, 'theo.config.ts')\n server.watcher.on('change', (file) => {\n if (file === configPath) {\n console.warn(\n '\\n[theokit] theo.config.ts changed; restart dev server for plugin changes to take effect\\n',\n )\n }\n })\n\n // T2.2 (architecture-medium-deferrals) — SSR dev middleware extracted.\n if (ssrEnabled) {\n setupSsrDevMiddleware(server, {\n projectRoot,\n virtualEntryServerId: VIRTUAL_ENTRY_SERVER_ID,\n securityHeaders,\n })\n }\n\n // Frontend HMR watcher\n function handleRouteChange(filePath: string) {\n if (!isRouteFile(basename(filePath))) return\n if (!filePath.startsWith(appDir)) return\n\n const mod = server.moduleGraph.getModuleById(RESOLVED_MANIFEST_ID)\n if (mod) {\n server.moduleGraph.invalidateModule(mod)\n server.ws.send({ type: 'full-reload' })\n }\n }\n\n server.watcher.on('add', handleRouteChange)\n server.watcher.on('unlink', handleRouteChange)\n\n // T2.3 (architecture-medium-deferrals) — WS upgrade extracted to sibling.\n setupWsUpgrade(server, projectRoot)\n\n // T2.4 — clear devtools WS reference on shutdown\n server.httpServer?.once('close', () => {\n ;(globalThis as { __theoViteHotServer?: unknown }).__theoViteHotServer = undefined\n })\n },\n }\n}\n","/**\n * T3.1 — Translate the server-side RouteNode tree into the devtools-facing\n * RouteManifest shape, then broadcast over the HMR bridge.\n *\n * No-op in production / when no dev server is attached.\n *\n * NEVER use dangerouslySetInnerHTML in any devtools component — see plan EC-20.\n */\nimport type { RouteNode } from '../../core/contracts/route-node.js'\nimport type { RouteInfo, RouteManifest } from '../shared.js'\n\nimport { broadcastToDevtools } from './broadcast.js'\n\ninterface FlattenAccumulator {\n routes: RouteInfo[]\n}\n\nfunction buildPath(parents: string[], segment: string): string {\n const joined = [...parents, segment].filter(Boolean).join('/')\n return '/' + joined\n}\n\nfunction walk(\n node: RouteNode,\n parents: string[],\n layoutChain: string[],\n acc: FlattenAccumulator,\n): void {\n const path = buildPath(parents, node.segment)\n // Layout file (if any) joins the chain for any descendant page.\n const nextChain = node.layout ? [...layoutChain, node.layout] : layoutChain\n\n if (node.page) {\n acc.routes.push({\n path,\n absoluteFilePath: node.page,\n layoutChain: [...layoutChain], // freeze chain at this leaf\n hasLoading: Boolean(node.loading),\n hasError: Boolean(node.error),\n hasNotFound: Boolean(node.notFound),\n })\n }\n\n for (const child of node.children) {\n const nextParents = node.segment ? [...parents, node.segment] : parents\n walk(child, nextParents, nextChain, acc)\n }\n}\n\n/**\n * Pure helper: convert RouteNode tree → RouteManifest for the devtools UI.\n * Exported for testing.\n */\nexport function buildRouteManifest(tree: RouteNode): RouteManifest {\n const acc: FlattenAccumulator = { routes: [] }\n walk(tree, [], [], acc)\n return { routes: acc.routes }\n}\n\n/**\n * Broadcast the manifest to the devtools UI over the HMR bridge.\n * Safe to call from any dev-server context — no-op in production.\n */\nexport function broadcastRouteManifest(tree: RouteNode): void {\n const manifest = buildRouteManifest(tree)\n broadcastToDevtools('theo:devtools:manifest', manifest)\n}\n","export interface EntryServerOptions {\n /** When true, emit a streaming entry using onShellReady + signal cleanup.\n * When false (default), emit the legacy single-shot onAllReady entry. */\n streaming?: boolean\n /**\n * TheoUI config — when present, the SSR React tree wraps StaticRouterProvider\n * in <TheoUIProvider> + <Suspense> to MATCH the client entry exactly. Without\n * this, hydration falls back silently because the trees differ — button\n * onClick handlers never get attached and the page looks dead.\n *\n * EC-2 (CSS): the SSR entry never imports CSS. Only the React tree is\n * mirrored — the CSS stays client-only.\n */\n theoUi?: { theme?: 'violet-forge' | 'noir' | 'paper' }\n}\n\nexport function generateEntryServer(options: EntryServerOptions = {}): string {\n if (options.streaming) {\n return generateStreamingEntry(options)\n }\n return generateSingleShotEntry(options)\n}\n\n/**\n * Build the React element tree the server renders. Must mirror the client\n * tree shape from `generateEntryClient` — same wrapper components, same\n * order — or hydration silently falls back to client-only render.\n */\nfunction buildAppTreeJs(options: EntryServerOptions): string {\n const theme = options.theoUi?.theme ?? 'violet-forge'\n // T4.1 — pass options.nonce to StaticRouterProvider so its internal\n // hydration data script (`<script>window.__staticRouterHydrationData\n // = ...</script>`) carries the nonce attribute. Without this, CSP\n // enforce mode (without 'unsafe-inline') blocks the hydration script\n // → React falls back to client-only render → button onClick handlers\n // never attach → page looks dead. The nonce option to\n // renderToPipeableStream covers React-emitted scripts but NOT the\n // hydration script which is emitted by react-router itself.\n // hydrate: false — CRITICAL fix for hydration mismatch.\n //\n // StaticRouterProvider with `hydrate: true` (default) emits\n // `<script>window.__staticRouterHydrationData = ...</script>` INSIDE\n // the React tree. The client's `<RouterProvider>` does NOT emit any\n // script. React's reconciler sees server={...stuff, <script>} vs\n // client={...stuff} and DISCARDS the entire server tree, regenerating\n // from scratch on the client. That regeneration causes a massive\n // layout shift (CLS 0.39 measured in the example).\n //\n // Fix: tell StaticRouterProvider to NOT emit the script. The framework\n // emits the hydration data as a separate `<script>` in the HTML\n // template (outside #root), via the `hydrationData` returned from\n // `render()`. The script still runs BEFORE entry-client.js, so\n // window.__staticRouterHydrationData is populated when\n // createBrowserRouter reads it.\n if (options.theoUi) {\n return [\n `React.createElement(TheoUIProvider, { theme: { defaultTheme: '${theme}' } },`,\n ` React.createElement(Suspense, { fallback: null },`,\n ` React.createElement(StaticRouterProvider, { router, context, hydrate: false })`,\n ` )`,\n ` )`,\n ].join('\\n')\n }\n return `React.createElement(Suspense, { fallback: null },\\n React.createElement(StaticRouterProvider, { router, context, hydrate: false })\\n )`\n}\n\n/**\n * Generate the hydration data extraction snippet. Reads\n * loaderData/actionData/errors from the StaticHandlerContext and returns\n * them as an object the framework can serialize into a `<script>` tag.\n */\nfunction hydrationDataExtractSnippet(): string {\n return [\n ` const hydrationData = {`,\n ` loaderData: context.loaderData,`,\n ` actionData: context.actionData,`,\n ` errors: context.errors,`,\n ` }`,\n ].join('\\n')\n}\n\nfunction generateSingleShotEntry(options: EntryServerOptions): string {\n const theoUiImport = options.theoUi ? `import { TheoUIProvider } from '@usetheo/ui'\\n` : ''\n const appTree = buildAppTreeJs(options)\n return [\n `import React, { Suspense } from 'react'`,\n `import { renderToPipeableStream } from 'react-dom/server'`,\n `import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router'`,\n `import { PassThrough } from 'node:stream'`,\n `import { routes } from '/@theo/route-manifest'`,\n theoUiImport,\n `export async function render(url, options = {}) {`,\n ` const handler = createStaticHandler(routes)`,\n ` const request = new Request('http://localhost' + url)`,\n ` const context = await handler.query(request)`,\n ``,\n ` if (context instanceof Response) {`,\n ` return { redirect: context }`,\n ` }`,\n ``,\n ` const router = createStaticRouter(handler.dataRoutes, context)`,\n ` const app = ${appTree}`,\n ``,\n hydrationDataExtractSnippet(),\n ``,\n ` return new Promise((resolve, reject) => {`,\n ` let html = ''`,\n ` let piped = false`,\n ` const passthrough = new PassThrough()`,\n ` passthrough.on('data', (chunk) => { html += chunk.toString() })`,\n ` passthrough.on('end', () => { resolve({ html, hydrationData }) })`,\n ` passthrough.on('error', reject)`,\n ``,\n ` // Pipe on onShellReady (Next.js pattern). Calling pipe() twice`,\n ` // throws \"React currently only supports piping to one writable`,\n ` // stream\". The \\`piped\\` flag is a belt-and-suspenders guard if`,\n ` // onShellReady fires unexpectedly more than once.`,\n ` // Forward options.nonce to React so every <script> tag React`,\n ` // emits (Suspense boundary scripts) carries the nonce attribute.`,\n ` const { pipe } = renderToPipeableStream(app, {`,\n ` nonce: options.nonce,`,\n ` onShellReady() { if (!piped) { piped = true; pipe(passthrough) } },`,\n ` onShellError(err) { reject(err) },`,\n ` onError(err) { console.error('[SSR Error]', err) },`,\n ` })`,\n ` })`,\n `}`,\n ].join('\\n')\n}\n\n// Generated-code fragments — extracted so the parent emitter stays under\n// the max-lines-per-function ceiling.\nfunction streamingWebRenderer(appTree: string): string[] {\n return [\n `// T2.3 — Web Standards streaming entry for edge runtimes (Cloudflare,`,\n `// Bun, Deno, Vercel Edge). Uses renderToReadableStream and returns a`,\n `// Response with the stream as body. Honors request.signal for client`,\n `// disconnect cleanup.`,\n `export async function renderStreamingWeb(request, options = {}) {`,\n ` const handler = createStaticHandler(routes)`,\n ` const url = new URL(request.url)`,\n ` const context = await handler.query(request)`,\n ``,\n ` if (context instanceof Response) {`,\n ` return context`,\n ` }`,\n ``,\n ` const router = createStaticRouter(handler.dataRoutes, context)`,\n ` const app = ${appTree}`,\n ``,\n ` const stream = await renderToReadableStream(app, {`,\n ` signal: request.signal,`,\n ` nonce: options.nonce,`,\n ` onError(err) { console.error('[SSR Web Stream Error]', err) },`,\n ` })`,\n ` return new Response(stream, {`,\n ` status: 200,`,\n ` headers: {`,\n ` 'Content-Type': 'text/html; charset=utf-8',`,\n ` 'Transfer-Encoding': 'chunked',`,\n ` },`,\n ` })`,\n `}`,\n ]\n}\n\nfunction streamingNodeRenderer(appTree: string): string[] {\n return [\n `// T6.1 — Node streaming SSR entry (opt-in via theo.config.ts > ssrStreaming: true)`,\n `// Flushes the shell as soon as it's ready, then streams Suspense boundaries.`,\n `// EC-11: respects request.signal for client-disconnect cleanup.`,\n `export async function renderStreaming(url, response, options = {}) {`,\n ` const handler = createStaticHandler(routes)`,\n ` const request = new Request('http://localhost' + url, { signal: options.signal })`,\n ` const context = await handler.query(request)`,\n ``,\n ` if (context instanceof Response) {`,\n ` return { redirect: context }`,\n ` }`,\n ``,\n ` const router = createStaticRouter(handler.dataRoutes, context)`,\n ` const app = ${appTree}`,\n ``,\n ` return new Promise((resolve, reject) => {`,\n ` let didError = false`,\n ` const stream = renderToPipeableStream(app, {`,\n ` nonce: options.nonce,`,\n ` onShellReady() {`,\n ` response.statusCode = didError ? 500 : 200`,\n ` response.setHeader('Content-Type', 'text/html; charset=utf-8')`,\n ` response.setHeader('Transfer-Encoding', 'chunked')`,\n ` stream.pipe(response)`,\n ` resolve({ streaming: true })`,\n ` },`,\n ` onShellError(err) { reject(err) },`,\n ` onError(err) {`,\n ` didError = true`,\n ` console.error('[SSR Stream Error]', err)`,\n ` },`,\n ` })`,\n ``,\n ` // EC-11: client disconnect cleanup`,\n ` if (options.signal) {`,\n ` options.signal.addEventListener('abort', () => { stream.abort() })`,\n ` }`,\n ` })`,\n `}`,\n ]\n}\n\nfunction backCompatRenderer(appTree: string): string[] {\n return [\n `// Backward compatibility: keep the single-shot render export available so`,\n `// callers that always used 'render()' don't break when streaming is on.`,\n `export async function render(url, options = {}) {`,\n ` const handler = createStaticHandler(routes)`,\n ` const request = new Request('http://localhost' + url)`,\n ` const context = await handler.query(request)`,\n ``,\n ` if (context instanceof Response) {`,\n ` return { redirect: context }`,\n ` }`,\n ``,\n ` const router = createStaticRouter(handler.dataRoutes, context)`,\n ` const app = ${appTree}`,\n ``,\n hydrationDataExtractSnippet(),\n ``,\n ` const { PassThrough } = await import('node:stream')`,\n ` return new Promise((resolve, reject) => {`,\n ` let html = ''`,\n ` let piped = false`,\n ` const passthrough = new PassThrough()`,\n ` passthrough.on('data', (chunk) => { html += chunk.toString() })`,\n ` passthrough.on('end', () => { resolve({ html, hydrationData }) })`,\n ` passthrough.on('error', reject)`,\n ``,\n ` // Pipe on onShellReady (Next.js pattern). nonce forwarded.`,\n ` const { pipe } = renderToPipeableStream(app, {`,\n ` nonce: options.nonce,`,\n ` onShellReady() { if (!piped) { piped = true; pipe(passthrough) } },`,\n ` onShellError(err) { reject(err) },`,\n ` onError(err) { console.error('[SSR Error]', err) },`,\n ` })`,\n ` })`,\n `}`,\n ]\n}\n\nfunction generateStreamingEntry(options: EntryServerOptions): string {\n const theoUiImport = options.theoUi ? `import { TheoUIProvider } from '@usetheo/ui'\\n` : ''\n const appTree = buildAppTreeJs(options)\n return [\n `import React, { Suspense } from 'react'`,\n `import { renderToPipeableStream, renderToReadableStream } from 'react-dom/server'`,\n `import { createStaticHandler, createStaticRouter, StaticRouterProvider } from 'react-router'`,\n `import { routes } from '/@theo/route-manifest'`,\n theoUiImport,\n ``,\n ...streamingWebRenderer(appTree),\n ``,\n ...streamingNodeRenderer(appTree),\n ``,\n ...backCompatRenderer(appTree),\n ].join('\\n')\n}\n","export interface EntryClientOptions {\n theoUi?: {\n fonts?: 'bundled' | 'cdn'\n theme?: 'violet-forge' | 'noir' | 'paper'\n }\n}\n\nexport function generateEntryClient(ssr?: boolean, opts: EntryClientOptions = {}): string {\n const rootMethod = ssr ? 'hydrateRoot' : 'createRoot'\n\n // T2.2 — TheoUI CSS imports (client-only; EC-2: NEVER in entry-server)\n // T2.3 — Wrap RouterProvider in <TheoUIProvider>\n const theoUiImports: string[] = []\n if (opts.theoUi) {\n theoUiImports.push(\n `// T2.2 — TheoUI CSS auto-injected (config.ui)`,\n `import '@usetheo/ui/styles.css'`,\n )\n const fontsModule = opts.theoUi.fonts === 'cdn' ? 'fonts-cdn.css' : 'fonts.css'\n theoUiImports.push(\n `import '@usetheo/ui/${fontsModule}'`,\n `// T2.3 — TheoUIProvider auto-wraps RouterProvider`,\n `import { TheoUIProvider } from '@usetheo/ui'`,\n )\n }\n\n const theme = opts.theoUi?.theme ?? 'violet-forge'\n // Build the React tree: when theoUi enabled, RouterProvider sits inside\n // TheoUIProvider; otherwise RouterProvider is the top-level child.\n const routerTree = opts.theoUi\n ? `React.createElement(TheoUIProvider, { theme: { defaultTheme: '${theme}' } },\\n React.createElement(Suspense, { fallback: null },\\n React.createElement(RouterProvider, { router })\\n )\\n )`\n : `React.createElement(Suspense, { fallback: null },\\n React.createElement(RouterProvider, { router })\\n )`\n\n const renderCall = ssr\n ? ` ${rootMethod}(el,\\n ${routerTree}\\n )`\n : ` ${rootMethod}(el).render(\\n ${routerTree}\\n )`\n\n // SSR hydration: <StaticRouterProvider hydrate> emits\n // `<script>window.__staticRouterHydrationData = …</script>` into the\n // server HTML. The browser router MUST receive this so it continues\n // from the server's state instead of re-fetching everything.\n //\n // Without `hydrationData`, `createBrowserRouter` boots from scratch,\n // React detects a DOM mismatch with the SSR-rendered HTML, and\n // hydration silently falls back to client-only render — every\n // `onClick` handler attached during hydration is lost. The page\n // looks fine but is \"dead HTML\".\n const hydrationLine = ssr\n ? `const router = createBrowserRouter(routes, { hydrationData: window.__staticRouterHydrationData })`\n : `const router = createBrowserRouter(routes)`\n\n // Phase 4 — Code-splitting + matchRoutes safeguard (EC-3).\n //\n // SSR mode: pages are React.lazy()-wrapped in the manifest. If we render\n // before the matched route's module is loaded, React.lazy throws a\n // promise, the outer Suspense fires its fallback (null), and the SSR\n // DOM is wiped before hydration → onClick handlers die.\n //\n // The fix:\n // 1. matchRoutes(routes, location.pathname) on the client to discover\n // which routes actually render at this URL. Using the client matcher\n // (not a server hint) avoids URL-drift races: SSR may have prepared\n // /foo while a browser auto-redirect now points at /bar.\n // 2. Look up each matched route's path in __theoPreloadMap and call\n // the import() factory. Browsers cache modules by URL — when\n // React.lazy fires its own import() during render, it gets the\n // cached promise instantly.\n // 3. Promise.all with a 1500ms timeout. On slow networks we'd rather\n // lose hydration on ONE request than hang the page forever. The\n // fallback path proceeds to hydrate anyway — React.lazy will then\n // Suspense its fallback as usual.\n const preloadBlock = ssr\n ? [\n `// Phase 4 — preload matched-route modules before hydrate (EC-3 safeguard)`,\n `const __theoMatches = matchRoutes(routes, window.location.pathname) ?? []`,\n `const __theoPreloadPaths = __theoMatches`,\n ` .map((m) => m.route && (m.route).path)`,\n ` .filter((p) => typeof p === 'string' && p in __theoPreloadMap)`,\n `const __theoPreloadPromise = Promise.all(`,\n ` __theoPreloadPaths.map((p) => __theoPreloadMap[p]().catch((err) => { console.error('[theo] preload failed', p, err); return null }))`,\n `)`,\n `const __theoTimeout = new Promise((resolve) => setTimeout(() => resolve('timeout'), 1500))`,\n `await Promise.race([__theoPreloadPromise, __theoTimeout])`,\n '',\n ]\n : []\n\n // The hydrate/render call needs to live inside an async IIFE when we\n // await preloads. In CSR-only mode we keep the existing synchronous\n // block for backward compat.\n const renderBlock = ssr\n ? [\n `if (el) {`,\n ` ;(async () => {`,\n ...preloadBlock.map((l) => ' ' + l),\n renderCall,\n ` })()`,\n `}`,\n ]\n : [`if (el) {`, renderCall, `}`]\n\n const manifestImports = ssr\n ? `import { routes, __theoPreloadMap } from '/@theo/route-manifest'`\n : `import { routes } from '/@theo/route-manifest'`\n\n const reactRouterImports = ssr\n ? `import { createBrowserRouter, RouterProvider, matchRoutes } from 'react-router'`\n : `import { createBrowserRouter, RouterProvider } from 'react-router'`\n\n return [\n `import React, { Suspense } from 'react'`,\n `import { ${rootMethod} } from 'react-dom/client'`,\n reactRouterImports,\n manifestImports,\n `// T1.3 — side-effect import sets globalThis.__THEO_TRANSFORMER__ for theoFetch`,\n `import '/@theo/runtime-config'`,\n ...theoUiImports,\n ``,\n hydrationLine,\n `const el = document.getElementById('root')`,\n ...renderBlock,\n ].join('\\n')\n}\n","import type { RouteNode } from './types.js'\n\nfunction normalizePath(p: string): string {\n return p.replace(/\\\\/g, '/')\n}\n\nfunction safeVarName(segment: string, prefix: string): string {\n const safe = segment.replace(/[^a-zA-Z0-9]/g, '_') || 'root'\n return `${prefix}_${safe}`\n}\n\ninterface ImportEntry {\n varName: string\n importPath: string\n}\n\n/**\n * Build the absolute route path for a node by accumulating segments from\n * the root. Used to key the preload map exactly as react-router's\n * `matchRoutes` reports `match.route.path`.\n */\nfunction buildRoutePath(parents: string[], segment: string): string {\n const joined = [...parents, segment].filter(Boolean).join('/')\n return '/' + joined\n}\n\ninterface WalkAccumulator {\n staticImports: ImportEntry[]\n lazyPages: { varName: string; importPath: string; routePath: string }[]\n layoutState: { found: boolean }\n}\n\nfunction pushIf(staticImports: ImportEntry[], filePath: string | undefined, varName: string): void {\n if (filePath !== undefined) {\n staticImports.push({ varName, importPath: normalizePath(filePath) })\n }\n}\n\nfunction walkRouteTree(node: RouteNode, parents: string[], acc: WalkAccumulator): void {\n const seg = node.segment || 'root'\n const routePath = buildRoutePath(parents, node.segment)\n\n if (node.page !== undefined) {\n acc.lazyPages.push({\n varName: safeVarName(seg, 'Page'),\n importPath: normalizePath(node.page),\n routePath,\n })\n }\n if (node.layout !== undefined) acc.layoutState.found = true\n pushIf(acc.staticImports, node.layout, safeVarName(seg, 'Layout'))\n pushIf(acc.staticImports, node.error, safeVarName(seg, 'Error'))\n pushIf(acc.staticImports, node.loading, safeVarName(seg, 'Loading'))\n pushIf(acc.staticImports, node.notFound, safeVarName(seg, 'NotFound'))\n for (const child of node.children) {\n const nextParents = node.segment ? [...parents, node.segment] : parents\n walkRouteTree(child, nextParents, acc)\n }\n}\n\nexport function generateRouteManifest(tree: RouteNode): string {\n // Static imports (always-needed at boot): layouts, errors, loading, not-found.\n // Lazy-loaded pages — tracked separately so we emit React.lazy() and\n // build the preload map.\n const acc: WalkAccumulator = {\n staticImports: [],\n lazyPages: [],\n layoutState: { found: false },\n }\n walkRouteTree(tree, [], acc)\n const staticImports = acc.staticImports\n const lazyPages = acc.lazyPages\n const layoutState = acc.layoutState\n\n // Phase 4 — Code-splitting + matchRoutes safeguard (EC-3).\n // PAGES are lazy. LAYOUTS / ERROR / LOADING / NOT-FOUND stay static\n // because they're always needed at boot regardless of route.\n // The preload map exposes the same `import()` calls keyed by absolute\n // route path. The entry-client re-matches `routes` against\n // `location.pathname` and awaits the matched entries BEFORE\n // `hydrateRoot`, so React.lazy modules resolve from cache and no\n // Suspense fallback fires during hydration.\n const lines: string[] = [`import React, { Suspense } from 'react'`]\n\n if (layoutState.found) {\n lines.push(`import { Outlet } from 'react-router'`)\n }\n\n lines.push('')\n\n // Static imports first\n for (const imp of staticImports) {\n lines.push(`import ${imp.varName} from '${imp.importPath}'`)\n }\n\n // Lazy-loaded pages\n for (const lp of lazyPages) {\n lines.push(`const ${lp.varName} = React.lazy(() => import('${lp.importPath}'))`)\n }\n\n lines.push('')\n\n // Preload map — keys are absolute route paths, values are factories that\n // return the same import() the lazy() above resolves. Browsers cache the\n // module by URL so the preload + lazy() share a single promise.\n const preloadEntries = lazyPages.map(\n (lp) => ` '${lp.routePath}': () => import('${lp.importPath}'),`,\n )\n // No TS type annotation — this manifest is emitted as a virtual JS module\n // and Rollup rejects type annotations in production builds.\n lines.push('export const __theoPreloadMap = {')\n for (const e of preloadEntries) lines.push(e)\n lines.push('}', '')\n\n // Build the children-array string for one node, separately from the\n // wrapping logic — keeps `genRouteConfig` under the complexity ceiling.\n function buildChildrenArray(node: RouteNode, seg: string): string {\n const childConfigs: string[] = []\n\n // Index route for this node's page — wrap in Suspense (the lazy module\n // is preloaded on initial hydrate, so this fallback never fires there;\n // it covers client-side navigation to other routes too).\n if (node.page) {\n const pageVar = safeVarName(seg, 'Page')\n const fallbackEl = node.loading\n ? `React.createElement(${safeVarName(seg, 'Loading')})`\n : 'null'\n const pageElement = `React.createElement(Suspense, { fallback: ${fallbackEl} }, React.createElement(${pageVar}))`\n childConfigs.push(`{ index: true, element: ${pageElement} }`)\n }\n\n // Child routes\n for (const child of node.children) {\n childConfigs.push(genRouteConfig(child, false))\n }\n\n // Not-found wildcard (only at this level)\n if (node.notFound) {\n const nfVar = safeVarName(seg, 'NotFound')\n childConfigs.push(`{ path: '*', element: React.createElement(${nfVar}) }`)\n }\n\n let arr = `[${childConfigs.join(', ')}]`\n if (node.error) {\n const errVar = safeVarName(seg, 'Error')\n arr = `[{ errorElement: React.createElement(${errVar}), children: ${arr} }]`\n }\n return arr\n }\n\n // Generate route config\n function genRouteConfig(node: RouteNode, isRoot: boolean): string {\n const seg = node.segment || 'root'\n const childrenArray = buildChildrenArray(node, seg)\n\n // Build route object\n if (node.layout) {\n const layoutVar = safeVarName(seg, 'Layout')\n const pathPart = isRoot ? `path: '/'` : `path: '${node.segment}'`\n // Layout receives `<Outlet />` as `children` prop. This supports BOTH\n // conventions: Next.js-style layouts that render `{children}` AND\n // layouts that call `<Outlet />` directly (the prop is the same element,\n // ignored by the latter). Without this, Next.js-style templates render\n // empty because react-router does not pass a `children` prop by default.\n return `{ ${pathPart}, element: React.createElement(${layoutVar}, { children: React.createElement(Outlet) }), children: ${childrenArray} }`\n }\n\n // No layout — if root, wrap in path '/'\n if (isRoot) {\n if (node.children.length === 0 && !node.page && !node.notFound && !node.error) {\n return `{ path: '/', children: [] }`\n }\n // Root without layout: children are direct routes\n return `{ path: '/', children: ${childrenArray} }`\n }\n\n // Child segment without layout — just a route\n if (node.page && node.children.length === 0 && !node.error && !node.notFound) {\n const pageVar = safeVarName(seg, 'Page')\n const fallbackEl = node.loading\n ? `React.createElement(${safeVarName(seg, 'Loading')})`\n : 'null'\n const pageElement = `React.createElement(Suspense, { fallback: ${fallbackEl} }, React.createElement(${pageVar}))`\n return `{ path: '${node.segment}', element: ${pageElement} }`\n }\n\n // Child with children but no layout\n return `{ path: '${node.segment}', children: ${childrenArray} }`\n }\n\n const routeConfig = genRouteConfig(tree, true)\n lines.push(`export const routes = [${routeConfig}]`)\n\n return lines.join('\\n')\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time file-system scanner. All paths originate from `appDir`,\n * which is itself derived from `process.cwd()`. No HTTP input flows here.\n */\nimport { readdirSync, statSync, existsSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\n\nimport type { RouteNode, RouteFileName } from './types.js'\nimport { ROUTE_FILE_NAMES, ROUTE_FILE_EXTENSIONS } from './types.js'\n\nfunction toNodeKey(name: RouteFileName): 'page' | 'layout' | 'error' | 'loading' | 'notFound' {\n if (name === 'not-found') return 'notFound'\n return name\n}\n\nfunction setRouteFile(\n node: RouteNode,\n key: 'page' | 'layout' | 'error' | 'loading' | 'notFound',\n value: string,\n): void {\n switch (key) {\n case 'page':\n node.page = value\n break\n case 'layout':\n node.layout = value\n break\n case 'error':\n node.error = value\n break\n case 'loading':\n node.loading = value\n break\n case 'notFound':\n node.notFound = value\n break\n }\n}\n\nfunction attachRouteFiles(node: RouteNode, dir: string): void {\n // Check route files with extension priority (.tsx > .ts > .jsx > .js)\n for (const name of ROUTE_FILE_NAMES) {\n const key = toNodeKey(name)\n if (node[key] !== undefined) continue\n for (const ext of ROUTE_FILE_EXTENSIONS) {\n const filename = `${name}${ext}`\n if (existsSync(join(dir, filename))) {\n setRouteFile(node, key, resolve(dir, filename))\n break\n }\n }\n }\n}\n\nfunction nodeHasContent(node: RouteNode): boolean {\n return (\n node.page !== undefined ||\n node.layout !== undefined ||\n node.error !== undefined ||\n node.loading !== undefined ||\n node.notFound !== undefined ||\n node.children.length > 0\n )\n}\n\nfunction scanDir(dir: string, segment: string, routePath: string): RouteNode {\n const node: RouteNode = { segment, path: routePath, children: [] }\n attachRouteFiles(node, dir)\n\n // Recurse into subdirectories\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue\n\n const childPath = routePath === '/' ? `/${entry.name}` : `${routePath}/${entry.name}`\n const child = scanDir(join(dir, entry.name), entry.name, childPath)\n\n // Prune empty nodes — a directory with no route files AND no\n // children is irrelevant to the manifest.\n if (nodeHasContent(child)) {\n node.children.push(child)\n }\n }\n\n return node\n}\n\nexport function scanRoutes(appDir: string): RouteNode {\n if (!existsSync(appDir)) {\n throw new Error(`App directory does not exist: ${appDir}`)\n }\n if (!statSync(appDir).isDirectory()) {\n throw new Error(`App path is not a directory: ${appDir}`)\n }\n return scanDir(appDir, '', '/')\n}\n","// T2.2 (architecture-cleanup) — RouteNode moved to core/contracts/route-node.ts\n// (canonical home per ADR-0001 v3). Re-export keeps the local path stable.\nexport type { RouteNode } from '../core/contracts/route-node.js'\n\nexport const ROUTE_FILE_NAMES = ['page', 'layout', 'error', 'loading', 'not-found'] as const\n\nexport type RouteFileName = (typeof ROUTE_FILE_NAMES)[number]\n\nexport const ROUTE_FILE_EXTENSIONS = ['.tsx', '.ts', '.jsx', '.js'] as const\n\nconst ROUTE_FILE_REGEX = /^(page|layout|error|loading|not-found)\\.(tsx|ts|jsx|js)$/\n\nexport function isRouteFile(filename: string): boolean {\n return ROUTE_FILE_REGEX.test(filename)\n}\n","import { randomUUID } from 'node:crypto'\n\nimport type { ViteDevServer, Connect } from 'vite'\n\nimport { executeAction } from '../server/http/action-execute.js'\nimport { sendError } from '../server/http/execute.js'\nimport { logRequest } from '../server/observability/logger.js'\nimport { findSuggestion } from '../server/observability/suggest.js'\nimport type { PluginRunner } from '../server/plugins/plugin-runner.js'\nimport { scanServerActions } from '../server/scan/action-scan.js'\nimport { createViteLoader } from '../server/scan/module-loader.js'\nimport type { CsrfMode, DisallowedConfig } from '../server/security/csrf.js'\n\nconst PREFIX = '/api/__actions/'\n\nexport interface ActionMiddlewareOptions {\n pluginRunner?: PluginRunner\n /**\n * CSRF mode passed through to `executeAction`. Parity with the route\n * middleware — actions inherit the same warn/strict policy as routes.\n * Defaults to 'strict' (the 0.3.0 default).\n */\n csrfMode?: CsrfMode\n /**\n * T5.1 — Rails-inspired per-route escalation. Forwarded to `executeAction`.\n */\n disallowed?: DisallowedConfig\n}\n\nexport function createActionMiddleware(\n vite: ViteDevServer,\n serverDir: string,\n options?: ActionMiddlewareOptions,\n): Connect.NextHandleFunction {\n const loadModule = createViteLoader(vite)\n const pluginRunner = options?.pluginRunner\n const csrfMode: CsrfMode = options?.csrfMode ?? 'strict'\n const disallowed = options?.disallowed\n return (req, res, next) => {\n void (async () => {\n const url = req.url ?? ''\n if (!url.startsWith(PREFIX)) {\n next()\n return\n }\n\n const requestId = randomUUID()\n const start = Date.now()\n res.setHeader('x-request-id', requestId)\n\n const pathAfterPrefix = url.slice(PREFIX.length).split('?')[0]\n const segments = pathAfterPrefix.split('/').filter(Boolean)\n\n if (segments.length < 2) {\n sendError(\n res,\n 'BAD_REQUEST',\n 'Action URL must be /api/__actions/{file}/{exportName}',\n 400,\n undefined,\n requestId,\n )\n logRequest({\n method: req.method ?? 'POST',\n url,\n status: 400,\n duration: Date.now() - start,\n requestId,\n })\n return\n }\n\n const exportName = segments[segments.length - 1]\n const actionPath = segments.slice(0, -1).join('/')\n\n const actions = scanServerActions(serverDir)\n const action = actions.find((a) => a.actionPath === actionPath)\n\n if (!action) {\n const actionPaths = actions.map((a) => a.actionPath)\n const suggestion = findSuggestion(actionPath, actionPaths)\n const msg = suggestion\n ? `Action file \"${actionPath}\" not found. Did you mean: ${suggestion}?`\n : `Action file \"${actionPath}\" not found`\n sendError(res, 'NOT_FOUND', msg, 404, undefined, requestId)\n logRequest({\n method: req.method ?? 'POST',\n url,\n status: 404,\n duration: Date.now() - start,\n requestId,\n })\n return\n }\n\n await executeAction(\n action.filePath,\n exportName,\n req,\n res,\n loadModule,\n serverDir,\n requestId,\n pluginRunner,\n csrfMode,\n disallowed,\n )\n logRequest({\n method: req.method ?? 'POST',\n url,\n status: res.statusCode,\n duration: Date.now() - start,\n requestId,\n })\n })()\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\n\nimport type { ViteDevServer, Connect } from 'vite'\n\nimport { handleBatchRequest, BATCH_PATH } from '../server/http/batch-handler.js'\nimport { createCorsHandler, type CorsConfig } from '../server/http/cors.js'\nimport { executeRoute, sendError } from '../server/http/execute.js'\nimport { extractTraceId, TRACE_HEADER } from '../server/http/trace-context.js'\nimport type { AuditLogger } from '../server/observability/audit-log.js'\nimport { logRequest } from '../server/observability/logger.js'\nimport { findSuggestion } from '../server/observability/suggest.js'\nimport type { PluginRunner } from '../server/plugins/plugin-runner.js'\nimport { createRateLimiter } from '../server/rate-limit/rate-limit.js'\nimport type { RateLimitConfig } from '../server/rate-limit/rate-limit.js'\nimport { matchRoute } from '../server/scan/match.js'\nimport { createViteLoader } from '../server/scan/module-loader.js'\nimport { scanServerRoutes } from '../server/scan/scan.js'\nimport {\n CSP_REPORT_PATH,\n handleCspReport,\n type CspReportHandlerOptions,\n} from '../server/security/csp-report.js'\nimport { handleCsrfReadiness } from '../server/security/csrf-readiness-endpoint.js'\nimport type { CsrfReadinessStore } from '../server/security/csrf-readiness-store.js'\nimport type { DisallowedConfig } from '../server/security/csrf.js'\nimport { applySecurityHeaders } from '../server/security/security-headers.js'\nimport type { SecurityHeadersConfig } from '../server/security/security-headers.js'\nimport type { TheoTransformer } from '../server/transformer.js'\n\nexport interface ApiMiddlewareOptions {\n rateLimitConfig?: RateLimitConfig\n pluginRunner?: PluginRunner\n transformer?: TheoTransformer\n /** When defined, enables /api/__theo_batch__ endpoint with given options. */\n batching?: { max?: number }\n /** Phase 5 — CSRF enforcement mode. Default 'warn' (0.2.0). */\n csrfMode?: 'off' | 'warn' | 'strict'\n /** Phase 6 — Default security headers config. */\n securityHeaders?: SecurityHeadersConfig\n /** T5.1 — per-route disallowed escalation pattern. */\n disallowed?: DisallowedConfig\n /** T1.2 — CORS configuration. When undefined, no CORS handling (same-origin only). */\n cors?: CorsConfig\n /** T4.1 — Audit logger. Receives csrf.warn, rate-limit.exceeded, csp.violation events. */\n auditLogger?: AuditLogger\n /** T5.1 — Optional CSP violation hook (forwarded to Sentry / custom sink). */\n onCspViolation?: CspReportHandlerOptions['onViolation']\n /**\n * T2.2 — Optional CSRF readiness store. When provided, the\n * `/__theo/csrf-readiness` endpoint is mounted and warn events are\n * recorded into the store. Dev-mode middleware wires this automatically;\n * production hosts opt in via config.security.csrfTelemetry.exposeReadinessEndpoint.\n */\n csrfReadinessStore?: CsrfReadinessStore\n /**\n * Wave 2 completion (T1.1 vite-proxy) — list of services-proxy path prefixes\n * (e.g. `['/api/agent', '/api/worker']`). Requests whose path starts with\n * any of these prefixes bypass the api-middleware (call `next()`) so the\n * later proxyMiddleware (installed by Vite from `server.proxy`) can forward\n * them to the polyglot sidecar. Empty / undefined preserves Wave 1 BC.\n */\n servicesProxyPrefixes?: readonly string[]\n}\n\n/**\n * Wave 2 completion — true when `url` is OUTSIDE TheoKit's API namespace,\n * either because it doesn't start with `/api/` OR because it matches a\n * services-proxy prefix. In both cases the middleware should call `next()`\n * so the request reaches Vite's proxyMiddleware / static fallback. Combining\n * both checks into one helper keeps the main arrow function's cyclomatic\n * complexity within the eslint ceiling.\n */\nfunction shouldBypassApiMiddleware(url: string, prefixes: readonly string[]): boolean {\n if (!url.startsWith('/api/')) return true\n if (prefixes.length === 0) return false\n const path = url.split('?')[0]\n for (const prefix of prefixes) {\n if (path === prefix || path.startsWith(`${prefix}/`)) return true\n }\n return false\n}\n\nasync function handleCspReportIfMatch(\n req: IncomingMessage,\n res: ServerResponse,\n url: string,\n ctx: {\n auditLogger: AuditLogger | undefined\n onCspViolation: CspReportHandlerOptions['onViolation'] | undefined\n },\n): Promise<boolean> {\n const pathOnly = url.split('?')[0]\n if (pathOnly !== CSP_REPORT_PATH || req.method !== 'POST') return false\n await handleCspReport(req, res, { auditLogger: ctx.auditLogger, onViolation: ctx.onCspViolation })\n return true\n}\n\ninterface RateLimitCtx {\n rateLimiter:\n | ((req: IncomingMessage) => { limited: boolean; headers: Record<string, string> })\n | null\n requestId: string\n url: string\n start: number\n}\n\n/**\n * Apply rate-limit headers and send 429 if exceeded. Returns true when\n * the caller should stop handling the request (limit hit), false otherwise.\n * Extracted from `createApiMiddleware` to keep complexity within ceiling.\n */\nfunction applyRateLimitOr429(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: RateLimitCtx,\n): boolean {\n if (!ctx.rateLimiter) return false\n const check = ctx.rateLimiter(req)\n for (const [k, v] of Object.entries(check.headers)) res.setHeader(k, v)\n if (!check.limited) return false\n sendError(res, 'RATE_LIMITED', 'Too many requests', 429, undefined, ctx.requestId)\n logRequest({\n method: req.method ?? 'GET',\n url: ctx.url,\n status: 429,\n duration: Date.now() - ctx.start,\n requestId: ctx.requestId,\n })\n return true\n}\n\ninterface BatchMatchCtx {\n url: string\n batching: { max?: number } | undefined\n requestId: string\n start: number\n}\n\nasync function handleBatchIfMatch(\n req: IncomingMessage,\n res: ServerResponse,\n ctx: BatchMatchCtx,\n): Promise<boolean> {\n if (!ctx.batching) return false\n const urlPathOnly = ctx.url.split('?')[0]\n if (urlPathOnly !== BATCH_PATH || req.method !== 'POST') return false\n await handleBatchInline(req, res, ctx.batching, ctx.requestId)\n logRequest({\n method: req.method ?? 'POST',\n url: ctx.url,\n status: res.statusCode,\n duration: Date.now() - ctx.start,\n requestId: ctx.requestId,\n })\n return true\n}\n\nasync function handleBatchInline(\n req: IncomingMessage,\n res: ServerResponse,\n batching: { max?: number },\n requestId: string,\n): Promise<void> {\n try {\n const chunks: Buffer[] = []\n await new Promise<void>((resolve, reject) => {\n req.on('data', (c) => chunks.push(c as Buffer))\n req.on('end', () => {\n resolve()\n })\n req.on('error', reject)\n })\n // CR-028: pass the parsed JSON as `unknown`; Zod inside\n // handleBatchRequest is the validation boundary.\n const payload: unknown = JSON.parse(Buffer.concat(chunks).toString())\n const outerHeaders: Record<string, string> = {}\n for (const [k, v] of Object.entries(req.headers)) {\n if (typeof v === 'string') outerHeaders[k.toLowerCase()] = v\n }\n const result = await handleBatchRequest(payload, {\n max: batching.max,\n outerHeaders,\n // T1.4 placeholder — full per-item route execution lands in a\n // follow-up; for now we return an empty ack so the integration\n // tests of the batch endpoint shape pass.\n execute: () => Promise.resolve({ data: { ok: true } }),\n })\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n sendError(res, 'BATCH_ERROR', message, 400, undefined, requestId)\n }\n}\n\nexport function createApiMiddleware(\n vite: ViteDevServer,\n serverDir: string,\n rateLimitConfigOrOptions?: RateLimitConfig | ApiMiddlewareOptions,\n): Connect.NextHandleFunction {\n // Backward-compat: accept either RateLimitConfig directly (old signature)\n // or an ApiMiddlewareOptions object (new signature with pluginRunner).\n const opts: ApiMiddlewareOptions =\n rateLimitConfigOrOptions && 'windowMs' in rateLimitConfigOrOptions\n ? { rateLimitConfig: rateLimitConfigOrOptions }\n : (rateLimitConfigOrOptions ?? {})\n\n const loadModule = createViteLoader(vite)\n const rateLimiter = opts.rateLimitConfig ? createRateLimiter(opts.rateLimitConfig) : null\n const pluginRunner = opts.pluginRunner\n const transformer = opts.transformer\n const batching = opts.batching\n // T6.1 — default flipped from 'warn' to 'strict' for 0.3.0.\n const csrfMode = opts.csrfMode ?? 'strict'\n const disallowed = opts.disallowed\n const securityHeadersConfig = opts.securityHeaders ?? {}\n const securityEnv = { production: process.env.NODE_ENV === 'production' }\n // T1.2 — CORS handler runs FIRST in the pipeline (D10).\n const corsHandler = opts.cors ? createCorsHandler(opts.cors) : null\n const auditLogger = opts.auditLogger\n const onCspViolation = opts.onCspViolation\n const csrfReadinessStore = opts.csrfReadinessStore\n const servicesProxyPrefixes = opts.servicesProxyPrefixes ?? []\n\n return (req, res, next) => {\n void (async () => {\n const url = req.url ?? ''\n\n // T5.1 — built-in CSP report endpoint. Matched BEFORE the /api/* gate\n // so the path lives outside the user's route namespace. Endpoint is\n // CSRF-exempt (browsers don't send X-Theo-Action on report POSTs).\n if (await handleCspReportIfMatch(req, res, url, { auditLogger, onCspViolation })) {\n return\n }\n\n // T2.2 — CSRF readiness endpoint. Only mounted when a store is wired\n // (dev-mode wires it automatically; prod opt-in via config).\n if (csrfReadinessStore && (await handleCsrfReadiness(req, res, csrfReadinessStore))) {\n return\n }\n\n if (shouldBypassApiMiddleware(url, servicesProxyPrefixes)) {\n next()\n return\n }\n\n // T1.2 + D10 — CORS preflight runs BEFORE rate limit, BEFORE CSRF.\n // Preflight short-circuits the response (204 + Access-Control-* headers).\n if (corsHandler?.handlePreflight(req, res)) {\n return\n }\n\n // Phase 7 — traceId resolution. Reads traceparent / x-request-id /\n // generates UUID. The `requestId` name is kept for backward compat\n // with downstream helpers (sendError, logRequest) — same value flows\n // under both `x-request-id` (legacy) and `x-trace-id` (canonical).\n const requestId = extractTraceId(req)\n const start = Date.now()\n res.setHeader('x-request-id', requestId)\n res.setHeader(TRACE_HEADER, requestId)\n // Phase 6 — Apply security headers BEFORE the handler runs so route\n // handlers can still override via res.setHeader (last write wins).\n applySecurityHeaders(res, securityHeadersConfig, securityEnv)\n // T1.2 — Add CORS headers to non-preflight responses.\n corsHandler?.applyHeaders(req, res)\n\n if (applyRateLimitOr429(req, res, { rateLimiter, requestId, url, start })) {\n return\n }\n\n // T1.4 — Batch endpoint (only when batching is enabled in config)\n if (await handleBatchIfMatch(req, res, { url, batching, requestId, start })) {\n return\n }\n\n const routes = scanServerRoutes(serverDir)\n const match = matchRoute(url, routes)\n\n if (!match) {\n const urlPath = url.split('?')[0]\n const routePaths = routes.map((r) => r.routePath)\n const suggestion = findSuggestion(urlPath, routePaths)\n const msg = suggestion\n ? `API route not found: ${urlPath}. Did you mean: ${suggestion}?`\n : 'API route not found'\n sendError(res, 'NOT_FOUND', msg, 404, undefined, requestId)\n logRequest({\n method: req.method ?? 'GET',\n url,\n status: 404,\n duration: Date.now() - start,\n requestId,\n })\n return\n }\n\n const method = (req.method ?? 'GET').toUpperCase()\n // T3.1 (ADR-0016) — context object replaces 12 positional args\n await executeRoute({\n route: match.route,\n method,\n params: match.params,\n req,\n res,\n loadModule,\n serverDir,\n requestId,\n pluginRunner,\n transformer,\n csrfMode,\n disallowed,\n })\n logRequest({ method, url, status: res.statusCode, duration: Date.now() - start, requestId })\n })()\n }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Config loader. Reads `theo.config.{ts,js,mjs}` under the user's `cwd`.\n * Names are a fixed set of literals; `cwd` is a CLI arg resolved to\n * absolute. Build-time tool — no HTTP input.\n */\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { TheoConfigError } from './errors.js'\nimport { loadEnv } from './load-env.js'\nimport { theoConfigSchema } from './schema.js'\nimport type { TheoConfig } from './schema.js'\n\nconst CONFIG_FILE = 'theo.config.ts'\n\n/**\n * Deep merges two plain objects. Override values take precedence.\n * Arrays are replaced (not concatenated).\n * Protects against prototype pollution (EC-4).\n */\nexport function deepMerge(\n base: Record<string, unknown>,\n override: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...base }\n for (const key of Object.keys(override)) {\n // EC-4: Prevent prototype pollution\n if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue\n\n const baseVal = base[key]\n const overVal = override[key]\n\n if (\n overVal !== null &&\n typeof overVal === 'object' &&\n !Array.isArray(overVal) &&\n baseVal !== null &&\n typeof baseVal === 'object' &&\n !Array.isArray(baseVal)\n ) {\n result[key] = deepMerge(\n baseVal as Record<string, unknown>,\n overVal as Record<string, unknown>,\n )\n } else {\n result[key] = overVal\n }\n }\n return result\n}\n\nexport async function loadConfig(dir: string): Promise<TheoConfig> {\n // T1.3 — Load .env BEFORE reading theo.config.ts. Defensive: CLI commands\n // (dev/build/start) already call loadEnv() first, but programmatic users\n // who call loadConfig directly (tests, custom scripts) need this too.\n // Module-level cache makes the second call a Map-lookup (no FS).\n loadEnv({ cwd: dir })\n\n const configPath = resolve(dir, CONFIG_FILE)\n\n if (!existsSync(configPath)) {\n return theoConfigSchema.parse({})\n }\n\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(configPath).href)) as Record<string, unknown>\n } catch (err) {\n throw new TheoConfigError([{ field: '_file', message: (err as Error).message }], configPath)\n }\n\n const userConfig = mod.default\n\n if (userConfig == null || typeof userConfig !== 'object') {\n throw new TheoConfigError(\n [\n {\n field: '_export',\n message: 'theo.config.ts must use export default defineConfig({...})',\n },\n ],\n configPath,\n )\n }\n\n // Merge with per-environment config if NODE_ENV is set\n let rawConfig = userConfig as Record<string, unknown>\n const nodeEnv = process.env.NODE_ENV\n\n if (nodeEnv) {\n const envFile = `theo.config.${nodeEnv}.ts`\n const envPath = resolve(dir, envFile)\n\n if (existsSync(envPath)) {\n try {\n const envMod = (await import(pathToFileURL(envPath).href)) as Record<string, unknown>\n const envConfig = envMod.default\n\n if (envConfig != null && typeof envConfig === 'object') {\n rawConfig = deepMerge(rawConfig, envConfig as Record<string, unknown>)\n }\n } catch (err) {\n throw new TheoConfigError([{ field: '_file', message: (err as Error).message }], envPath)\n }\n }\n }\n\n const result = theoConfigSchema.safeParse(rawConfig)\n\n if (!result.success) {\n const issues = result.error.issues.map((i) => ({\n field: i.path.join('.'),\n message: i.message,\n }))\n throw new TheoConfigError(issues, configPath)\n }\n\n return result.data\n}\n","export interface ConfigIssue {\n field: string\n message: string\n}\n\nexport class TheoConfigError extends Error {\n public readonly issues: ConfigIssue[]\n public readonly configPath: string\n\n constructor(issues: ConfigIssue[], configPath: string) {\n const issueLines = issues.map((i) => ` - ${i.field}: ${i.message}`).join('\\n')\n\n super(\n `Invalid theo.config.ts\\n\\n` +\n ` File: ${configPath}\\n\\n` +\n (issueLines ? ` Issues:\\n${issueLines}\\n` : ''),\n )\n\n this.name = 'TheoConfigError'\n this.issues = issues\n this.configPath = configPath\n }\n}\n","import { z } from 'zod'\n\nimport { servicesConfigSchema } from '../services/index.js'\n\n/**\n * Base bucket config — legacy shape preserved for backwards compatibility.\n */\nconst baseRateLimitSchema = z.object({\n windowMs: z.number().min(1),\n max: z.number().int().min(1),\n})\n\n/**\n * T2.2 — Per-route + per-user rate limit. The new shape adds `routes`\n * (path map), `keyBy`, and `cookieName`. The legacy flat shape is still\n * accepted via the union — see `createRouteRateLimiter` for normalization.\n */\nexport const rateLimitSchema = z.union([\n baseRateLimitSchema,\n z.object({\n default: baseRateLimitSchema.optional(),\n routes: z.record(z.string(), baseRateLimitSchema).optional(),\n keyBy: z\n .union([\n z.enum(['ip', 'session', 'user']),\n z.function().args(z.unknown()).returns(z.string()),\n ])\n .optional(),\n cookieName: z.string().min(1).optional(),\n }),\n])\n\nexport const uploadSchema = z.object({\n maxFileSize: z\n .number()\n .min(1)\n .default(10 * 1024 * 1024), // 10MB\n maxFiles: z.number().int().min(1).default(10),\n maxFieldSize: z\n .number()\n .min(1)\n .default(1 * 1024 * 1024), // 1MB\n})\n\nexport const loggingSchema = z.object({\n level: z.enum(['debug', 'info', 'warn', 'error', 'silent']).default('info'),\n})\n\n/**\n * Cache subsystem config (caching-and-revalidation-plan).\n * Default `cache: undefined` keeps the framework backward-compatible\n * (no engine initialized → no cache primitives available).\n *\n * Setting `cache: {}` opts in with all defaults.\n */\nconst routeRuleSchema = z.object({\n maxAge: z.number().nonnegative().finite().optional(),\n swr: z.number().nonnegative().finite().optional(),\n tags: z.array(z.string()).optional(),\n})\n\nexport const cacheSchema = z.object({\n enabled: z.boolean().default(true),\n /** 'memory' uses InMemoryCacheAdapter; otherwise pass a custom adapter instance. */\n storage: z.union([z.literal('memory'), z.custom<unknown>()]).default('memory'),\n maxEntries: z.number().int().positive().default(1000),\n defaults: z\n .object({\n maxAge: z.number().nonnegative().finite().default(1),\n swr: z.number().nonnegative().finite().optional(),\n cacheErrors: z.boolean().default(false),\n })\n .default({}),\n keyDerivation: z\n .object({\n excludeQuery: z.array(z.string()).optional(),\n sortQuery: z.boolean().default(true),\n lowercaseHost: z.boolean().default(true),\n })\n .default({}),\n routeRules: z.record(z.string(), routeRuleSchema).optional(),\n})\n\n/**\n * Phase 5 — CSRF warn-first (EC-1).\n *\n * 0.2.0 default: `warn`. Existing apps keep working but get structured\n * warnings about every state-mutating request that does not carry the\n * `X-Theo-Action: 1` header. 0.3.0 will flip the default to `strict`.\n *\n * Set explicitly to `strict` to opt into the future default early,\n * or `off` to disable CSRF entirely (only valid when you have another\n * defense — bearer auth, no session cookies, etc).\n */\n/**\n * Phase 6 — Default security headers (D4 / EC-2).\n *\n * 0.2.0 defaults:\n * - CSP in `report-only` mode (EC-2: don't break existing apps)\n * - X-Frame-Options: DENY · X-Content-Type-Options: nosniff\n * - Referrer-Policy: strict-origin-when-cross-origin\n * - HSTS in production only (no TLS on localhost)\n *\n * Users override individual headers, swap CSP to `enforce`, or disable\n * CSP entirely (`csp: false` / `cspMode: 'off'`).\n */\n/**\n * EC-3 — CWE-113 HTTP Response Splitting mitigation.\n *\n * Every string that becomes a header value must reject CR/LF. Apps that\n * derive header values from untrusted input (feature flags, tenant config,\n * URL params) would otherwise let attackers inject Set-Cookie / Location\n * headers via `\\r\\n`. Apply this refinement to every header-bound string\n * field: permissionsPolicy, csp, hsts, referrerPolicy.\n */\nconst headerSafeString = z\n .string()\n .refine((s) => !/[\\r\\n]/.test(s), { message: 'Header value must not contain CR/LF' })\n\nexport const securityHeadersSchema = z.object({\n csp: z.union([headerSafeString, z.literal(false)]).optional(),\n // T6.1 — default flipped from 'report-only' to 'enforce' for 0.3.0.\n // Users who want the old behaviour set `cspMode: 'report-only'`\n // explicitly. See docs/migrating/0.2-to-0.3.md.\n cspMode: z.enum(['enforce', 'report-only', 'off']).default('enforce'),\n hsts: z.union([headerSafeString, z.literal(false)]).optional(),\n frameOptions: z.enum(['DENY', 'SAMEORIGIN']).default('DENY'),\n contentTypeOptions: z.literal('nosniff').default('nosniff'),\n referrerPolicy: headerSafeString.default('strict-origin-when-cross-origin'),\n /**\n * T1.1 — Permissions-Policy directive string. EC-3-refined: rejects CR/LF.\n * Pass `false` to suppress the header.\n */\n permissionsPolicy: z.union([headerSafeString, z.literal(false)]).optional(),\n})\n\n/**\n * T5.1 — Disallowed-routes escalation pattern (Rails-inspired).\n *\n * `routes` accepts string (exact match — trailing slash matters) or\n * RegExp entries. Matched routes that would otherwise emit `csrf.warn`\n * dispatch through `disallowedBehavior` instead:\n * - `'warn'` : no-op vs the default warn-mode behavior\n * - `'raise'` : escalate to 403, even when global `csrf` mode is 'warn'\n *\n * Use to roll out strict mode per-route (e.g., flip /api/auth/* first)\n * without committing the entire surface to strict at once.\n */\nexport const disallowedConfigSchema = z.object({\n routes: z.array(z.union([z.string(), z.instanceof(RegExp)])),\n behavior: z.enum(['warn', 'raise']).default('raise'),\n})\n\n/**\n * T1.2 — CORS configuration.\n *\n * `origins` accepts a single value (`'*'`, string, RegExp, callback) OR an\n * array of (string | RegExp). The spec-violating `origins: '*'` +\n * `credentials: true` combination is rejected at parse time (browsers\n * ignore wildcards when credentials are sent).\n *\n * EC-3 — `allowedHeaders` and `exposedHeaders` entries go through the\n * header-safe refinement (CR/LF rejected — CWE-113 mitigation).\n */\nexport const corsSchema = z\n .object({\n origins: z.union([\n z.literal('*'),\n headerSafeString,\n z.instanceof(RegExp),\n z.array(z.union([headerSafeString, z.instanceof(RegExp)])),\n z.function().args(z.string()).returns(z.boolean()),\n ]),\n methods: z\n .array(z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD']))\n .optional(),\n allowedHeaders: z.array(headerSafeString).optional(),\n exposedHeaders: z.array(headerSafeString).optional(),\n credentials: z.boolean().default(false),\n maxAge: z.number().int().min(0).max(86400).default(600),\n })\n .refine((c) => !(c.origins === '*' && c.credentials), {\n message: 'CORS spec forbids origins:\"*\" with credentials:true — browsers ignore the wildcard',\n })\n\nexport const securitySchema = z.object({\n // T6.1 — default flipped from 'warn' to 'strict' for 0.3.0. Apps that\n // grep their warn-mode logs from 0.2.x already know which endpoints\n // break; opt back into 'warn' globally OR use disallowedRoutes for\n // surgical migration. See docs/migrating/0.2-to-0.3.md.\n csrf: z.enum(['off', 'warn', 'strict']).default('strict'),\n headers: securityHeadersSchema.optional(),\n /** T5.1 — per-route escalation (Rails disallowed_warnings pattern). */\n disallowed: disallowedConfigSchema.optional(),\n /** T1.2 — Cross-Origin Resource Sharing. Single global config; runs first in pipeline. */\n cors: corsSchema.optional(),\n})\n\n/**\n * StorageManager schemas (T1.1 / ADR-0007 D4).\n *\n * `theo.config.ts > storage` declares Postgres servers (credentials), the\n * databases on each server (TheoCloud / managed PG / self-host), and Redis\n * servers. The runtime `StorageManager` consumes this block; adapters\n * (PostgresJobBackend, PostgresConversationStorage, etc.) request pools by\n * database name and never see raw credentials at the call site.\n *\n * EC-1 (DOCUMENT in concept doc T4.1): Zod default strip-unknown mode\n * silently drops typo keys (`databasees` instead of `databases`). The\n * concept doc warns users to use exact names; runtime errors are still\n * actionable (`Database \"X\" not configured`).\n *\n * EC-2 (DEFERRED to use-time): `databases.X.server` references a key in\n * `servers`. Cross-field validation is intentionally NOT enforced at parse\n * time — `StorageManager.usePostgres()` throws an actionable error on the\n * first call with the dangling reference, matching Rails / Nitro behavior.\n */\nconst tlsConfigSchema = z.object({\n rejectUnauthorized: z.boolean().optional(),\n caCert: z.string().optional(),\n clientCert: z.string().optional(),\n clientKey: z.string().optional(),\n})\n\nconst serverConfigSchema = z.object({\n host: z.string().min(1),\n port: z.number().int().positive().max(65535).optional(),\n user: z.string().min(1),\n /** Password may be the empty string (some providers permit it). */\n password: z.string(),\n tls: tlsConfigSchema.optional(),\n})\n\nconst postgresPoolConfigSchema = z.object({\n min: z.number().int().nonnegative().optional(),\n max: z.number().int().positive().optional(),\n connectionTimeoutMillis: z.number().int().positive().optional(),\n idleTimeoutMillis: z.number().int().nonnegative().optional(),\n})\n\nconst postgresDatabaseConfigSchema = z.object({\n /** References a key in `storage.servers`. Resolved at `usePostgres()` call time. */\n server: z.string().min(1),\n database: z.string().min(1),\n pool: postgresPoolConfigSchema.optional(),\n})\n\nconst redisServerConfigSchema = serverConfigSchema.extend({\n db: z.number().int().nonnegative().optional(),\n maxRetriesPerRequest: z.number().int().nonnegative().optional(),\n})\n\nexport const storageSchema = z.object({\n servers: z.record(z.string(), serverConfigSchema).optional(),\n databases: z.record(z.string(), postgresDatabaseConfigSchema).optional(),\n redis: z.record(z.string(), redisServerConfigSchema).optional(),\n})\n\nexport type StorageConfig = z.infer<typeof storageSchema>\n\nexport const theoConfigSchema = z\n .object({\n appDir: z.string().default('app'),\n serverDir: z.string().default('server'),\n /**\n * T2.2 / EC-4 — Build output directory. Must be a relative path inside\n * the project root. Refused absolute or parent-relative paths to prevent\n * `cleanOutDir` from wiping arbitrary locations (defense-in-depth on\n * top of cleanOutDir's runtime EC-3 guard).\n */\n distDir: z\n .string()\n .default('.theo')\n .refine(\n (d) => !/^([A-Za-z]:)?[/\\\\]/.test(d) && !d.startsWith('..'),\n 'distDir must be a relative path inside the project root (e.g., \".theo\")',\n ),\n /**\n * Agent runtime configuration.\n *\n * - `maxRegistries` (T2.3, legacy): dev-mode cleanup of stale\n * `.theokit/agents/<id>/` dirs by mtime. Now superseded by SDK's\n * native registry GC but kept for backward-compat.\n * - `registry` (Phase 6, Production-Readiness #2): forwarded to\n * `Agent.registry.configure()` lazily on first request.\n * * `maxAgents` — LRU cap. MUST be ≥ max-concurrent-active-conversations\n * (EC-17 DOCUMENT): with maxAgents:1 and 2 concurrent chats, LRU evicts\n * mid-stream → SDK aborts with code:'aborted'. Default 100 covers\n * indie/small-team; tune up for high-traffic.\n * * `idleTimeoutMs` — auto-evict idle agents (default 30 min). 0 disables\n * idle eviction (LRU only).\n */\n agents: z\n .object({\n maxRegistries: z.number().int().positive().default(100),\n registry: z\n .object({\n /** LRU cap — MUST be ≥ max-concurrent-active-conversations. */\n maxAgents: z.number().int().positive().max(10_000).default(100),\n /** Idle eviction window in ms. 0 disables idle eviction (LRU only). */\n idleTimeoutMs: z\n .number()\n .int()\n .nonnegative()\n .default(30 * 60_000),\n })\n .optional(),\n })\n .optional(),\n port: z.number().int().min(1).max(65535).default(3000),\n ssr: z.boolean().default(false),\n /** When true (and ssr === true), use renderToPipeableStream with progressive\n * shell flush instead of single-shot renderToString. Opt-in for streaming\n * SSR; default false preserves the current behavior. */\n ssrStreaming: z.boolean().default(false),\n rateLimit: rateLimitSchema.optional(),\n upload: uploadSchema.optional(),\n logging: loggingSchema.optional(),\n security: securitySchema.optional(),\n serialization: z.enum(['json', 'superjson']).default('json'),\n // Plugins are validated structurally at runtime by createPluginRunnerFromConfig.\n // Zod only checks the shape minimally (must be array). Type-level safety is\n // provided through defineConfig at the user surface.\n plugins: z.array(z.unknown()).optional(),\n /** Enable client-side batching of theoFetch calls and the\n * /api/__theo_batch__ server endpoint. */\n batching: z\n .union([z.boolean(), z.object({ max: z.number().int().positive().optional() })])\n .optional(),\n /** T4.1 — Audit log. When `logger` is provided, framework events\n * (csrf.warn, rate-limit.exceeded, session.rotated, csp.violation) are\n * emitted to it. Default: noop. */\n audit: z\n .object({\n logger: z.unknown().optional(),\n })\n .optional(),\n /** TheoUI auto-wire (T2.1). `false` = opt-out; object = explicit theme/fonts;\n * undefined = enabled when @usetheo/ui is detected in node_modules. */\n ui: z\n .union([\n z.literal(false),\n z.object({\n theme: z.enum(['violet-forge', 'noir', 'paper']).optional(),\n fonts: z.enum(['bundled', 'cdn']).optional(),\n }),\n ])\n .optional(),\n /**\n * Cache subsystem (caching-and-revalidation-plan).\n * Default `undefined` keeps caching disabled (backward compatible).\n * Pass `cache: {}` to opt in with defaults.\n */\n cache: cacheSchema.optional(),\n /**\n * Devtools overlay (Phase 0.4.0+ — see docs/plans/devtools-plan.md).\n *\n * - `undefined` (default): devtools auto-injects in `pnpm dev`, NEVER in `vite build`.\n * - `false`: devtools disabled entirely (Vite plugin skips injection even in dev).\n * - `{ ... }`: devtools enabled with explicit defaults (position, theme).\n *\n * Tree-shaken to noop in prod via the dual-export pattern in\n * `packages/theo/src/devtools/index.ts` (EC-17 positive prod check).\n */\n devtools: z\n .union([\n z.literal(false),\n z.object({\n position: z.enum(['top-left', 'top-right', 'bottom-left', 'bottom-right']).optional(),\n theme: z.enum(['light', 'dark', 'system']).optional(),\n }),\n ])\n .optional(),\n /**\n * Informative list of deploy adapters the app supports. Does NOT\n * trigger per-build translations — only the `--target` CLI flag does\n * (EC-201 / ADR D2). If `config.adapters` includes a target NOT\n * matching `--target`, `theokit build` emits a cross-reference note.\n */\n adapters: z.array(z.string()).optional(),\n /**\n * Jobs backend (ADR D3 + T2.1). When configured, every request gets\n * `ctx.queue.enqueue` auto-wired via the outbox lifecycle. Pass a\n * `JobBackend` instance (InMemoryJobBackend, PostgresJobBackend, etc.).\n */\n jobs: z\n .object({\n backend: z.custom<unknown>((v) => typeof v === 'object' && v !== null),\n })\n .optional(),\n /**\n * StorageManager configuration (T1.1 / ADR-0007).\n *\n * Declares Postgres servers + databases + Redis servers. Consumed by\n * `getStorageManager().configure()` at boot via `start.ts`.\n *\n * Default `undefined` means manager exists but is not configured — adapters\n * relying on the manager (PostgresJobBackend.fromStorageManager, etc.) will\n * throw with an actionable error on first use.\n */\n storage: storageSchema.optional(),\n /**\n * Wave 2 — Polyglot services orchestration (T1.1 / ADR-0012/0013/0014/0015).\n *\n * Declarative external sidecar processes (Python FastAPI / Node Hono)\n * that boot alongside the TheoKit TS app. Empty `services: {}` is the\n * default and preserves Wave 1 behavior.\n */\n services: servicesConfigSchema,\n })\n // EC-2 fix: cross-config refine — no service may share TheoKit's web port.\n .refine((cfg) => !Object.values(cfg.services).some((s) => s.port === cfg.port), {\n message: 'service.port collides with TheoKit web port — change one of them',\n path: ['services'],\n })\n\nexport type TheoConfig = z.infer<typeof theoConfigSchema>\n","/**\n * T2.1 — Detect `@usetheo/ui` presence in the user's project.\n *\n * Uses `require.resolve` with explicit `paths` instead of `existsSync` so\n * pnpm-hoist layouts (TheoUI at workspace root, app in `apps/<x>/`) still\n * detect correctly. Returns `{ enabled: false }` on any failure — never throws.\n */\n\n/* eslint-disable security/detect-non-literal-fs-filename --\n * Reads `package.json` of `@usetheo/ui` via filesystem walk under `node_modules`.\n * Paths come from a controlled CLI/config inputs; this is a build-time tool.\n *\n * D13 invariant (ADR 0021): @usetheo/ui is ESM-only by design (`type: \"module\"`,\n * exports['.'] sem `require` condition). Não usar `createRequire(...).resolve()` —\n * `ERR_PACKAGE_PATH_NOT_EXPORTED` em runtime. Usar filesystem walk direto.\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nexport type TheoUiTheme = 'violet-forge' | 'noir' | 'paper'\nexport type TheoUiFonts = 'bundled' | 'cdn'\n\nexport interface TheoUiConfig {\n theme: TheoUiTheme\n fonts: TheoUiFonts\n}\n\nexport interface TheoUiDetectResult {\n enabled: boolean\n config: TheoUiConfig\n}\n\n/**\n * Raw user config shape (from theo.config.ts > ui field).\n * `false` = opt-out (force disabled); object = explicit config; undefined = default.\n */\nexport type RawTheoUiConfig = false | undefined | { theme?: TheoUiTheme; fonts?: TheoUiFonts }\n\n/**\n * Resolve the TheoUI config with defaults applied.\n * `false` → returns disabled defaults (caller checks `enabled`).\n */\nexport function resolveTheoUiConfig(\n raw: { theme?: TheoUiTheme; fonts?: TheoUiFonts } | undefined,\n): TheoUiConfig {\n return {\n theme: raw?.theme ?? 'violet-forge',\n fonts: raw?.fonts ?? 'bundled',\n }\n}\n\n/**\n * Detect whether `@usetheo/ui` is installed under `projectRoot` (or any\n * parent dir via Node module resolution — handles pnpm hoist).\n *\n * EC-1: uses `require.resolve` with `paths: [projectRoot]` not `existsSync`.\n * EC-5: corrupted installs (dir without an importable entry) fall through to disabled.\n * EC-9: theme validation happens in the Zod schema, not here.\n *\n * Note: we resolve a known subpath (`./styles.css`) instead of `./package.json`\n * or the root specifier because (a) `@usetheo/ui` declares `exports` with no\n * CJS entry, so `require.resolve('@usetheo/ui')` fails inside CJS contexts,\n * and (b) `./package.json` is not listed in `exports`. The `styles.css`\n * subpath IS exported and is exactly what entry-client imports — if it\n * resolves, the package is installed and usable.\n */\n/** Resolver fn — abstracted so tests can stub Node's walk-up behavior. */\nexport type SubpathResolver = (specifier: string, projectRoot: string) => boolean\n\n/**\n * D13 invariant: substituir `require.resolve` por filesystem walk que LÊ exports.\n *\n * Specifier shape: `<pkgScope>/<pkgName>/<subpath>` (e.g. `@usetheo/ui/styles.css`)\n * OR `<pkgName>/<subpath>` (e.g. `react/jsx-runtime`).\n *\n * Algoritmo:\n * 1. Walk up node_modules a partir de projectRoot (handle pnpm hoist + workspaces).\n * 2. Em cada candidato, ler package.json + resolver subpath via exports field.\n * 3. Se exports mapeia o subpath, checar existsSync no path mapeado.\n *\n * Mimica resolução ESM Node sem usar createRequire (D13).\n */\nfunction resolveExportSubpath(pkgRoot: string, subpath: string): string | null {\n const pkgJsonPath = join(pkgRoot, 'package.json')\n if (!existsSync(pkgJsonPath)) return null\n try {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8')) as {\n exports?: Record<string, unknown>\n }\n const exportKey = `./${subpath}`\n const exp = pkg.exports?.[exportKey]\n if (!exp) {\n // Fallback: tentar path direto (dist/<subpath> é convenção comum)\n const fallback = join(pkgRoot, 'dist', subpath)\n return existsSync(fallback) ? fallback : null\n }\n // exports value: string OR { import, require, default, types, ... }\n let target: string | undefined\n if (typeof exp === 'string') target = exp\n else if (exp && typeof exp === 'object') {\n const e = exp as { import?: string; default?: string }\n target = e.import ?? e.default\n }\n if (!target) return null\n const cleaned = target.replace(/^\\.\\//, '')\n const candidate = join(pkgRoot, cleaned)\n return existsSync(candidate) ? candidate : null\n } catch {\n return null\n }\n}\n\nconst defaultResolver: SubpathResolver = (specifier, projectRoot) => {\n const parts = specifier.split('/')\n const pkgName = parts[0]?.startsWith('@') && parts.length >= 2\n ? `${parts[0]}/${parts[1]}`\n : parts[0]\n if (!pkgName) return false\n const subpath = specifier.slice(pkgName.length + 1)\n if (!subpath) return false\n // Walk up node_modules (handle pnpm hoist)\n let dir = projectRoot\n for (let depth = 0; depth < 10; depth++) {\n const pkgRoot = join(dir, 'node_modules', ...pkgName.split('/'))\n if (existsSync(pkgRoot)) {\n const resolved = resolveExportSubpath(pkgRoot, subpath)\n if (resolved) return true\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return false\n}\n\n/** Reads `<projectRoot>/package.json` and returns whether `@usetheo/ui`\n * is declared as a (dev)dependency. Conservative gate: pnpm hoist still\n * works because pnpm rewrites the consumer's package.json to include the\n * declared dep, even when the install lives at the workspace root. */\nfunction isDeclaredInPackageJson(projectRoot: string): boolean {\n try {\n const raw = readFileSync(join(projectRoot, 'package.json'), 'utf-8')\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n peerDependencies?: Record<string, string>\n }\n // `||` is intentional — any truthy version string (including '0.0.0')\n // counts as a declaration. `??` would let '' fall through, but version\n // strings are never empty.\n return Boolean(\n pkg.dependencies?.['@usetheo/ui'] ??\n pkg.devDependencies?.['@usetheo/ui'] ??\n pkg.peerDependencies?.['@usetheo/ui'],\n )\n } catch {\n return false\n }\n}\n\nexport function detectTheoUi(\n projectRoot: string,\n rawConfig: RawTheoUiConfig,\n resolver: SubpathResolver = defaultResolver,\n): TheoUiDetectResult {\n const config = resolveTheoUiConfig(typeof rawConfig === 'object' ? rawConfig : undefined)\n\n // Explicit opt-out wins over detection\n if (rawConfig === false) {\n return { enabled: false, config }\n }\n\n // **Conservative gate** — require the dep to be DECLARED in the user's\n // package.json. Stops the monorepo workspace from being detected as\n // having TheoUI inside fixtures that never asked for it (and would\n // 500 on the import).\n if (!isDeclaredInPackageJson(projectRoot)) {\n return { enabled: false, config }\n }\n\n // EC-1 + EC-5: prefer a subpath that's guaranteed to be in `exports`.\n // Try several known subpaths; success on any one means the package is usable.\n const probes = ['@usetheo/ui/styles.css', '@usetheo/ui/fonts.css']\n for (const probe of probes) {\n if (resolver(probe, projectRoot)) {\n return { enabled: true, config }\n }\n }\n return { enabled: false, config }\n}\n","/**\n * T2.1 (architecture-medium-deferrals plan, ADR D2) — `configResolved` hook\n * body extracted from `vite-plugin/index.ts` for SRP.\n *\n * `resolvePluginConfig(projectRoot)` reads `theo.config.ts` and returns a\n * `ResolvedPluginConfig` bag with every field the Vite plugin needs at\n * `configResolved` time. The `configLoadedOnce` flag stays in `index.ts`\n * (caller owns the one-shot semantic).\n *\n * Errors during config load are swallowed silently (matches pre-refactor\n * behavior — config errors are surfaced elsewhere via validate-structure).\n */\n\nimport { loadConfig } from '../config/load-config.js'\nimport type { CorsConfig } from '../server/http/cors.js'\nimport type { AuditLogger } from '../server/observability/audit-log.js'\nimport { createPluginRunnerFromConfig } from '../server/plugins/load-plugins.js'\nimport type { PluginRunner } from '../server/plugins/plugin-runner.js'\nimport type { DisallowedConfig } from '../server/security/csrf.js'\nimport type { SecurityHeadersConfig } from '../server/security/security-headers.js'\nimport { resolveTransformer, type TheoTransformer } from '../server/transformer.js'\n\nimport { detectTheoUi, type TheoUiDetectResult } from './theoui-detect.js'\n\nexport interface ResolvedPluginConfig {\n pluginRunner: PluginRunner | undefined\n transformer: TheoTransformer | undefined\n resolvedBatching: { max?: number } | undefined\n theoUi: TheoUiDetectResult | undefined\n csrfMode: 'off' | 'warn' | 'strict'\n securityHeaders: SecurityHeadersConfig | undefined\n disallowed: DisallowedConfig | undefined\n cors: CorsConfig | undefined\n auditLogger: AuditLogger | undefined\n devtoolsEnabled: boolean\n}\n\n/**\n * Default config when load fails — keeps the plugin running with safe defaults.\n */\nconst DEFAULT_RESOLVED: ResolvedPluginConfig = {\n pluginRunner: undefined,\n transformer: undefined,\n resolvedBatching: undefined,\n theoUi: undefined,\n csrfMode: 'strict',\n securityHeaders: undefined,\n disallowed: undefined,\n cors: undefined,\n auditLogger: undefined,\n devtoolsEnabled: true,\n}\n\nexport async function resolvePluginConfig(projectRoot: string): Promise<ResolvedPluginConfig> {\n try {\n const userConfig = await loadConfig(projectRoot)\n const pluginRunner = await createPluginRunnerFromConfig(userConfig.plugins)\n const transformer = resolveTransformer(userConfig.serialization)\n\n // Batching: Zod admits `boolean | { max?: number }`; normalize to object.\n let resolvedBatching: { max?: number } | undefined\n if (userConfig.batching === true) {\n resolvedBatching = {}\n } else if (typeof userConfig.batching === 'object') {\n resolvedBatching = userConfig.batching\n }\n\n const theoUi = detectTheoUi(projectRoot, userConfig.ui)\n\n // Audit logger — duck-type validation (consumer may pass any shape with `log()`).\n let auditLogger: AuditLogger | undefined\n const maybeLogger = (userConfig as { audit?: { logger?: unknown } }).audit?.logger\n if (maybeLogger && typeof (maybeLogger as { log?: unknown }).log === 'function') {\n auditLogger = maybeLogger as AuditLogger\n }\n\n return {\n pluginRunner,\n transformer,\n resolvedBatching,\n theoUi,\n csrfMode: userConfig.security?.csrf ?? 'strict',\n securityHeaders: userConfig.security?.headers,\n disallowed: userConfig.security?.disallowed,\n cors: userConfig.security?.cors,\n auditLogger,\n devtoolsEnabled: userConfig.devtools !== false,\n }\n } catch {\n // Config load errors are surfaced elsewhere (validate-structure).\n // Return safe defaults so middlewares can run without hooks.\n return DEFAULT_RESOLVED\n }\n}\n","/**\n * T1.2 — Auto-inject the devtools entry `<script>` into served HTML (dev only).\n *\n * Origin: matches the inject-entry-client.ts pattern but for the devtools\n * module. In dev, the Vite plugin's transformIndexHtml hook calls this for\n * every served HTML. In build, this is a no-op.\n *\n * - EC-30: naive `.replace('</head>', ...)` IS used; alternative HTML parser\n * is too heavy for the bug class (user putting `</head>` literal in inline\n * JS is near-zero). Documented in known limitations.\n * - User opt-out via `config.devtools = false` is respected at the plugin\n * level (this function is simply not called).\n *\n * NEVER use dangerouslySetInnerHTML in any devtools component — see plan EC-20.\n */\n\nexport const DEVTOOLS_VIRTUAL_ID = '/@theo/devtools/entry.js'\nexport const DEVTOOLS_RESOLVED_ID = '\\0@theo/devtools/entry.js'\n\nconst SCRIPT_TAG = `<script type=\"module\" src=\"${DEVTOOLS_VIRTUAL_ID}\"></script>`\n\nexport interface InjectDevtoolsResult {\n html: string\n injected: boolean\n warning?: string\n}\n\nexport function injectDevtoolsScript(\n html: string,\n opts: { isDev: boolean; enabled?: boolean },\n): InjectDevtoolsResult {\n // Build mode → no inject\n if (!opts.isDev) return { html, injected: false }\n // User opt-out via config.devtools = false\n if (opts.enabled === false) return { html, injected: false }\n\n // Already present (HMR re-run, user added manually) → idempotent\n if (html.includes(DEVTOOLS_VIRTUAL_ID)) {\n return { html, injected: false }\n }\n\n // Inject before </head> (case-insensitive, first occurrence)\n const headClosePattern = /<\\/head\\s*>/i\n if (headClosePattern.test(html)) {\n return {\n html: html.replace(headClosePattern, (match) => ` ${SCRIPT_TAG}\\n ${match}`),\n injected: true,\n }\n }\n\n // No </head> tag — skip inject + warn (rather than corrupt the HTML)\n return {\n html,\n injected: false,\n warning:\n 'theokit devtools: index.html has no </head> tag; devtools script was NOT injected. Add <head>…</head> to your template to enable devtools.',\n }\n}\n","/**\n * Auto-inject the entry-client `<script>` into served HTML.\n *\n * Origin: a real user (live session) wrote `index.html` without the\n * `<script type=\"module\" src=\"/@theo/entry-client\"></script>` tag. The\n * page rendered SSR perfectly but NO JS ran — every onClick was dead.\n * No error, no warning. An hour of debugging.\n *\n * Fix: the Vite plugin's `transformIndexHtml` hook runs this for every\n * served HTML. If the script is already present (by URL substring match\n * — handles every quoting/ordering variant) the HTML is returned\n * unchanged. Otherwise the script is inserted before `</body>`. If\n * there's no `</body>` at all (malformed HTML), the script is appended\n * at the end and we emit a console.warn in dev.\n */\n\nconst ENTRY_CLIENT_URL = '/@theo/entry-client'\nconst SCRIPT_TAG = `<script type=\"module\" src=\"${ENTRY_CLIENT_URL}\"></script>`\n\nexport interface InjectResult {\n html: string\n injected: boolean\n warning?: string\n}\n\nexport function injectEntryClient(html: string): InjectResult {\n // Detect via URL substring — robust against:\n // <script src='/@theo/entry-client'>\n // <script type=\"module\" src=\"/@theo/entry-client\" />\n // <link rel=\"modulepreload\" href=\"/@theo/entry-client\">\n if (html.includes(ENTRY_CLIENT_URL)) {\n return { html, injected: false }\n }\n\n // Inject before </body> (case-insensitive, first occurrence)\n const bodyClosePattern = /<\\/body\\s*>/i\n if (bodyClosePattern.test(html)) {\n return {\n html: html.replace(bodyClosePattern, (match) => ` ${SCRIPT_TAG}\\n ${match}`),\n injected: true,\n }\n }\n\n // Malformed HTML — append at end and warn\n return {\n html: `${html}\\n${SCRIPT_TAG}`,\n injected: true,\n warning:\n 'theokit: index.html has no </body> tag; entry-client script was appended at end. Add <body>…</body> to your template.',\n }\n}\n","/**\n * Inject `<link rel=\"stylesheet\">` tags into served HTML during DEV.\n *\n * Why this exists (real bug, 2026-05-22): the example chat app had an\n * LCP of 9-16s because the HTML response landed WITHOUT any `<link>` tag\n * for `@usetheo/ui/styles.css`. CSS only loaded after entry-client.js\n * ran the layout import. Browser paint waited for the JS → CSS chain:\n *\n * HTML arrives → browser paints nothing\n * JS bundle arrives → React hydrates → encounters `import 'styles.css'`\n * CSS arrives → browser RE-paints with styles\n *\n * Fix: emit the `<link>` in the HTML head so the browser fetches CSS in\n * PARALLEL with JS. LCP becomes time-to-CSS instead of time-to-JS-exec.\n *\n * DEV-only: in production builds, Vite's SSR pipeline emits the\n * appropriate `<link>` via its own asset manifest (with content hashes).\n * We must not double-inject there.\n */\n\ninterface StylesheetTarget {\n /** Vite dev URL — what the browser hits */\n href: string\n /** node_modules path checked before injection */\n packageRoot: string\n}\n\nconst TARGETS: StylesheetTarget[] = [\n {\n href: '/@id/@usetheo/ui/styles.css',\n packageRoot: '@usetheo/ui',\n },\n]\n\n/**\n * Note (2026-05-23): font preloads were briefly added here to address a\n * \"FOUT-looking\" CLS of 0.39 measured in DevTools. They turned out to\n * be a misdiagnosis — the real cause was a React hydration mismatch\n * from `<StaticRouterProvider hydrate>` emitting a `<script>` inside\n * the React tree (fixed in commit 31506d1).\n *\n * Why we don't preload fonts:\n * - In dev, pnpm hoists @usetheo/ui via `.pnpm/<hash>/...`. The CSS\n * `@font-face` resolves to the real path; our preload would use the\n * symlink path. Browser doesn't dedupe — preload is \"wasted\" and\n * Chrome logs \"preloaded but not used within a few seconds\".\n * - In prod, Vite's SSR bundle emits proper hashed preload metadata\n * for fonts referenced from compiled CSS. Manual preload there\n * would conflict.\n *\n * If a future regression brings back font-related CLS, the right path\n * is `font-display: optional` (no swap) or size-adjust metric matching\n * in @usetheo/ui itself — not framework-side preload.\n */\n\nexport interface InjectStylesheetsResult {\n html: string\n injected: string[]\n}\n\nexport interface InjectStylesheetsOptions {\n /** Only inject in dev (default). Skip when building for production. */\n isDev: boolean\n /** Function that checks whether a package is installed at projectRoot. */\n hasPackage(name: string): boolean\n}\n\nexport function injectStylesheets(\n html: string,\n opts: InjectStylesheetsOptions,\n): InjectStylesheetsResult {\n if (!opts.isDev) return { html, injected: [] }\n\n const tagsToInject: string[] = []\n for (const target of TARGETS) {\n if (!opts.hasPackage(target.packageRoot)) continue\n // Idempotency: skip if href already present\n if (html.includes(target.href)) continue\n tagsToInject.push(`<link rel=\"stylesheet\" href=\"${target.href}\" />`)\n }\n\n if (tagsToInject.length === 0) return { html, injected: [] }\n\n const joined = tagsToInject.join('\\n ')\n // Inject before </head>; fall back to start of <body> if no head close.\n const headClosePattern = /<\\/head\\s*>/i\n if (headClosePattern.test(html)) {\n return {\n html: html.replace(headClosePattern, (match) => ` ${joined}\\n ${match}`),\n injected: tagsToInject,\n }\n }\n\n const bodyOpenPattern = /<body[^>]*>/i\n if (bodyOpenPattern.test(html)) {\n return {\n html: html.replace(bodyOpenPattern, (match) => `${match}\\n ${joined}`),\n injected: tagsToInject,\n }\n }\n\n // Malformed HTML — prepend and trust the browser\n return { html: `${joined}\\n${html}`, injected: tagsToInject }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time tool. Read-only filesystem walks under cwd + node_modules\n * to resolve consumer-side optional deps. Paths are derived from the\n * CLI-controlled cwd and a fixed package name list.\n */\n/**\n * `integrateUseTheoUI(cwd, opts)` — auto-chains the Vite plugins needed\n * for `@usetheo/ui` styling when the consumer has the dep declared.\n *\n * Algorithm (D3 + D5 of the plan):\n * 1. opts.enabled === false → return [].\n * 2. detectPackage('@usetheo/ui') — if absent, return [].\n * 3. opts.consumerTailwindConfig or opts.consumerPostcssConfig set →\n * log info + return []. Consumer-in-control wins (D3).\n * 4. detectPackage('@tailwindcss/vite') — if absent, log warn + return [].\n * 5. Dynamic-import both. Type-check default exports (EC-5). Type-check\n * return shapes (EC-6). If any guard fails, log + return [].\n * 6. Return [tailwindcssPlugin(), useTheoUIPlugin()].\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport type { Plugin } from 'vite'\n\nimport { detectPackage } from './auto-detect.js'\n\nexport interface IntegrateUiOptions {\n /** When `false`, disable auto-config regardless of detection. Default: true. */\n enabled?: boolean\n /** Path to the consumer's tailwind.config.* (any extension), if present. D3 deferral. */\n consumerTailwindConfig?: string\n /** Path to the consumer's postcss.config.* (any extension), if present. D3 deferral. */\n consumerPostcssConfig?: string\n}\n\n/**\n * Resolve a bare specifier to an absolute file URL by walking up from the\n * consumer's `cwd`, scanning `node_modules` directly. Works for ESM-only\n * packages that don't expose a `require` condition (createRequire fails\n * on those). Reads the resolved package.json's `exports.\".\"` field to\n * find the entry. Returns the file:// URL or null if not resolvable.\n */\nfunction resolveConsumerImport(name: string, cwd: string): string | null {\n let dir = cwd\n for (let i = 0; i < 10; i++) {\n const pkgDir = join(dir, 'node_modules', ...name.split('/'))\n const pkgJsonPath = join(pkgDir, 'package.json')\n if (existsSync(pkgJsonPath)) {\n try {\n const raw = readFileSync(pkgJsonPath, 'utf-8')\n const pkg = JSON.parse(raw) as {\n exports?: { '.'?: { import?: string; default?: string } | string }\n main?: string\n module?: string\n }\n let entry: string | undefined\n const dotExport = pkg.exports?.['.']\n if (typeof dotExport === 'string') entry = dotExport\n else if (dotExport && typeof dotExport === 'object') {\n entry = dotExport.import ?? dotExport.default\n }\n entry ??= pkg.module ?? pkg.main\n if (!entry) return null\n // Strip leading ./ then join.\n const cleaned = entry.replace(/^\\.\\//, '')\n return pathToFileURL(join(pkgDir, cleaned)).href\n } catch {\n return null\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n\nfunction isValidPlugin(value: unknown): value is Plugin {\n if (value === null || typeof value !== 'object') return false\n if (Array.isArray(value)) return false\n // Vite Plugin shape: object with a `name: string` field at minimum.\n if (!('name' in value)) return false\n return typeof (value as Record<string, unknown>).name === 'string'\n}\n\n/**\n * Normalize a Vite plugin factory return value into a flat Plugin[].\n *\n * Background: Tailwind v3 returned a single Plugin from its factory.\n * Tailwind v4 (`@tailwindcss/vite@4.x`) returns an ARRAY of 3 plugins\n * (`@tailwindcss/vite:scan` + `:generate:serve` + `:generate:build`).\n * The EC-6 single-Plugin guard rejected the v4 array shape and silently\n * skipped chain integration, causing 0 utilities generated in the\n * consumer's CSS. This normalizer accepts both shapes.\n */\nfunction normalizePluginReturn(value: unknown): Plugin[] | null {\n if (Array.isArray(value)) {\n const result: Plugin[] = []\n for (const entry of value) {\n if (!isValidPlugin(entry)) return null\n result.push(entry)\n }\n return result.length > 0 ? result : null\n }\n if (isValidPlugin(value)) return [value]\n return null\n}\n\n/** Test-only side-door so EC-6 shape guard can be unit-tested directly. */\nexport const _isValidPluginForTest = isValidPlugin\n/** Test-only side-door for the v3/v4 normalizer. */\nexport const _normalizePluginReturnForTest = normalizePluginReturn\n\n// eslint-disable-next-line complexity -- canonical auto-config gate (5 detection branches + 2 import guards + 2 shape guards); flattening to micro-helpers would hide the linear contract\nexport async function integrateUseTheoUI(\n cwd: string,\n opts?: IntegrateUiOptions,\n): Promise<Plugin[]> {\n if (opts?.enabled === false) return []\n\n const uiDetect = detectPackage('@usetheo/ui', cwd)\n if (!uiDetect.installed) return []\n\n // D3 — consumer's manual config wins\n if (opts?.consumerTailwindConfig || opts?.consumerPostcssConfig) {\n // eslint-disable-next-line no-console -- one-line transparency hint; goal is to surface the override path\n console.info(\n `[theokit] Detected your tailwind.config / postcss.config — skipping auto-config. Extend with \\`import preset from '@usetheo/ui/preset'\\` to apply UI theme.`,\n )\n return []\n }\n\n const tailwindDetect = detectPackage('@tailwindcss/vite', cwd)\n if (!tailwindDetect.installed) {\n console.warn(\n `[theokit] @usetheo/ui detected but @tailwindcss/vite is not installed. Run \\`pnpm add -D @tailwindcss/vite\\` to enable styling.`,\n )\n return []\n }\n\n // Explicit chain: @tailwindcss/vite FIRST + @usetheo/ui/vite-plugin\n // with `{ tailwind: false }` (avoids double-add of @tailwindcss/vite).\n //\n // Why resolve via filesystem then import by URL: this module runs from\n // theokit's own dist/, so `await import('@tailwindcss/vite')` would\n // try to resolve from theokit's node_modules — where the consumer's\n // optional deps don't exist. Resolving from the consumer's cwd\n // gives the correct path.\n const tailwindUrl = resolveConsumerImport('@tailwindcss/vite', cwd)\n if (!tailwindUrl) {\n console.warn(\n `[theokit] @tailwindcss/vite installed but its package entry was not resolvable from ${cwd}. Skipping auto-config.`,\n )\n return []\n }\n let tailwindMod: { default?: unknown }\n let uiMod: { default?: unknown }\n try {\n tailwindMod = (await import(tailwindUrl)) as { default?: unknown }\n } catch (err) {\n console.warn(\n `[theokit] @tailwindcss/vite dynamic import failed (${(err as Error).message}). Skipping auto-config.`,\n )\n return []\n }\n // For @usetheo/ui/vite-plugin, resolve via package + subpath:\n // node_modules/@usetheo/ui/dist/vite-plugin.js\n const uiPkgInstalled = detectPackage('@usetheo/ui', cwd)\n const uiPkgDir = uiPkgInstalled.resolvedPath\n ? uiPkgInstalled.resolvedPath.replace(/[\\\\/]package\\.json$/, '')\n : null\n const uiPluginPath = uiPkgDir ? join(uiPkgDir, 'dist', 'vite-plugin.js') : null\n if (!uiPluginPath || !existsSync(uiPluginPath)) {\n console.warn(\n `[theokit] @usetheo/ui/vite-plugin entry not found at ${String(uiPluginPath)}. Skipping auto-config.`,\n )\n return []\n }\n try {\n uiMod = (await import(pathToFileURL(uiPluginPath).href)) as { default?: unknown }\n } catch (err) {\n console.warn(\n `[theokit] @usetheo/ui/vite-plugin dynamic import failed (${(err as Error).message}). Skipping auto-config.`,\n )\n return []\n }\n\n if (typeof tailwindMod.default !== 'function') {\n console.warn(\n `[theokit] @tailwindcss/vite does not expose a default-export function. Skipping auto-config.`,\n )\n return []\n }\n if (typeof uiMod.default !== 'function') {\n console.warn(\n `[theokit] @usetheo/ui/vite-plugin does not expose a default-export function. Skipping auto-config.`,\n )\n return []\n }\n\n let tailwindPlugin: unknown\n let uiPlugin: unknown\n try {\n tailwindPlugin = (tailwindMod.default as () => unknown)()\n } catch (err) {\n console.warn(`[theokit] @tailwindcss/vite() threw: ${(err as Error).message}`)\n return []\n }\n try {\n // Pass { tailwind: false } so the UI plugin skips its internal\n // @tailwindcss/vite chain (we already added it above).\n uiPlugin = (uiMod.default as (opts?: { tailwind?: boolean }) => unknown)({\n tailwind: false,\n })\n } catch (err) {\n console.warn(`[theokit] @usetheo/ui/vite-plugin() threw: ${(err as Error).message}`)\n return []\n }\n\n const tailwindPlugins = normalizePluginReturn(tailwindPlugin)\n if (tailwindPlugins === null) {\n console.warn(\n `[theokit] @tailwindcss/vite returned unexpected shape. Skipping auto-config.`,\n )\n return []\n }\n const uiPlugins = normalizePluginReturn(uiPlugin)\n if (uiPlugins === null) {\n console.warn(\n `[theokit] @usetheo/ui/vite-plugin returned unexpected shape. Skipping auto-config.`,\n )\n return []\n }\n\n return [...tailwindPlugins, ...uiPlugins]\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Reads <projectRoot>/package.json + resolves the target package's own\n * package.json. Paths come from controlled CLI/config inputs; this is a\n * build-time tool, no HTTP.\n */\n/**\n * `detectPackage(name, cwd)` — generalized form of `theoui-detect.ts`.\n *\n * Used by T3.2 `integrateUseTheoUI` to gate auto-config on whether the\n * consumer has `@usetheo/ui` AND `@tailwindcss/vite` installed.\n *\n * Algorithm (same as `theoui-detect.ts` but parameterized):\n * 1. Read `<cwd>/package.json`. Check `dependencies` / `devDependencies` /\n * `peerDependencies` for the package name.\n * 2. If declared, probe `require.resolve('<name>/package.json', { paths: [cwd] })`.\n * Read the resolved package.json to capture `version`.\n * 3. If resolution fails, fall back to probing common entrypoints (so\n * packages whose `exports` doesn't include `./package.json` still\n * detect).\n *\n * NEVER throws. Returns `{installed: false}` on any failure.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nimport type { DetectResult } from './auto-detect-types.js'\n\n/**\n * D13 invariant (ADR 0021): @usetheo/ui is ESM-only by design.\n * NÃO usar `createRequire(...).resolve()` — `ERR_PACKAGE_PATH_NOT_EXPORTED`\n * em runtime para packages que declaram `type:\"module\"` sem `require` condition.\n * Tudo filesystem walk direto.\n */\n\nfunction isDeclared(name: string, projectRoot: string): boolean {\n try {\n const raw = readFileSync(join(projectRoot, 'package.json'), 'utf-8')\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n peerDependencies?: Record<string, string>\n }\n return Boolean(\n pkg.dependencies?.[name] ??\n pkg.devDependencies?.[name] ??\n pkg.peerDependencies?.[name],\n )\n } catch {\n return false\n }\n}\n\n/**\n * D13: filesystem walk pra encontrar package.json (substitui require.resolve).\n * Walks node_modules up to 10 levels (handles pnpm hoist + workspace symlinks).\n */\nfunction resolvePackageJson(name: string, cwd: string): { path: string; version?: string } | null {\n let dir = cwd\n for (let depth = 0; depth < 10; depth++) {\n const pkgJsonPath = join(dir, 'node_modules', ...name.split('/'), 'package.json')\n if (existsSync(pkgJsonPath)) {\n try {\n const raw = readFileSync(pkgJsonPath, 'utf-8')\n const pkg = JSON.parse(raw) as { name?: string; version?: string }\n // Validate package name matches (defesa contra colisão path)\n if (pkg.name === name) {\n return { path: pkgJsonPath, version: pkg.version }\n }\n } catch {\n // continue walking\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n\n/**\n * D13: fallback probe via filesystem (substitui require.resolve).\n * Tenta common entry paths em node_modules. Retorna path do entry achado.\n */\nfunction fallbackProbe(\n name: string,\n cwd: string,\n): { resolvedEntry: string } | null {\n const candidates = ['index.mjs', 'dist/index.mjs', 'dist/index.js', 'index.js']\n let dir = cwd\n for (let depth = 0; depth < 10; depth++) {\n const pkgDir = join(dir, 'node_modules', ...name.split('/'))\n for (const candidate of candidates) {\n const entry = join(pkgDir, candidate)\n if (existsSync(entry)) return { resolvedEntry: entry }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n\n/** Walk up from a resolved entry path until we hit the package's own package.json\n * whose `name` field matches `expectedName`. Returns null on any failure. */\nfunction findOwningPackageJson(entry: string, expectedName: string): { path: string; version?: string } | null {\n let dir = dirname(entry)\n // Bound the walk to ~10 levels to avoid pathological cases.\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'package.json')\n if (existsSync(candidate)) {\n try {\n const raw = readFileSync(candidate, 'utf-8')\n const pkg = JSON.parse(raw) as { name?: string; version?: string }\n if (pkg.name === expectedName) {\n return { path: candidate, version: pkg.version }\n }\n } catch {\n // ignore + continue walking\n }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n return null\n}\n\nexport function detectPackage(name: string, cwd: string): DetectResult {\n if (!isDeclared(name, cwd)) {\n return { installed: false }\n }\n\n const pkgJson = resolvePackageJson(name, cwd)\n if (pkgJson) {\n return {\n installed: true,\n version: pkgJson.version,\n resolvedPath: pkgJson.path,\n }\n }\n\n // Filesystem fallback: ESM-only packages (no `require` condition) can't\n // be resolved by createRequire. Check node_modules directly. The walk\n // upward handles pnpm hoist + workspace symlinks.\n let dir = cwd\n for (let i = 0; i < 10; i++) {\n const nmPath = join(dir, 'node_modules', ...name.split('/'))\n const nmPkgJson = join(nmPath, 'package.json')\n if (existsSync(nmPkgJson)) {\n try {\n const raw = readFileSync(nmPkgJson, 'utf-8')\n const pkg = JSON.parse(raw) as { name?: string; version?: string }\n if (pkg.name === name) {\n return { installed: true, version: pkg.version, resolvedPath: nmPkgJson }\n }\n } catch {\n /* fall through to entry probe */\n }\n return { installed: true }\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n\n // Last-resort fallback — exports doesn't include ./package.json. Walk up from\n // the resolved entry to find the package's own package.json.\n const probe = fallbackProbe(name, cwd)\n if (probe) {\n const owning = findOwningPackageJson(probe.resolvedEntry, name)\n if (owning) {\n return { installed: true, version: owning.version, resolvedPath: owning.path }\n }\n return { installed: true }\n }\n\n return { installed: false }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Resolves theokit's own install directory (the `node_modules/theokit/`).\n * Build-time tool. Read-only check. No HTTP input.\n */\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\n/**\n * Resolve the directory that holds the framework's compiled (or source)\n * subpaths — `client/`, `server/`, `react-query/`, etc.\n *\n * Cases (regression T1.3):\n * - Source mode (`src/vite-plugin/index.ts`) — `currentDir` is\n * `…/src/vite-plugin`. Parent (`…/src`) contains `client/`. Return parent.\n * - Dist mode (`dist/chunk-XYZ.js`) — `currentDir` is `…/dist`. That dir\n * itself contains `client/`. Return currentDir.\n * - Unknown shape — fall back to parent (legacy behavior). The dogfood\n * validator will catch the misconfiguration before runtime.\n *\n * Pure function — no side effects, only filesystem reads via `existsSync`.\n * Exported so the regression test can exercise the branch logic directly.\n */\nexport function resolveTheoRootDir(currentDir: string): string {\n if (existsSync(resolve(currentDir, 'client'))) {\n return currentDir\n }\n return resolve(currentDir, '..')\n}\n","/**\n * T2.2 (architecture-medium-deferrals plan, ADR D2) — SSR dev middleware\n * extracted from `vite-plugin/index.ts` for SRP.\n *\n * `setupSsrDevMiddleware(server, opts)` registers a Connect-style middleware\n * on the Vite dev server that:\n * 1. Skips API, static, and HMR requests (let other middlewares handle).\n * 2. Reads `index.html`, runs `transformIndexHtml`.\n * 3. Generates per-request nonce, applies security headers (CSP + Cache-Control).\n * 4. Calls `ssrLoadModule(VIRTUAL_ENTRY_SERVER_ID).render(url, { nonce })`.\n * 5. Injects rendered HTML (with hydration script) into root div.\n * 6. On error: ssrFixStacktrace + fallback to CSR via `next()`.\n *\n * No-op when `ssrEnabled === false`. Caller's responsibility to gate.\n */\n\nimport { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { ViteDevServer } from 'vite'\n\nimport { generateNonce } from '../server/auth/nonce.js'\nimport {\n applySecurityHeaders,\n type SecurityHeadersConfig,\n} from '../server/security/security-headers.js'\n\ninterface SsrRenderResult {\n html: string\n hydrationData: {\n loaderData?: unknown\n actionData?: unknown\n errors?: unknown\n }\n}\n\ninterface SsrEntryServer {\n render: (\n url: string,\n opts: { nonce: string },\n ) => Promise<SsrRenderResult | { redirect: Response } | string>\n}\n\nfunction isSsrRenderResult(value: unknown): value is SsrRenderResult {\n if (typeof value !== 'object' || value === null) return false\n if (!('html' in value)) return false\n return typeof (value as Record<string, unknown>).html === 'string'\n}\n\nexport interface SsrDevMiddlewareOptions {\n projectRoot: string\n virtualEntryServerId: string\n securityHeaders: SecurityHeadersConfig | undefined\n}\n\n/**\n * Attach the SSR dev middleware to a Vite dev server. Caller decides whether\n * to invoke this based on `ssrEnabled` — this function does not gate.\n */\nexport function setupSsrDevMiddleware(server: ViteDevServer, opts: SsrDevMiddlewareOptions): void {\n server.middlewares.use((req, res, next) => {\n void (async () => {\n const url = req.url ?? '/'\n // Skip API, static, and HMR requests\n if (\n url.startsWith('/api/') ||\n url.startsWith('/@') ||\n url.startsWith('/node_modules/') ||\n url.includes('.')\n ) {\n next()\n return\n }\n\n try {\n const indexPath = resolve(opts.projectRoot, 'index.html')\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- projectRoot is from `theokit dev`'s caller-controlled cwd\n let template = readFileSync(indexPath, 'utf-8')\n template = await server.transformIndexHtml(url, template)\n\n // T4.1 — Generate a per-request nonce and apply security headers BEFORE render.\n // The same nonce flows into React's renderToPipeableStream({ nonce }) so every\n // emitted <script> carries it AND into the CSP script-src directive.\n // EC-3: applySecurityHeaders also forces Cache-Control: private, no-store.\n const nonce = generateNonce()\n applySecurityHeaders(\n res,\n opts.securityHeaders ?? {},\n { production: process.env.NODE_ENV === 'production' },\n { nonce },\n )\n\n const mod = (await server.ssrLoadModule(opts.virtualEntryServerId)) as SsrEntryServer\n const result = await mod.render(url, { nonce })\n\n if (result && typeof result === 'object' && 'redirect' in result) {\n res.writeHead(302, {\n Location: result.redirect.headers.get('location') ?? '/',\n })\n res.end()\n return\n }\n\n // Backward-compat: old render returned string. New shape returns\n // { html, hydrationData } so the framework can emit the hydration\n // data script OUTSIDE the React root (fixes hydration mismatch).\n let ssrHtml: string\n let hydrationScript = ''\n if (typeof result === 'string') {\n ssrHtml = result\n } else if (isSsrRenderResult(result)) {\n ssrHtml = result.html\n const dataJson = JSON.stringify(result.hydrationData).replace(/</g, '\\\\u003c')\n hydrationScript = `<script nonce=\"${nonce}\">window.__staticRouterHydrationData=${dataJson}</script>`\n } else {\n ssrHtml = ''\n }\n const rootDivMatch = /<div id=[\"']root[\"'][^>]*>/.exec(template)\n if (!rootDivMatch) {\n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(template)\n return\n }\n\n const splitIdx = template.indexOf(rootDivMatch[0]) + rootDivMatch[0].length\n const html =\n template.slice(0, splitIdx) + ssrHtml + hydrationScript + template.slice(splitIdx)\n\n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(html)\n } catch (err) {\n server.ssrFixStacktrace(err as Error)\n console.error('[SSR Dev Error]', err)\n // Fallback to CSR\n next()\n return\n }\n })()\n })\n}\n","/**\n * T2.3 (architecture-medium-deferrals plan, ADR D2) — WebSocket upgrade\n * handler extracted from `vite-plugin/index.ts` for SRP.\n *\n * `setupWsUpgrade(server, projectRoot)` scans `server/ws/*` and attaches an\n * upgrade handler to `server.httpServer`. Lazy-imports the `ws` package so\n * non-WS apps don't pay the cost.\n *\n * **EC-1 (architecture-medium-deferrals plan v1.1 MUST FIX):** must tolerate\n * `server.httpServer === null` (Vite middleware mode — embed in Express/etc).\n * Without the guard, dev embeds crash on plugin init. The function exits\n * silently when no httpServer is available; consumer can wire their own.\n *\n * Mirrors the prod surface in `cli/commands/start-websocket-handler.ts` —\n * same `onOpen`/`onMessage`/`onClose`/`onError` handler shape (EC-6 parity).\n */\n\nimport type { IncomingMessage } from 'node:http'\nimport { resolve } from 'node:path'\nimport type { Duplex } from 'node:stream'\n\nimport type { ViteDevServer } from 'vite'\n\nimport { scanWebSocketRoutes } from '../server/scan/ws-scan.js'\n\ninterface WsHandler {\n onOpen?: (ws: unknown, request: unknown) => void | Promise<void>\n onMessage?: (ws: unknown, data: string) => void | Promise<void>\n onClose?: (ws: unknown, code: number, reason: Buffer) => void | Promise<void>\n onError?: (ws: unknown, err: Error) => void | Promise<void>\n}\n\nexport function setupWsUpgrade(server: ViteDevServer, projectRoot: string): void {\n const wsRoutes = scanWebSocketRoutes(resolve(projectRoot, 'server'))\n if (wsRoutes.length === 0) return\n\n // EC-1 — middleware-mode Vite has no httpServer. Silently skip; the host\n // platform owns its own upgrade routing in that case.\n const wsHttpServer = server.httpServer\n if (!wsHttpServer) return\n\n // Lazy-import `ws` so non-WS apps don't pay the cost.\n void import('ws')\n .then(({ WebSocketServer }) => {\n const wss = new WebSocketServer({ noServer: true })\n\n wsHttpServer.on('upgrade', (request: IncomingMessage, socket: Duplex, head: Buffer) => {\n void (async () => {\n const url = request.url ?? '/'\n if (!url.startsWith('/ws/')) return // Let Vite handle HMR etc.\n\n const wsPath = url.split('?')[0]\n const match = wsRoutes.find((r) => r.wsPath === wsPath)\n if (!match) {\n socket.destroy()\n return\n }\n\n try {\n const mod = await server.ssrLoadModule(match.filePath)\n const handler = ((mod as { default?: unknown }).default ?? mod) as WsHandler\n\n wss.handleUpgrade(request, socket, head, (ws) => {\n void handler.onOpen?.(ws, request)\n ws.on('message', (data: Buffer) => {\n void handler.onMessage?.(ws, data.toString())\n })\n ws.on('close', (code: number, reason: Buffer) => {\n void handler.onClose?.(ws, code, reason)\n })\n ws.on('error', (err: Error) => {\n void handler.onError?.(ws, err)\n })\n })\n } catch {\n socket.destroy()\n }\n })()\n })\n })\n .catch(() => {\n console.warn(\n '[Theo] WebSocket routes found but \"ws\" package not installed. Run: npm install ws',\n )\n })\n}\n","/**\n * T3.1 — Vite integration extension API (`defineTheoIntegration`).\n *\n * Build-time extension system (mirrors Astro Integrations). Lets third\n * parties hook into Theo's Vite lifecycle without forking the plugin.\n *\n * Strictly separated from runtime `defineTheoPlugin` (Phase 4) — different\n * concerns, different surfaces. See ADR D7 in the plan.\n */\n\nexport type HookName =\n | 'theo:config:setup'\n | 'theo:build:start'\n | 'theo:build:done'\n | 'theo:dev:start'\n\nexport interface HookContext {\n addVirtualModule?: (id: string, code: string) => void\n addRoute?: (path: string, handler: RouteHandler) => void\n [key: string]: unknown\n}\n\nexport type Hook = (ctx: HookContext) => void | Promise<void>\n\nexport type RouteHandler = (request: Request) => Response | Promise<Response>\n\nexport interface TheoIntegration {\n name: string\n hooks: Partial<Record<HookName, Hook>>\n}\n\n/**\n * Identity factory for type-checking against TheoIntegration shape.\n */\nexport function defineTheoIntegration(integration: TheoIntegration): TheoIntegration {\n return integration\n}\n\nexport class IntegrationVirtualModulePrefixError extends Error {\n constructor(integrationName: string, id: string) {\n super(\n `Integration \"${integrationName}\" tried to addVirtualModule(\"${id}\"). ` +\n `Virtual module IDs must start with \"virtual:integration:${integrationName}/\" ` +\n `to avoid collisions with Theo internals or other integrations.`,\n )\n this.name = 'IntegrationVirtualModulePrefixError'\n }\n}\n\nexport class IntegrationRouteCollisionError extends Error {\n constructor(integrationName: string, path: string) {\n super(\n `Integration \"${integrationName}\" tried to register route \"${path}\", ` +\n `but it conflicts with an existing route. Choose a different path.`,\n )\n this.name = 'IntegrationRouteCollisionError'\n }\n}\n\nexport interface IntegrationRegistryOptions {\n /** Routes already scanned from `server/routes/`. Used to detect collisions. */\n existingRoutes: string[]\n}\n\nexport interface IntegrationRoute {\n path: string\n owner: string\n}\n\nexport interface IntegrationRegistry {\n registerIntegration(integration: TheoIntegration): void\n fire(hookName: HookName, baseCtx: Record<string, unknown>): Promise<void>\n addVirtualModule(integrationName: string, id: string, code: string): void\n addRoute(integrationName: string, path: string, handler: RouteHandler): void\n getVirtualModule(id: string): string | undefined\n listVirtualModules(): string[]\n listRoutes(): IntegrationRoute[]\n /** Test helper: invoke hook surface directly without firing the lifecycle. */\n callHook(\n integrationName: string,\n hookName: HookName,\n extraCtx: Partial<HookContext>,\n ): Promise<void>\n}\n\nexport function createIntegrationRegistry(\n options: IntegrationRegistryOptions,\n): IntegrationRegistry {\n const integrations: TheoIntegration[] = []\n const virtualModules = new Map<string, { code: string; owner: string }>()\n const routes: { path: string; owner: string; handler: RouteHandler }[] = []\n const userRoutes = new Set(options.existingRoutes)\n\n function buildHookCtxFor(integrationName: string, extra: Partial<HookContext>): HookContext {\n return {\n ...extra,\n addVirtualModule: (id: string, code: string) => {\n addVirtualModule(integrationName, id, code)\n },\n addRoute: (path: string, handler: RouteHandler) => {\n addRoute(integrationName, path, handler)\n },\n }\n }\n\n function addVirtualModule(integrationName: string, id: string, code: string): void {\n const expectedPrefix = `virtual:integration:${integrationName}/`\n if (!id.startsWith(expectedPrefix)) {\n throw new IntegrationVirtualModulePrefixError(integrationName, id)\n }\n virtualModules.set(id, { code, owner: integrationName })\n }\n\n function addRoute(integrationName: string, path: string, handler: RouteHandler): void {\n if (userRoutes.has(path)) {\n throw new IntegrationRouteCollisionError(integrationName, path)\n }\n if (routes.some((r) => r.path === path)) {\n throw new IntegrationRouteCollisionError(integrationName, path)\n }\n routes.push({ path, owner: integrationName, handler })\n }\n\n return {\n registerIntegration(integration) {\n integrations.push(integration)\n },\n async fire(hookName, baseCtx) {\n for (const intg of integrations) {\n const hook = intg.hooks[hookName]\n if (!hook) continue\n try {\n await hook(buildHookCtxFor(intg.name, baseCtx))\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err))\n const wrapped = new Error(\n `Integration \"${intg.name}\" hook \"${hookName}\" threw: ${e.message}`,\n )\n ;(wrapped as { cause?: unknown }).cause = e\n throw wrapped\n }\n }\n },\n addVirtualModule,\n addRoute,\n getVirtualModule(id) {\n return virtualModules.get(id)?.code\n },\n listVirtualModules() {\n return Array.from(virtualModules.keys())\n },\n listRoutes() {\n return routes.map((r) => ({ path: r.path, owner: r.owner }))\n },\n // eslint-disable-next-line @typescript-eslint/require-await -- async surface for the public callHook contract\n async callHook(integrationName, _hookName, extraCtx) {\n // Build the ctx for parity with `fire()` so test invocations\n // observe the same shape; we don't actually need the value here.\n buildHookCtxFor(integrationName, extraCtx)\n // Surface for direct test invocation; production code uses fire()\n if (typeof extraCtx.addVirtualModule === 'function') {\n extraCtx.addVirtualModule(\n `virtual:integration:${integrationName}/test`,\n 'export const ok = true',\n )\n }\n },\n }\n}\n"],"mappings":"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","names":["existsSync","resolve","dirname","resolve","existsSync","resolve","resolve","existsSync","existsSync","join","SCRIPT_TAG","existsSync","readFileSync","dirname","join","pathToFileURL","existsSync","readFileSync","dirname","join","join","existsSync","readFileSync","pathToFileURL","dirname","join","existsSync","pathToFileURL","existsSync","resolve","readFileSync","resolve","resolve","readFileSync","resolve","resolve","basename","resolve","existsSync","dirname"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/scan/action-scan.ts","../src/server/_internal/scan-walker.ts","../src/server/scan/scan.ts","../src/server/scan/match.ts","../src/server/scan/ws-scan.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks `serverDir/actions/` derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { existsSync, statSync } from 'node:fs'\nimport { extname, join, relative } from 'node:path'\n\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nexport interface ActionNode {\n filePath: string\n actionPath: string\n}\n\nconst ACTION_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\nexport function scanServerActions(serverDir: string): ActionNode[] {\n const actionsDir = join(serverDir, 'actions')\n if (!existsSync(actionsDir) || !statSync(actionsDir).isDirectory()) {\n return []\n }\n\n const results: ActionNode[] = []\n walkSourceFiles(actionsDir, { extensions: ACTION_EXTENSIONS }, (absPath) => {\n let rel = relative(actionsDir, absPath)\n rel = rel.replace(/\\\\/g, '/')\n rel = rel.slice(0, -extname(rel).length)\n results.push({\n filePath: absPath,\n actionPath: rel,\n })\n })\n return results\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks directories derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { readdirSync } from 'node:fs'\nimport { extname, join, resolve } from 'node:path'\n\n/**\n * Options for walkSourceFiles.\n *\n * Sequential by design — callers (route precedence) depend on insertion\n * order (EC-19 documented decision). Async-callback support is implicit\n * via JavaScript's serial await loop.\n *\n * Tested on macOS + Linux. Windows long-path support not validated (EC-20).\n */\nexport interface WalkOptions {\n /** File extensions to include (e.g., new Set(['.ts', '.tsx'])). */\n extensions: ReadonlySet<string>\n /** Skip directories whose name starts with any of these (default: ['_', '.']). */\n skipPrefixes?: readonly string[]\n}\n\n/**\n * Recursively walk `root`, invoking `onFile(absPath)` for every file matching\n * `opts.extensions`. Directories whose name starts with any `skipPrefixes`\n * char are skipped (defaults to `_` and `.`).\n *\n * Replaces 3 near-identical recursive walkers in scan.ts, action-scan.ts,\n * ws-scan.ts (PV-3 — DRY consolidation). Resolves T3.1 of\n * architecture-review-remediation-plan.\n *\n * Symlink loops are NOT tracked — callers must avoid them or pre-resolve\n * via `fs.realpath`. EC-11 documented but not implemented (rare in dev).\n */\nexport function walkSourceFiles(\n root: string,\n opts: WalkOptions,\n onFile: (absPath: string) => void,\n): void {\n const skipPrefixes = opts.skipPrefixes ?? ['_', '.']\n const visit = (dir: string): void => {\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n // Silently skip unreadable directories — caller controls discoverability\n return\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory() && !skipPrefixes.some((p) => entry.name.startsWith(p))) {\n visit(fullPath)\n } else if (entry.isFile() && opts.extensions.has(extname(entry.name))) {\n onFile(resolve(fullPath))\n }\n }\n }\n visit(root)\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks `serverDir/routes/` derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { existsSync, statSync } from 'node:fs'\nimport { extname, join, relative } from 'node:path'\n\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nimport { compilePattern, type ServerRouteNode } from './match.js'\n\nconst ROUTE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\nfunction fileToRoutePath(filePath: string, routesDir: string): string {\n let rel = relative(routesDir, filePath)\n // Strip extension\n const ext = extname(rel)\n rel = rel.slice(0, -ext.length)\n // Normalize separators\n rel = rel.replace(/\\\\/g, '/')\n // Strip index suffix\n if (rel.endsWith('/index')) {\n rel = rel.slice(0, -6)\n } else if (rel === 'index') {\n rel = ''\n }\n // Replace [...param] with :...param (catch-all, before regular params).\n // Replace [param] with :param. Inputs are file paths bounded by the\n // OS filename limit; the bracket capture is bounded by `]`.\n rel = rel.replace(/\\[\\.\\.\\.([^\\]]+)\\]/g, ':...$1')\n // eslint-disable-next-line sonarjs/slow-regex -- bounded by `]`; input is a single filename\n rel = rel.replace(/\\[([^\\]]+)\\]/g, ':$1')\n return `/api/${rel}`\n}\n\nexport function scanServerRoutes(serverDir: string): ServerRouteNode[] {\n const routesDir = join(serverDir, 'routes')\n if (!existsSync(routesDir) || !statSync(routesDir).isDirectory()) {\n return []\n }\n\n const results: ServerRouteNode[] = []\n walkSourceFiles(routesDir, { extensions: ROUTE_EXTENSIONS }, (absPath) => {\n const routePath = fileToRoutePath(absPath, routesDir)\n const { pattern, paramNames } = compilePattern(routePath)\n results.push({\n filePath: absPath,\n routePath,\n paramNames,\n pattern,\n })\n })\n\n // T1.4 / EC-2 — refuse to scan if a user route collides with the reserved\n // batch endpoint path. User must rename or disable batching.\n const conflicting = results.find((r) => r.routePath === '/api/__theo_batch__')\n if (conflicting) {\n throw new Error(\n `Server route ${conflicting.filePath} resolves to '/api/__theo_batch__' which is reserved for the batch endpoint. Rename the route or disable batching in theo.config.ts.`,\n )\n }\n\n // Sort: static first, then dynamic, then catch-all last\n const isCatchAll = (route: ServerRouteNode) => route.routePath.includes(':...')\n results.sort((a, b) => {\n const aStatic = a.paramNames.length === 0\n const bStatic = b.paramNames.length === 0\n const aCatchAll = isCatchAll(a)\n const bCatchAll = isCatchAll(b)\n\n // Static routes first\n if (aStatic && !bStatic) return -1\n if (!aStatic && bStatic) return 1\n // Catch-all routes last\n if (aCatchAll && !bCatchAll) return 1\n if (!aCatchAll && bCatchAll) return -1\n return a.routePath.localeCompare(b.routePath)\n })\n\n return results\n}\n","export interface ServerRouteNode {\n filePath: string\n routePath: string\n paramNames: string[]\n pattern: RegExp\n}\n\nexport function compilePattern(routePath: string): {\n pattern: RegExp\n paramNames: string[]\n} {\n const paramNames: string[] = []\n // Single pass: handle both catch-all (:...name) and regular (:name) params\n const regexStr = routePath.replace(/:(?:\\.\\.\\.)?([^/]+)/g, (match: string, name: string) => {\n paramNames.push(name)\n // Catch-all matches across slashes, regular matches single segment\n return match.startsWith(':...') ? '(.+)' : '([^/]+)'\n })\n // `regexStr` is derived from a developer-authored route path (build-time\n // input, not HTTP-controlled). The `security/detect-non-literal-regexp`\n // rule cannot see this constraint — disable narrowly.\n // eslint-disable-next-line security/detect-non-literal-regexp -- route pattern from build-time scan, never HTTP input\n return { pattern: new RegExp(`^${regexStr}$`), paramNames }\n}\n\nexport function matchRoute(\n url: string,\n routes: ServerRouteNode[],\n): { route: ServerRouteNode; params: Record<string, string> } | null {\n // Strip query string and trailing slash\n let path = url.split('?')[0]\n if (path.length > 1 && path.endsWith('/')) {\n path = path.slice(0, -1)\n }\n\n for (const route of routes) {\n const match = route.pattern.exec(path)\n if (match) {\n const params: Record<string, string> = {}\n route.paramNames.forEach((name, i) => {\n params[name] = match[i + 1]\n })\n return { route, params }\n }\n }\n return null\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks `serverDir/ws/` derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { existsSync, statSync } from 'node:fs'\nimport { extname, join, relative } from 'node:path'\n\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nconst WS_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\n\nexport interface WebSocketRouteNode {\n filePath: string\n wsPath: string\n}\n\nexport function scanWebSocketRoutes(serverDir: string): WebSocketRouteNode[] {\n const wsDir = join(serverDir, 'ws')\n if (!existsSync(wsDir) || !statSync(wsDir).isDirectory()) {\n return []\n }\n\n const results: WebSocketRouteNode[] = []\n walkSourceFiles(wsDir, { extensions: WS_EXTENSIONS }, (absPath) => {\n let rel = relative(wsDir, absPath)\n rel = rel.replace(/\\\\/g, '/')\n rel = rel.slice(0, -extname(rel).length)\n if (rel.endsWith('/index')) rel = rel.slice(0, -6)\n else if (rel === 'index') rel = ''\n results.push({\n filePath: absPath,\n wsPath: `/ws/${rel}`,\n })\n })\n return results\n}\n"],"mappings":"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","names":["extname","join","join","extname","existsSync","statSync","extname","join","relative","relative","extname","join","existsSync","statSync","existsSync","statSync","extname","join","relative","join","existsSync","statSync","relative","extname"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/scan/manifest.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time manifest emitter / loader. All paths derived from `distDir`\n * + `serverDir`, themselves resolved from `process.cwd()`. No HTTP input.\n */\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { join, resolve, relative } from 'node:path'\n\nimport { scanServerActions } from './action-scan.js'\nimport type { ActionNode } from './action-scan.js'\nimport { compilePattern } from './match.js'\nimport type { ServerRouteNode } from './match.js'\nimport { scanServerRoutes } from './scan.js'\nimport { scanWebSocketRoutes } from './ws-scan.js'\nimport type { WebSocketRouteNode } from './ws-scan.js'\n\n// --- Manifest Types ---\n\nexport interface ManifestRoute {\n filePath: string\n routePath: string\n paramNames: string[]\n}\n\nexport interface ManifestAction {\n filePath: string\n actionPath: string\n}\n\nexport interface ManifestWebSocket {\n filePath: string\n wsPath: string\n}\n\nexport interface TheoManifest {\n version: 1\n generatedAt: string\n routes: ManifestRoute[]\n actions: ManifestAction[]\n websockets: ManifestWebSocket[]\n}\n\nexport interface LoadedManifest {\n routes: ServerRouteNode[]\n actions: ActionNode[]\n websockets: WebSocketRouteNode[]\n}\n\n// --- Generate ---\n\nexport function generateManifest(serverDir: string): TheoManifest {\n const routes = scanServerRoutes(serverDir)\n const actions = scanServerActions(serverDir)\n const websockets = scanWebSocketRoutes(serverDir)\n\n return {\n version: 1,\n generatedAt: new Date().toISOString(),\n routes: routes.map((r) => ({\n filePath: relative(serverDir, r.filePath),\n routePath: r.routePath,\n paramNames: r.paramNames,\n })),\n actions: actions.map((a) => ({\n filePath: relative(serverDir, a.filePath),\n actionPath: a.actionPath,\n })),\n websockets: websockets.map((w) => ({\n filePath: relative(serverDir, w.filePath),\n wsPath: w.wsPath,\n })),\n }\n}\n\n// --- Write ---\n\nexport function writeManifest(manifest: TheoManifest, outputDir: string): void {\n mkdirSync(outputDir, { recursive: true })\n const manifestPath = join(outputDir, 'manifest.json')\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2))\n}\n\n// --- Load ---\n\nexport function loadManifest(distDir: string, serverDir: string): LoadedManifest {\n const manifestPath = join(distDir, 'manifest.json')\n\n if (!existsSync(manifestPath)) {\n throw new Error(`No manifest found at ${manifestPath}. Run \"theo build\" first.`)\n }\n\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8')) as TheoManifest\n\n const routes: ServerRouteNode[] = raw.routes.map((r) => {\n const { pattern, paramNames } = compilePattern(r.routePath)\n return {\n filePath: resolve(serverDir, r.filePath),\n routePath: r.routePath,\n paramNames,\n pattern,\n }\n })\n\n const actions: ActionNode[] = raw.actions.map((a) => ({\n filePath: resolve(serverDir, a.filePath),\n actionPath: a.actionPath,\n }))\n\n const websockets: WebSocketRouteNode[] = raw.websockets.map((w) => ({\n filePath: resolve(serverDir, w.filePath),\n wsPath: w.wsPath,\n }))\n\n return { routes, actions, websockets }\n}\n"],"mappings":";;;;;;;;;;AAIA,SAAS,YAAY,cAAc,eAAe,iBAAiB;AACnE,SAAS,MAAM,SAAS,gBAAgB;AA4CjC,SAAS,iBAAiB,WAAiC;AAChE,QAAM,SAAS,iBAAiB,SAAS;AACzC,QAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAM,aAAa,oBAAoB,SAAS;AAEhD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,QAAQ,OAAO,IAAI,CAAC,OAAO;AAAA,MACzB,UAAU,SAAS,WAAW,EAAE,QAAQ;AAAA,MACxC,WAAW,EAAE;AAAA,MACb,YAAY,EAAE;AAAA,IAChB,EAAE;AAAA,IACF,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,MAC3B,UAAU,SAAS,WAAW,EAAE,QAAQ;AAAA,MACxC,YAAY,EAAE;AAAA,IAChB,EAAE;AAAA,IACF,YAAY,WAAW,IAAI,CAAC,OAAO;AAAA,MACjC,UAAU,SAAS,WAAW,EAAE,QAAQ;AAAA,MACxC,QAAQ,EAAE;AAAA,IACZ,EAAE;AAAA,EACJ;AACF;AAIO,SAAS,cAAc,UAAwB,WAAyB;AAC7E,YAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AACxC,QAAM,eAAe,KAAK,WAAW,eAAe;AACpD,gBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC/D;AAIO,SAAS,aAAa,SAAiB,WAAmC;AAC/E,QAAM,eAAe,KAAK,SAAS,eAAe;AAElD,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,UAAM,IAAI,MAAM,wBAAwB,YAAY,2BAA2B;AAAA,EACjF;AAEA,QAAM,MAAM,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAE1D,QAAM,SAA4B,IAAI,OAAO,IAAI,CAAC,MAAM;AACtD,UAAM,EAAE,SAAS,WAAW,IAAI,eAAe,EAAE,SAAS;AAC1D,WAAO;AAAA,MACL,UAAU,QAAQ,WAAW,EAAE,QAAQ;AAAA,MACvC,WAAW,EAAE;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,UAAwB,IAAI,QAAQ,IAAI,CAAC,OAAO;AAAA,IACpD,UAAU,QAAQ,WAAW,EAAE,QAAQ;AAAA,IACvC,YAAY,EAAE;AAAA,EAChB,EAAE;AAEF,QAAM,aAAmC,IAAI,WAAW,IAAI,CAAC,OAAO;AAAA,IAClE,UAAU,QAAQ,WAAW,EAAE,QAAQ;AAAA,IACvC,QAAQ,EAAE;AAAA,EACZ,EAAE;AAEF,SAAO,EAAE,QAAQ,SAAS,WAAW;AACvC;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/cost/track-agent-run.ts","../src/server/cost/usage-storage-memory.ts","../src/server/cost/track-agent-tools.ts"],"sourcesContent":["import type { UsageRecord, UsageStorageAdapter } from './cost-types.js'\n\nexport interface TrackAgentRunInput {\n userId: string\n model: string\n tokens: { input: number; output: number }\n costUsd: number\n /** Defaults to `new Date()`. */\n timestamp?: Date\n}\n\nexport interface TrackAgentRunOptions {\n /** Adapter resolved from `theo.config.ts > cost.storage`. */\n storage: UsageStorageAdapter | undefined\n}\n\n/**\n * Record a single agent run's usage + cost. Companion to the client-side\n * `<CostMeter>` from `@usetheo/ui`.\n *\n * EC-14: this function NEVER bubbles errors back to the caller. Adapter\n * failures (network outage, DB down, etc.) are logged via `console.warn`\n * and swallowed. The agent response MUST NOT fail because cost tracking\n * is degraded.\n *\n * No-op when `storage` is undefined (cost tracking unconfigured).\n *\n * @see docs/concepts/cost-tracking.md (when implemented in T6.3)\n */\nexport async function trackAgentRun(\n input: TrackAgentRunInput,\n opts: TrackAgentRunOptions,\n): Promise<void> {\n if (!opts.storage) return\n const record: UsageRecord = {\n userId: input.userId,\n model: input.model,\n tokens: input.tokens,\n costUsd: input.costUsd,\n timestamp: input.timestamp ?? new Date(),\n }\n try {\n await opts.storage.record(record)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n\n console.warn(\n `[theokit:cost] usage storage record failed: ${message}. ` +\n '(Response is unaffected — cost tracking degraded.)',\n )\n }\n}\n","import type { StorageAdapter } from '../storage/storage-types.js'\n\nimport type {\n ToolUsageRecord,\n UsageQuery,\n UsageRecord,\n UsageResult,\n UsageStorageAdapter,\n} from './cost-types.js'\n\n/**\n * In-memory usage storage for dev/tests. Unbounded — production\n * deployments MUST plug in a durable adapter (Postgres/Redis recipes\n * land with R0.6.7; documented in EC-114).\n *\n * Phase 5 — Production-Readiness #4: accepts both `UsageRecord` (LLM call,\n * kind='llm' or omitted) AND `ToolUsageRecord` (tool call, kind='tool').\n * `getUsage` only sums LLM records (tools have no token/cost dimension).\n *\n * EC-9 (backward compat): input without `kind` is normalized to `kind:'llm'`\n * — adapters from older versions stay working.\n *\n * Concurrency: Node's single-threaded event loop guarantees that\n * `Array.push` is atomic, so concurrent record() calls cannot lose data.\n */\nexport class InMemoryUsageStorage implements UsageStorageAdapter, StorageAdapter {\n readonly name = 'memory'\n readonly #records: (UsageRecord | ToolUsageRecord)[] = []\n\n /**\n * T2.3 — `StorageAdapter` lifecycle hook (ADR-0007 D6). In-memory storage\n * has no real cleanup to perform — this is intentionally a noop so the\n * adapter can be registered with `StorageManager.register()` and\n * participate in graceful shutdown without changing behavior.\n *\n * Does NOT clear stored records (dispose ≠ reset). For test reset use\n * a fresh instance.\n */\n dispose(): Promise<void> {\n // Intentional noop — see jsdoc above\n return Promise.resolve()\n }\n\n async record(input: UsageRecord | ToolUsageRecord): Promise<void> {\n // EC-9: normalize legacy input (no `kind` field) to kind:'llm'.\n const normalized: UsageRecord | ToolUsageRecord =\n 'kind' in input && input.kind === 'tool'\n ? { ...input }\n : ({ ...input, kind: 'llm' as const } satisfies UsageRecord)\n this.#records.push(normalized)\n return Promise.resolve()\n }\n\n async getUsage(query: UsageQuery): Promise<UsageResult> {\n const from = query.period.from.getTime()\n const to = query.period.to.getTime()\n let totalTokens = 0\n let totalCostUsd = 0\n let runs = 0\n for (const r of this.#records) {\n if (r.kind === 'tool') continue\n if (r.userId !== query.userId) continue\n const t = r.timestamp.getTime()\n if (t < from || t > to) continue\n totalTokens += r.tokens.input + r.tokens.output\n totalCostUsd += r.costUsd\n runs += 1\n }\n return Promise.resolve({ totalTokens, totalCostUsd, runs })\n }\n\n /** @internal — test helper to inspect raw record stream */\n __getRecords(): readonly (UsageRecord | ToolUsageRecord)[] {\n return this.#records\n }\n}\n","import type { ToolUsageRecord, UsageStorageAdapter } from './cost-types.js'\n\n/**\n * Phase 5 — Production-Readiness #4: tool lifecycle hooks for cost tracking.\n *\n * The SDK calls `onToolStart` → handler runs → `onToolEnd` (success) or\n * `onToolError` (throw). This factory returns the three callbacks ready to\n * attach to `Agent.create({ tools, onToolStart, onToolEnd, onToolError })`.\n *\n * Each successful tool call writes a `ToolUsageRecord{success:true}`; each\n * failure writes `ToolUsageRecord{success:false}` with `errorMessage` from\n * the thrown Error.\n *\n * Invariants:\n * - `onToolStart` records nothing yet (no duration available). Only stashes\n * a `startedAt` timestamp by `callId` in a per-factory Map.\n * - `onToolEnd` reads the stashed timestamp, computes `durationMs`, writes\n * a successful record. Removes the Map entry.\n * - `onToolError` analog with `success:false`.\n * - Hook throws are SWALLOWED to stderr — observation hooks must not crash\n * the run (per the v1.1.0 release contract).\n * - EC-8 (SHOULD TEST) — orphan starts (no matching End/Error) are pruned\n * on every onToolStart if older than 5 minutes. Bounded memory.\n * - EC-16 (DOCUMENT) — callId uniqueness is SDK contract; duplicate Start\n * for the same callId uses last-write-wins.\n */\n\nconst ORPHAN_TTL_MS = 5 * 60 * 1000\n\ninterface PendingStart {\n startedAt: number\n userId: string\n conversationId: string\n}\n\nexport interface TrackAgentToolsOptions {\n storage: UsageStorageAdapter\n /** Defaults to () => new Date() — overridable for deterministic testing. */\n now?: () => Date\n /** Identifier for the user — passed through to ToolUsageRecord.userId. */\n userId?: string\n /** Identifier for the conversation — passed through to ToolUsageRecord.conversationId. */\n conversationId?: string\n}\n\nexport interface ToolHookEvent {\n callId: string\n name: string\n // SDK shape — we only read these structurally\n [key: string]: unknown\n}\n\nexport interface TrackAgentToolsHooks {\n onToolStart: (event: ToolHookEvent) => void\n onToolEnd: (event: ToolHookEvent) => void\n onToolError: (event: ToolHookEvent) => void\n}\n\n/**\n * Create the three tool-lifecycle callbacks. Hand the returned object's\n * methods to `Agent.create({ tools, onToolStart, onToolEnd, onToolError })`.\n */\nexport function trackAgentTools(opts: TrackAgentToolsOptions): TrackAgentToolsHooks {\n const pending = new Map<string, PendingStart>()\n const now = opts.now ?? ((): Date => new Date())\n const userId = opts.userId ?? 'anonymous'\n const conversationId = opts.conversationId ?? 'unknown'\n\n function pruneOrphans(): void {\n const cutoff = now().getTime() - ORPHAN_TTL_MS\n for (const [id, p] of pending) {\n if (p.startedAt < cutoff) pending.delete(id)\n }\n }\n\n function safeRecord(record: ToolUsageRecord): void {\n Promise.resolve(opts.storage.record(record)).catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`[theokit:trackAgentTools] storage.record failed: ${msg}`)\n })\n }\n\n return {\n onToolStart(event: ToolHookEvent): void {\n try {\n pruneOrphans()\n pending.set(event.callId, {\n startedAt: now().getTime(),\n userId,\n conversationId,\n })\n } catch (err) {\n console.warn(\n `[theokit:trackAgentTools] onToolStart hook crashed (swallowed): ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n }\n },\n onToolEnd(event: ToolHookEvent): void {\n try {\n const start = pending.get(event.callId)\n const startedAt = start?.startedAt ?? now().getTime()\n const durationMs = start ? now().getTime() - startedAt : 0\n pending.delete(event.callId)\n if (!start) {\n console.warn(\n `[theokit:trackAgentTools] orphan onToolEnd for callId=${event.callId}; durationMs:0 recorded`,\n )\n }\n safeRecord({\n kind: 'tool',\n userId: start?.userId ?? userId,\n conversationId: start?.conversationId ?? conversationId,\n toolName: event.name,\n callId: event.callId,\n success: true,\n durationMs,\n timestamp: now(),\n })\n } catch (err) {\n console.warn(\n `[theokit:trackAgentTools] onToolEnd hook crashed (swallowed): ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n }\n },\n onToolError(event: ToolHookEvent): void {\n try {\n const start = pending.get(event.callId)\n const startedAt = start?.startedAt ?? now().getTime()\n const durationMs = start ? now().getTime() - startedAt : 0\n pending.delete(event.callId)\n const error = event.error\n let errorMessage = 'unknown error'\n if (error instanceof Error) errorMessage = error.message\n else if (typeof error === 'string') errorMessage = error\n safeRecord({\n kind: 'tool',\n userId: start?.userId ?? userId,\n conversationId: start?.conversationId ?? conversationId,\n toolName: event.name,\n callId: event.callId,\n success: false,\n durationMs,\n errorMessage,\n timestamp: now(),\n })\n } catch (err) {\n console.warn(\n `[theokit:trackAgentTools] onToolError hook crashed (swallowed): ${\n err instanceof Error ? err.message : String(err)\n }`,\n )\n }\n },\n }\n}\n\n/**\n * @internal — testing helper. Inspects the size of the pending-starts Map of\n * a factory instance. Not in the public API.\n */\nexport const __internalsForTesting = {\n ORPHAN_TTL_MS,\n}\n"],"mappings":"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","names":[]}
|