theokit 0.48.2 → 0.48.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/LICENSE +2 -2
  2. package/dist/{actions-virtual-module-2VVLVXHY.js → actions-virtual-module-GB5FWUPS.js} +6 -6
  3. package/dist/{actions-virtual-module-Z5LXAX7E.js → actions-virtual-module-YQXRSSMW.js} +2 -2
  4. package/dist/add-3VLFUPF4.js +0 -0
  5. package/dist/{agent-Y3JKRROD.js → agent-OAFIXOR5.js} +2 -2
  6. package/dist/{agents-typed-client-X56CQ6FX.js → agents-typed-client-D4OA2TXB.js} +12 -4
  7. package/dist/agents-typed-client-D4OA2TXB.js.map +1 -0
  8. package/dist/{agents-typed-client-TNHCUU7Q.js → agents-typed-client-INR2E7B3.js} +12 -4
  9. package/dist/agents-typed-client-INR2E7B3.js.map +1 -0
  10. package/dist/{app-typed-client-N4I4RBLT.js → app-typed-client-5QDNHANF.js} +6 -6
  11. package/dist/{app-typed-client-NI3CM2FA.js → app-typed-client-GHO3EWZK.js} +2 -2
  12. package/dist/{aws-lambda-7SUTORXM.js → aws-lambda-CYNDGU5O.js} +3 -3
  13. package/dist/body-parser-web-TIOTXPDW.js +0 -0
  14. package/dist/broadcast-LUMOJIJT.js +0 -0
  15. package/dist/{build-SJQDRD2B.js → build-QYEU5OOZ.js} +13 -12
  16. package/dist/build-QYEU5OOZ.js.map +1 -0
  17. package/dist/build-request-body-preview-XPZ2GYMG.js +0 -0
  18. package/dist/{bun-TLYZCEGE.js → bun-33RD6K7O.js} +3 -3
  19. package/dist/check-45NKUVSQ.js +0 -0
  20. package/dist/chunk-2CVV6CNN.js +0 -0
  21. package/dist/{chunk-ORKNVORZ.js → chunk-47CINLWF.js} +2 -2
  22. package/dist/chunk-47VNWTL4.js +0 -0
  23. package/dist/chunk-5ODOE6EF.js +0 -0
  24. package/dist/chunk-6GGWS7J3.js +0 -0
  25. package/dist/{chunk-O5W7XSUX.js → chunk-6PWNTTPI.js} +4 -4
  26. package/dist/{chunk-GEHX6CAE.js → chunk-6RJSGTMN.js} +3 -3
  27. package/dist/{chunk-GEHX6CAE.js.map → chunk-6RJSGTMN.js.map} +1 -1
  28. package/dist/{chunk-HRCNHWLP.js → chunk-7CQ6DEWZ.js} +2 -2
  29. package/dist/{chunk-YRRWQDKK.js → chunk-7QAYC757.js} +89 -14
  30. package/dist/chunk-7QAYC757.js.map +1 -0
  31. package/dist/{chunk-CUYEA62B.js → chunk-7VPQHEAJ.js} +2 -4
  32. package/dist/chunk-7VPQHEAJ.js.map +1 -0
  33. package/dist/{chunk-5JJCNEUS.js → chunk-A4ZEP3FE.js} +17 -8
  34. package/dist/chunk-A4ZEP3FE.js.map +1 -0
  35. package/dist/chunk-A7JBF5FO.js +0 -0
  36. package/dist/{chunk-MNIQ5F3Y.js → chunk-BMHS4WAN.js} +1 -1
  37. package/dist/{chunk-MNIQ5F3Y.js.map → chunk-BMHS4WAN.js.map} +1 -1
  38. package/dist/{chunk-DGQO372T.js → chunk-E576KYYT.js} +3 -3
  39. package/dist/chunk-E576KYYT.js.map +1 -0
  40. package/dist/{chunk-L5Z6IY5U.js → chunk-FNTLKHZ7.js} +1 -1
  41. package/dist/{chunk-L5Z6IY5U.js.map → chunk-FNTLKHZ7.js.map} +1 -1
  42. package/dist/chunk-GEQJAFSV.js +0 -0
  43. package/dist/{chunk-AOGYAXPY.js → chunk-GH32R55S.js} +2 -2
  44. package/dist/{chunk-Y2KHTD2W.js → chunk-GQNBZDYK.js} +1 -1
  45. package/dist/{chunk-Y2KHTD2W.js.map → chunk-GQNBZDYK.js.map} +1 -1
  46. package/dist/{chunk-VTJMND23.js → chunk-H6YBKIUN.js} +2 -2
  47. package/dist/chunk-HBU2GIMZ.js +0 -0
  48. package/dist/chunk-IEES3CHD.js +0 -0
  49. package/dist/{chunk-62EU2BVZ.js → chunk-J5MXCGKA.js} +1 -1
  50. package/dist/{chunk-62EU2BVZ.js.map → chunk-J5MXCGKA.js.map} +1 -1
  51. package/dist/{chunk-HNBWZKIQ.js → chunk-KTMQUYED.js} +1 -1
  52. package/dist/{chunk-HNBWZKIQ.js.map → chunk-KTMQUYED.js.map} +1 -1
  53. package/dist/chunk-LNVMHQ2Z.js +0 -0
  54. package/dist/{chunk-2ADKT37V.js → chunk-LXAESF4Y.js} +2 -2
  55. package/dist/{chunk-2ADKT37V.js.map → chunk-LXAESF4Y.js.map} +1 -1
  56. package/dist/{chunk-FXZZS7YW.js → chunk-T5C46IIU.js} +1 -1
  57. package/dist/chunk-T5C46IIU.js.map +1 -0
  58. package/dist/{chunk-ZALJIZH2.js → chunk-VQ62FIQW.js} +80 -16
  59. package/dist/chunk-VQ62FIQW.js.map +1 -0
  60. package/dist/chunk-VQIUTCK2.js +0 -0
  61. package/dist/{chunk-FO55VGMQ.js → chunk-XR74JD4M.js} +1 -1
  62. package/dist/{chunk-FO55VGMQ.js.map → chunk-XR74JD4M.js.map} +1 -1
  63. package/dist/{chunk-KSZGBUTI.js → chunk-YGAXV5HR.js} +1 -1
  64. package/dist/{chunk-KSZGBUTI.js.map → chunk-YGAXV5HR.js.map} +1 -1
  65. package/dist/{chunk-D3425YDV.js → chunk-ZB7D62OA.js} +2 -2
  66. package/dist/cli/index.js +14 -14
  67. package/dist/cli/index.js.map +1 -1
  68. package/dist/{cloudflare-JTBKOX3F.js → cloudflare-KYUWCEPL.js} +3 -3
  69. package/dist/configure-agent-registry-ZOBVU3MV.js +0 -0
  70. package/dist/controller-swc-transform-LUJ4VAZJ.js +0 -0
  71. package/dist/db-IVVCQE5Z.js +0 -0
  72. package/dist/{define-websocket-CPQcQK9h.d.ts → define-websocket-DzPn1sR6.d.ts} +0 -1
  73. package/dist/{deno-deploy-3ESNGYZU.js → deno-deploy-CCTB7HGS.js} +3 -3
  74. package/dist/{dev-6TWDBX6G.js → dev-5BKIKJYI.js} +12 -12
  75. package/dist/{dev-emit-7ZZRTYF3.js → dev-emit-GWD6IXV7.js} +3 -3
  76. package/dist/{dev-emit-E5Z26AMV.js → dev-emit-NBT6JD7R.js} +2 -2
  77. package/dist/dispatcher-KMZBGMM5.js +0 -0
  78. package/dist/docker-LZZB4D5E.js +0 -0
  79. package/dist/doctor-Y53QTUSP.js +0 -0
  80. package/dist/{generate-WQSNW4F6.js → generate-Y3GWM57K.js} +2 -2
  81. package/dist/generate-Y3GWM57K.js.map +1 -0
  82. package/dist/index.d.ts +36 -8
  83. package/dist/index.js +3 -3
  84. package/dist/{info-QB7Q3SHP.js → info-MSBQ72EM.js} +4 -4
  85. package/dist/{internal-api-XQA2L663.js → internal-api-ICU7ITJD.js} +6 -6
  86. package/dist/{internal-api-REGN3WMX.js → internal-api-WEOSTMSN.js} +2 -2
  87. package/dist/{load-config-JKJ73TOD.js → load-config-2LP2OEKD.js} +4 -4
  88. package/dist/{mcp-CO4AGAXV.js → mcp-4FNNCFPM.js} +3 -3
  89. package/dist/{netlify-OFJUYXTZ.js → netlify-AFMDNKT4.js} +3 -3
  90. package/dist/node-ZJQEJSP3.js +10 -0
  91. package/dist/{openapi-5CZCL7YP.js → openapi-FWNYHB6T.js} +10 -10
  92. package/dist/{openapi-5CZCL7YP.js.map → openapi-FWNYHB6T.js.map} +1 -1
  93. package/dist/registry-UJ6KNQPJ.js +23 -0
  94. package/dist/{router-6MAACS25.js → router-V64GKAS6.js} +1 -1
  95. package/dist/router-V64GKAS6.js.map +1 -0
  96. package/dist/{routes-GWAWUVVQ.js → routes-6AMNVFMI.js} +5 -5
  97. package/dist/scan-7MJC6PYU.js +0 -0
  98. package/dist/{schema-BpH6ivDY.d.ts → schema-BdakLtuC.d.ts} +1 -1
  99. package/dist/{schema-2JEG6TTU.js → schema-Z3Y7SFLE.js} +3 -7
  100. package/dist/server/agent/index.d.ts +1 -1
  101. package/dist/server/cost/index.d.ts +0 -3
  102. package/dist/server/cost/index.js +1 -1
  103. package/dist/server/cron/index.d.ts +0 -4
  104. package/dist/server/cron/index.js +1 -1
  105. package/dist/server/define/index.d.ts +2 -3
  106. package/dist/server/define/index.js +1 -1
  107. package/dist/server/index.d.ts +4 -6
  108. package/dist/server/index.js +6 -6
  109. package/dist/server/index.js.map +1 -1
  110. package/dist/server/jobs/index.d.ts +1 -4
  111. package/dist/server/jobs/index.js +1 -1
  112. package/dist/server/realtime/index.d.ts +1 -1
  113. package/dist/server/scan/index.js +1 -1
  114. package/dist/server/storage/index.d.ts +1 -1
  115. package/dist/server/webhook/index.d.ts +2 -2
  116. package/dist/server-error-to-envelope-4TGCDQ2S.js +0 -0
  117. package/dist/{server-routes-hmr-4W5L2MKN.js → server-routes-hmr-5D2ZPL74.js} +1 -1
  118. package/dist/server-routes-hmr-5D2ZPL74.js.map +1 -0
  119. package/dist/{server-routes-hmr-6CRNSEWF.js → server-routes-hmr-BWN3WIGR.js} +1 -1
  120. package/dist/{server-routes-hmr-6CRNSEWF.js.map → server-routes-hmr-BWN3WIGR.js.map} +1 -1
  121. package/dist/services-json-7ZXJ4CIS.js +0 -0
  122. package/dist/{services-typed-client-II7LKXKO.js → services-typed-client-PSAGRPFF.js} +2 -2
  123. package/dist/{sessions-gc-H4WC4IXB.js → sessions-gc-VAZR654G.js} +3 -3
  124. package/dist/sessions-gc-VAZR654G.js.map +1 -0
  125. package/dist/{start-IO3ZYGEX.js → start-QDPYXPW2.js} +14 -14
  126. package/dist/start-QDPYXPW2.js.map +1 -0
  127. package/dist/{static-HTT2WNIT.js → static-R25HSXEF.js} +3 -3
  128. package/dist/{storage-manager-ZSQFLEYT.js → storage-manager-3O5PDO6O.js} +1 -1
  129. package/dist/storage-manager-3O5PDO6O.js.map +1 -0
  130. package/dist/{storage-manager-C4jsO0Tp.d.ts → storage-manager-C6hmsaer.d.ts} +1 -1
  131. package/dist/{theo-cloud-ZTQLXGPS.js → theo-cloud-XAHWOUFK.js} +2 -2
  132. package/dist/{upgrade-readiness-77P6VNB4.js → upgrade-readiness-OILJRFOV.js} +1 -1
  133. package/dist/{upgrade-readiness-77P6VNB4.js.map → upgrade-readiness-OILJRFOV.js.map} +1 -1
  134. package/dist/{vercel-72HFEMJ3.js → vercel-SRS2DH6O.js} +3 -3
  135. package/dist/vite-plugin/index.d.ts +1 -1
  136. package/dist/vite-plugin/index.js +3 -3
  137. package/dist/{vite-plugin-NQ6F7FGV.js → vite-plugin-YOCPU4C6.js} +11 -11
  138. package/dist/{webhook-types-CNUZY7o1.d.ts → webhook-types-DGIjjcaI.d.ts} +0 -2
  139. package/package.json +11 -10
  140. package/dist/agents-typed-client-TNHCUU7Q.js.map +0 -1
  141. package/dist/agents-typed-client-X56CQ6FX.js.map +0 -1
  142. package/dist/build-SJQDRD2B.js.map +0 -1
  143. package/dist/chunk-5JJCNEUS.js.map +0 -1
  144. package/dist/chunk-CUYEA62B.js.map +0 -1
  145. package/dist/chunk-DGQO372T.js.map +0 -1
  146. package/dist/chunk-FXZZS7YW.js.map +0 -1
  147. package/dist/chunk-YRRWQDKK.js.map +0 -1
  148. package/dist/chunk-ZALJIZH2.js.map +0 -1
  149. package/dist/generate-WQSNW4F6.js.map +0 -1
  150. package/dist/node-ND4MJU3Z.js +0 -10
  151. package/dist/registry-QTSMLOVG.js +0 -23
  152. package/dist/router-6MAACS25.js.map +0 -1
  153. package/dist/server-routes-hmr-4W5L2MKN.js.map +0 -1
  154. package/dist/sessions-gc-H4WC4IXB.js.map +0 -1
  155. package/dist/start-IO3ZYGEX.js.map +0 -1
  156. package/dist/storage-manager-ZSQFLEYT.js.map +0 -1
  157. /package/dist/{actions-virtual-module-2VVLVXHY.js.map → actions-virtual-module-GB5FWUPS.js.map} +0 -0
  158. /package/dist/{actions-virtual-module-Z5LXAX7E.js.map → actions-virtual-module-YQXRSSMW.js.map} +0 -0
  159. /package/dist/{agent-Y3JKRROD.js.map → agent-OAFIXOR5.js.map} +0 -0
  160. /package/dist/{app-typed-client-N4I4RBLT.js.map → app-typed-client-5QDNHANF.js.map} +0 -0
  161. /package/dist/{app-typed-client-NI3CM2FA.js.map → app-typed-client-GHO3EWZK.js.map} +0 -0
  162. /package/dist/{aws-lambda-7SUTORXM.js.map → aws-lambda-CYNDGU5O.js.map} +0 -0
  163. /package/dist/{bun-TLYZCEGE.js.map → bun-33RD6K7O.js.map} +0 -0
  164. /package/dist/{chunk-ORKNVORZ.js.map → chunk-47CINLWF.js.map} +0 -0
  165. /package/dist/{chunk-O5W7XSUX.js.map → chunk-6PWNTTPI.js.map} +0 -0
  166. /package/dist/{chunk-HRCNHWLP.js.map → chunk-7CQ6DEWZ.js.map} +0 -0
  167. /package/dist/{chunk-AOGYAXPY.js.map → chunk-GH32R55S.js.map} +0 -0
  168. /package/dist/{chunk-VTJMND23.js.map → chunk-H6YBKIUN.js.map} +0 -0
  169. /package/dist/{chunk-D3425YDV.js.map → chunk-ZB7D62OA.js.map} +0 -0
  170. /package/dist/{cloudflare-JTBKOX3F.js.map → cloudflare-KYUWCEPL.js.map} +0 -0
  171. /package/dist/{deno-deploy-3ESNGYZU.js.map → deno-deploy-CCTB7HGS.js.map} +0 -0
  172. /package/dist/{dev-6TWDBX6G.js.map → dev-5BKIKJYI.js.map} +0 -0
  173. /package/dist/{dev-emit-7ZZRTYF3.js.map → dev-emit-GWD6IXV7.js.map} +0 -0
  174. /package/dist/{dev-emit-E5Z26AMV.js.map → dev-emit-NBT6JD7R.js.map} +0 -0
  175. /package/dist/{info-QB7Q3SHP.js.map → info-MSBQ72EM.js.map} +0 -0
  176. /package/dist/{internal-api-XQA2L663.js.map → internal-api-ICU7ITJD.js.map} +0 -0
  177. /package/dist/{internal-api-REGN3WMX.js.map → internal-api-WEOSTMSN.js.map} +0 -0
  178. /package/dist/{load-config-JKJ73TOD.js.map → load-config-2LP2OEKD.js.map} +0 -0
  179. /package/dist/{mcp-CO4AGAXV.js.map → mcp-4FNNCFPM.js.map} +0 -0
  180. /package/dist/{netlify-OFJUYXTZ.js.map → netlify-AFMDNKT4.js.map} +0 -0
  181. /package/dist/{node-ND4MJU3Z.js.map → node-ZJQEJSP3.js.map} +0 -0
  182. /package/dist/{registry-QTSMLOVG.js.map → registry-UJ6KNQPJ.js.map} +0 -0
  183. /package/dist/{routes-GWAWUVVQ.js.map → routes-6AMNVFMI.js.map} +0 -0
  184. /package/dist/{schema-2JEG6TTU.js.map → schema-Z3Y7SFLE.js.map} +0 -0
  185. /package/dist/{services-typed-client-II7LKXKO.js.map → services-typed-client-PSAGRPFF.js.map} +0 -0
  186. /package/dist/{static-HTT2WNIT.js.map → static-R25HSXEF.js.map} +0 -0
  187. /package/dist/{theo-cloud-ZTQLXGPS.js.map → theo-cloud-XAHWOUFK.js.map} +0 -0
  188. /package/dist/{vercel-72HFEMJ3.js.map → vercel-SRS2DH6O.js.map} +0 -0
  189. /package/dist/{vite-plugin-NQ6F7FGV.js.map → vite-plugin-YOCPU4C6.js.map} +0 -0
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env node
2
- import "tsx/esm";
3
-
4
- // src/adapters/registry.ts
5
- var adapterRegistry = {
6
- node: async () => (await import("./node-ND4MJU3Z.js")).nodeAdapter,
7
- vercel: async () => (await import("./vercel-72HFEMJ3.js")).vercelAdapter,
8
- cloudflare: async () => (await import("./cloudflare-JTBKOX3F.js")).cloudflareAdapter,
9
- static: async () => (await import("./static-HTT2WNIT.js")).staticAdapter,
10
- bun: async () => (await import("./bun-TLYZCEGE.js")).bunAdapter,
11
- "deno-deploy": async () => (await import("./deno-deploy-3ESNGYZU.js")).denoDeployAdapter,
12
- netlify: async () => (await import("./netlify-OFJUYXTZ.js")).netlifyAdapter,
13
- "aws-lambda": async () => (await import("./aws-lambda-7SUTORXM.js")).awsLambdaAdapter,
14
- "theo-cloud": async () => (await import("./theo-cloud-ZTQLXGPS.js")).theoCloudAdapter
15
- };
16
- async function resolveAdapter(target) {
17
- const factory = adapterRegistry[target];
18
- return factory();
19
- }
20
- export {
21
- resolveAdapter
22
- };
23
- //# sourceMappingURL=registry-QTSMLOVG.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/migrate/router.ts","../src/cli/commands/migrate/router-codemod.ts"],"sourcesContent":["/**\n * G6 T2.1 — `theokit migrate router` CLI subcommand.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * Wraps the pure `planRouterMigration` with side effects:\n * - EC-2: pre-flight `isPortInUse(3000|3100)` warning to prevent the\n * dev-server HMR cascade described in the edge-case review.\n * - EC-7: partial failure produces a typed `RouterMigrationPartialFailure`\n * with `filesAlreadyMigrated` so a re-run can continue from where it\n * stopped (idempotent by virtue of `planRouterMigration`).\n * - Prefers `git mv $from $to` so the rename appears as a single\n * history entry; falls back to `mkdir -p $(dirname $to) && fs.rename`\n * when not in a git repo or git mv fails.\n */\nimport { execFileSync } from 'node:child_process'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { dirname, resolve } from 'node:path'\n\nimport {\n computeDepthDelta,\n planRouterMigration,\n rewriteRelativeImports,\n type RouterMigrationPlanItem,\n} from './router-codemod.js'\n\ninterface RouterMigrateOptions {\n /** Absolute path to `<project>/server/routes`. Defaults to `<cwd>/server/routes`. */\n routesDir?: string\n /**\n * Skip the EC-2 dev-server port pre-flight check (CI / non-TTY).\n * Default: false.\n */\n force?: boolean\n /** When true, prints the plan but performs no renames (dry-run). */\n dryRun?: boolean\n /** When true, suppresses stdout (used in tests). */\n silent?: boolean\n}\n\n/**\n * Thrown when the codemod completes with at least one successful rename\n * AND at least one failure — caller can re-run safely (idempotent) and\n * the second pass will skip already-migrated files.\n */\nclass RouterMigrationPartialFailure extends Error {\n override readonly name = 'RouterMigrationPartialFailure'\n readonly filesAlreadyMigrated: string[]\n readonly failedFile: string\n readonly causeMessage: string\n constructor(filesAlreadyMigrated: string[], failedFile: string, causeMessage: string) {\n super(\n `Router migration partial failure: ${filesAlreadyMigrated.length} files migrated successfully, then failed on ${failedFile}: ${causeMessage}. Re-run \\`theokit migrate router\\` to retry — already-migrated files will be skipped.`,\n )\n this.filesAlreadyMigrated = filesAlreadyMigrated\n this.failedFile = failedFile\n this.causeMessage = causeMessage\n }\n}\n\n/**\n * EC-2: dev-server detection. Returns true if the port is in use (someone\n * is already listening on localhost:<port>). Uses Node's `node:net` —\n * zero new deps.\n */\nexport async function isPortInUse(port: number): Promise<boolean> {\n return await new Promise<boolean>((resolve) => {\n const probe = createServer()\n probe.once('error', (err: NodeJS.ErrnoException) => {\n probe.close(() => {\n resolve(err.code === 'EADDRINUSE')\n })\n })\n probe.once('listening', () => {\n probe.close(() => {\n resolve(false)\n })\n })\n probe.listen(port, '127.0.0.1')\n })\n}\n\n/**\n * EC-2 pre-flight: returns the first port in use among the typical\n * theokit dev ports (3000 + 3100) so the caller can warn the user.\n */\nexport async function findRunningDevServerPort(): Promise<number | null> {\n for (const port of [3000, 3100]) {\n if (await isPortInUse(port)) return port\n }\n return null\n}\n\nfunction tryGitMv(from: string, to: string): boolean {\n try {\n mkdirSync(dirname(to), { recursive: true })\n // Arguments are absolute paths from a recursive walk of <routesDir>.\n // Pass as argv to avoid shell parsing entirely (no `shell: true`).\n // `git` is resolved via the operator's PATH (same security model as\n // every other CLI tool — `theokit dev`, `pnpm install`, etc.).\n\n execFileSync('git', ['mv', from, to], { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n}\n\nfunction fallbackRename(from: string, to: string): void {\n mkdirSync(dirname(to), { recursive: true })\n renameSync(from, to)\n}\n\nfunction applyRename(item: RouterMigrationPlanItem): void {\n if (!existsSync(item.from)) {\n // Idempotency: already migrated — skip silently\n return\n }\n if (existsSync(item.to)) {\n // The plan() phase would have thrown CollisionError if we knew about\n // it at plan time. This branch covers a race condition where the\n // target was created between plan and apply.\n throw new Error(\n `Refusing to overwrite existing file at ${item.to} during migration of ${item.from}`,\n )\n }\n if (!tryGitMv(item.from, item.to)) {\n fallbackRename(item.from, item.to)\n }\n}\n\n/**\n * Adjust relative imports inside the renamed file to compensate for the\n * extra nesting depth. Without this, `import { foo } from './chat'` inside\n * a file moved from `routes/admin.sdk-config.ts` → `routes/admin/sdk-config.ts`\n * would fail to resolve at typecheck/runtime — the import needs `../chat`\n * now that the file lives one level deeper.\n */\nfunction applyImportRewrite(item: RouterMigrationPlanItem, routesDir: string): void {\n const delta = computeDepthDelta(item.from, item.to, routesDir)\n if (delta <= 0) return\n const source = readFileSync(item.to, 'utf8')\n const rewritten = rewriteRelativeImports(source, delta)\n if (rewritten !== source) {\n writeFileSync(item.to, rewritten, 'utf8')\n }\n}\n\ninterface RouterMigrateResult {\n /** Successfully renamed (from, to) pairs. */\n migrated: RouterMigrationPlanItem[]\n /** Plan was empty — nothing to do (already-nested). */\n alreadyClean: boolean\n}\n\ntype LogFn = (msg: string) => void\n\nfunction makeLog(silent: boolean | undefined): LogFn {\n if (silent) {\n return (_msg: string) => {\n // intentionally silent\n }\n }\n return (msg: string) => {\n console.log(msg)\n }\n}\n\nasync function assertNoRunningDevServer(opts: RouterMigrateOptions): Promise<void> {\n if (opts.force) return\n const runningPort = await findRunningDevServerPort()\n if (runningPort !== null) {\n throw new Error(\n `Detected theokit dev server running on port ${runningPort}. STOP it before running migration to avoid HMR cascade (see EC-2). Re-run with --force to override.`,\n )\n }\n}\n\nfunction executeRenames(\n plan: readonly RouterMigrationPlanItem[],\n routesDir: string,\n log: LogFn,\n): RouterMigrationPlanItem[] {\n const migrated: RouterMigrationPlanItem[] = []\n for (const item of plan) {\n try {\n applyRename(item)\n applyImportRewrite(item, routesDir)\n migrated.push(item)\n log(` ✓ ${item.from} → ${item.to}`)\n } catch (err) {\n // EC-7: partial failure observability — emit structured error with\n // the list of already-migrated files so a re-run can recover.\n const causeMessage = err instanceof Error ? err.message : String(err)\n throw new RouterMigrationPartialFailure(\n migrated.map((m) => m.from),\n item.from,\n causeMessage,\n )\n }\n }\n return migrated\n}\n\nexport async function routerMigrateCommand(\n opts: RouterMigrateOptions = {},\n): Promise<RouterMigrateResult> {\n const routesDir = opts.routesDir ?? resolve(process.cwd(), 'server', 'routes')\n const log = makeLog(opts.silent)\n\n await assertNoRunningDevServer(opts)\n\n const plan = planRouterMigration(routesDir)\n if (plan.length === 0) {\n log(' ✓ Router already uses directory-nested convention. Nothing to do.')\n return { migrated: [], alreadyClean: true }\n }\n\n log(` → Migrating ${plan.length} dotted route(s) to directory-nested form...`)\n\n if (opts.dryRun) {\n for (const item of plan) {\n log(` [dry-run] ${item.from} → ${item.to}`)\n }\n return { migrated: [], alreadyClean: false }\n }\n\n const migrated = executeRenames(plan, routesDir, log)\n log(` ✓ Migrated ${migrated.length} route(s).`)\n return { migrated, alreadyClean: false }\n}\n","/**\n * G6 T2.1 — Pure codemod core for `theokit migrate router`.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * `planRouterMigration` walks `<routesDir>` recursively and returns the\n * set of (from, to) renames required to convert legacy dotted-basename\n * routes (`auth.[provider].login.ts`) into the directory-nested form\n * (`auth/[provider]/login.ts`). The function is PURE — it does NOT\n * touch the filesystem beyond `readdirSync`/`statSync`. The CLI subcommand\n * (`router.ts`) is responsible for executing the renames via `git mv`\n * or `fs.rename` with the appropriate error handling.\n *\n * Edge cases covered:\n * - EC-4: co-located `*.test.[jt]sx?` / `*.spec.[jt]sx?` files are\n * silently skipped (same filter as the scanner).\n * - EC-5: target collision detection is CASE-INSENSITIVE so a\n * macOS/Windows dev doesn't silently overwrite a sibling file that\n * differs only in case.\n * - Idempotent: invoked twice on the same tree, the second pass is empty.\n */\nimport { readdirSync, statSync } from 'node:fs'\nimport { extname, join, relative, sep } from 'node:path'\n\nconst ROUTE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst TEST_OR_SPEC_RE = /\\.(test|spec)\\.[jt]sx?$/\n\n/**\n * One pending rename emitted by `planRouterMigration`.\n */\nexport interface RouterMigrationPlanItem {\n /** Absolute path of the offending dotted-basename file. */\n from: string\n /** Absolute path of the proposed directory-nested replacement. */\n to: string\n}\n\n/**\n * `RouterMigrationCollisionError` is thrown when migrating a dotted file\n * would overwrite an existing file (case-insensitive). The caller MUST\n * resolve the conflict manually before re-running the codemod.\n */\nexport class RouterMigrationCollisionError extends Error {\n override readonly name = 'RouterMigrationCollisionError'\n readonly from: string\n readonly to: string\n constructor(from: string, to: string) {\n super(\n `Router migration collision: ${from} would rename to ${to}, but that file already exists (case-insensitive match). Resolve manually.`,\n )\n this.from = from\n this.to = to\n }\n}\n\n/**\n * Compute the depth delta (number of extra `..` levels needed) between\n * the original (dotted) path and the migrated (nested) path, relative\n * to a common `routesDir` ancestor.\n *\n * - `admin.sdk-config.ts` (depth 0) → `admin/sdk-config.ts` (depth 1): delta = 1\n * - `debug.stability.last.ts` (depth 0) → `debug/stability/last.ts` (depth 2): delta = 2\n * - `canvas/artifacts.[id].ts` (depth 1) → `canvas/artifacts/[id].ts` (depth 2): delta = 1\n */\nexport function computeDepthDelta(from: string, to: string, routesDir: string): number {\n const depthOf = (p: string): number => {\n const rel = relative(routesDir, p).replace(/\\\\/g, '/')\n // depth = number of `/` separators in the relative path\n return rel.split('/').length - 1\n }\n return depthOf(to) - depthOf(from)\n}\n\n/**\n * Rewrite all relative imports in `source` by prepending `../` × `delta`\n * to every `./X` or `../X` specifier. Absolute / package specifiers\n * (`theokit/server`, `zod`, `node:fs`) are untouched.\n *\n * Handles three import shapes:\n * - `import ... from './foo'`\n * - `import('./foo')` (dynamic)\n * - `import './foo'` (side-effect only)\n * - `export ... from './foo'` (re-exports)\n *\n * Pure: returns the new source; does NOT touch disk.\n */\nexport function rewriteRelativeImports(source: string, delta: number): string {\n if (delta <= 0) return source\n\n const prefix = '../'.repeat(delta)\n\n // Rewrites a captured relative specifier: `./foo` → `<prefix>foo`,\n // `../foo` → `<prefix>../foo`. Single source of truth for the algorithm\n // shared by all three import-shape regexes below.\n const transformSpecifier = (specifier: string): string => {\n if (specifier.startsWith('./')) return `${prefix}${specifier.slice(2)}`\n return `${prefix}${specifier}`\n }\n\n // Three narrow regexes keep us out of catastrophic-backtracking territory.\n // Each is anchored on a keyword (`from`, `import`) and uses a possessive\n // character class (`[^'\"]+`) for the specifier, so backtracking is bounded.\n const fromRe = /\\bfrom\\s+(['\"])(\\.{1,2}\\/[^'\"]+)\\1/g\n const dynRe = /\\bimport\\s*\\(\\s*(['\"])(\\.{1,2}\\/[^'\"]+)\\1\\s*\\)/g\n const sideRe = /\\bimport\\s+(['\"])(\\.{1,2}\\/[^'\"]+)\\1/g\n\n const fromSub = (_m: string, q: string, spec: string): string =>\n `from ${q}${transformSpecifier(spec)}${q}`\n const dynSub = (_m: string, q: string, spec: string): string =>\n `import(${q}${transformSpecifier(spec)}${q})`\n const sideSub = (_m: string, q: string, spec: string): string =>\n `import ${q}${transformSpecifier(spec)}${q}`\n\n // `from` covers both `import ... from '...'` and `export ... from '...'`\n // (the `\\bfrom\\s+` anchor matches the keyword position in both shapes).\n // `dynRe` handles `import('...')`. `sideRe` handles bare `import '...'`.\n // No overlap — `sideRe` requires `import` followed by whitespace then\n // a quote (vs. `import(` for dynRe and `import ... from` for fromRe).\n return source.replace(fromRe, fromSub).replace(dynRe, dynSub).replace(sideRe, sideSub)\n}\n\nfunction isTestOrSpecFile(filePath: string): boolean {\n return TEST_OR_SPEC_RE.test(filePath)\n}\n\nfunction hasDotOutsideBrackets(segment: string): boolean {\n let depth = 0\n for (const ch of segment) {\n if (ch === '[') depth++\n else if (ch === ']') depth--\n else if (ch === '.' && depth === 0) return true\n }\n return false\n}\n\nfunction splitDottedSegmentOutsideBrackets(segment: string): string[] {\n const parts: string[] = []\n let current = ''\n let depth = 0\n for (const ch of segment) {\n if (ch === '[') {\n depth++\n current += ch\n } else if (ch === ']') {\n depth--\n current += ch\n } else if (ch === '.' && depth === 0) {\n if (current) parts.push(current)\n current = ''\n } else {\n current += ch\n }\n }\n if (current) parts.push(current)\n return parts\n}\n\nfunction toDirectoryNestedPath(filePath: string, routesDir: string): string {\n const rel = relative(routesDir, filePath).replace(/\\\\/g, '/')\n const ext = extname(rel)\n const withoutExt = rel.slice(0, -ext.length)\n const flattened = withoutExt.split('/').flatMap(splitDottedSegmentOutsideBrackets)\n return join(routesDir, `${flattened.join(sep)}${ext}`)\n}\n\nfunction walkRoutes(root: string, onFile: (absPath: string) => void): void {\n let entries\n try {\n entries = readdirSync(root, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) continue\n const full = join(root, entry.name)\n if (entry.isDirectory()) {\n walkRoutes(full, onFile)\n } else if (entry.isFile() && ROUTE_EXTENSIONS.has(extname(entry.name))) {\n onFile(full)\n }\n }\n}\n\nfunction isDottedRouteFile(filePath: string, routesDir: string): boolean {\n const rel = relative(routesDir, filePath).replace(/\\\\/g, '/')\n const ext = extname(rel)\n const withoutExt = rel.slice(0, -ext.length)\n return withoutExt.split('/').some(hasDotOutsideBrackets)\n}\n\n/**\n * Compute the migration plan for a `<server>/routes` tree.\n *\n * Pure: does NOT mutate the filesystem.\n *\n * @throws RouterMigrationCollisionError when a target collides with an\n * existing file (case-insensitive).\n */\nexport function planRouterMigration(routesDir: string): RouterMigrationPlanItem[] {\n const plan: RouterMigrationPlanItem[] = []\n const existingPathsLowercase = new Set<string>()\n\n walkRoutes(routesDir, (absPath) => {\n existingPathsLowercase.add(absPath.toLowerCase())\n })\n\n walkRoutes(routesDir, (absPath) => {\n if (isTestOrSpecFile(absPath)) return\n if (!isDottedRouteFile(absPath, routesDir)) return\n\n const to = toDirectoryNestedPath(absPath, routesDir)\n\n // EC-5: case-insensitive collision check — macOS HFS+/APFS default\n // and Windows NTFS treat case-only differences as the same path. If\n // any pre-existing file at a case-insensitive match exists, the codemod\n // would silently overwrite on those platforms; we bail explicitly.\n const targetLower = to.toLowerCase()\n if (existingPathsLowercase.has(targetLower) && targetLower !== absPath.toLowerCase()) {\n throw new RouterMigrationCollisionError(absPath, to)\n }\n // Also guard against statSync race using an explicit existence check.\n try {\n if (statSync(to).isFile()) {\n throw new RouterMigrationCollisionError(absPath, to)\n }\n } catch (err) {\n if (err instanceof RouterMigrationCollisionError) throw err\n // ENOENT — fine, target does not exist\n }\n\n plan.push({ from: absPath, to })\n })\n\n return plan\n}\n"],"mappings":"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","names":["resolve"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/vite-plugin/server-routes-hmr.ts"],"sourcesContent":["/**\n * G6 T1.2 — Vite plugin: watch `server/routes/**` and invalidate SSR module\n * cache on add/change/unlink with a 50 ms debounce window.\n *\n * Plan: .claude/knowledge-base/plans/g6-router-convention-plan.md v1.1\n *\n * Pattern reference: SvelteKit `exports/vite/dev/index.js:335-398`.\n *\n * Why this exists: in dev, `scanServerRoutes` runs per-request (fresh disk\n * read), so adding/removing routes already takes effect on next request.\n * But the SSR dynamic-import cache holds stale code for EDITED routes — Vite\n * needs an explicit `invalidateModule` call to bust it. We also send a\n * `full-reload` so any browser code that imported a route module\n * (rare, but the typed client G1 does this for ts-only type resolution)\n * picks up the change.\n *\n * EC-6: 50 ms debounce collapses bursty file events (e.g., codemod-driven\n * 21-rename storm in T2.1) into a single invalidation cycle — without it,\n * 21 invalidations + 21 full-reloads in 5 s would hang the dev server.\n */\nimport { sep } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\ninterface ServerRoutesHmrPluginOptions {\n /** Absolute path of the consumer's `server/` directory. */\n serverDir: string\n /** Debounce window in milliseconds (default 50 ms per EC-6). */\n debounceMs?: number\n}\n\ninterface ModuleGraphLike {\n getModuleById: (id: string) => unknown\n invalidateModule: (mod: unknown) => void\n idToModuleMap: Map<string, { id: string }>\n}\n\ninterface ViteDevServerLike {\n watcher: { on: (event: string, listener: (path: string) => void) => void }\n moduleGraph: ModuleGraphLike\n ws: { send: (payload: { type: string }) => void }\n}\n\nexport function serverRoutesHmrPlugin(opts: ServerRoutesHmrPluginOptions): Plugin {\n const routesDir = `${opts.serverDir}${sep}routes${sep}`\n // Cross-platform: on Windows the watcher MAY emit forward slashes even on NTFS.\n const routesDirPosix = routesDir.replace(/\\\\/g, '/')\n const debounceMs = opts.debounceMs ?? 50\n\n const isUnderRoutes = (filePath: string): boolean => {\n const normalized = filePath.replace(/\\\\/g, '/')\n return normalized.startsWith(routesDirPosix)\n }\n\n return {\n name: 'theokit:server-routes-hmr',\n\n configureServer(server: ViteDevServer) {\n const srv = server as unknown as ViteDevServerLike\n let timer: ReturnType<typeof setTimeout> | null = null\n\n const fireInvalidation = (): void => {\n timer = null\n for (const mod of srv.moduleGraph.idToModuleMap.values()) {\n const normalizedId = mod.id.replace(/\\\\/g, '/')\n if (normalizedId.startsWith(routesDirPosix)) {\n srv.moduleGraph.invalidateModule(mod)\n }\n }\n srv.ws.send({ type: 'full-reload' })\n }\n\n const scheduleInvalidation = (filePath: string): void => {\n if (!isUnderRoutes(filePath)) return\n if (timer !== null) clearTimeout(timer)\n timer = setTimeout(fireInvalidation, debounceMs)\n }\n\n srv.watcher.on('add', scheduleInvalidation)\n srv.watcher.on('change', scheduleInvalidation)\n srv.watcher.on('unlink', scheduleInvalidation)\n },\n }\n}\n"],"mappings":";;;;AAoBA,SAAS,WAAW;AAuBb,SAAS,sBAAsB,MAA4C;AAChF,QAAM,YAAY,GAAG,KAAK,SAAS,GAAG,GAAG,SAAS,GAAG;AAErD,QAAM,iBAAiB,UAAU,QAAQ,OAAO,GAAG;AACnD,QAAM,aAAa,KAAK,cAAc;AAEtC,QAAM,gBAAgB,CAAC,aAA8B;AACnD,UAAM,aAAa,SAAS,QAAQ,OAAO,GAAG;AAC9C,WAAO,WAAW,WAAW,cAAc;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,gBAAgB,QAAuB;AACrC,YAAM,MAAM;AACZ,UAAI,QAA8C;AAElD,YAAM,mBAAmB,MAAY;AACnC,gBAAQ;AACR,mBAAW,OAAO,IAAI,YAAY,cAAc,OAAO,GAAG;AACxD,gBAAM,eAAe,IAAI,GAAG,QAAQ,OAAO,GAAG;AAC9C,cAAI,aAAa,WAAW,cAAc,GAAG;AAC3C,gBAAI,YAAY,iBAAiB,GAAG;AAAA,UACtC;AAAA,QACF;AACA,YAAI,GAAG,KAAK,EAAE,MAAM,cAAc,CAAC;AAAA,MACrC;AAEA,YAAM,uBAAuB,CAAC,aAA2B;AACvD,YAAI,CAAC,cAAc,QAAQ,EAAG;AAC9B,YAAI,UAAU,KAAM,cAAa,KAAK;AACtC,gBAAQ,WAAW,kBAAkB,UAAU;AAAA,MACjD;AAEA,UAAI,QAAQ,GAAG,OAAO,oBAAoB;AAC1C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAC7C,UAAI,QAAQ,GAAG,UAAU,oBAAoB;AAAA,IAC/C;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/sessions-gc.ts"],"sourcesContent":["import { planTranscriptGC, runTranscriptGC } from '@theokit/agents/session'\nimport type { TranscriptGCPlan } from '@theokit/agents/session'\n\n/**\n * M72 — `theokit agent sessions gc`: bound the disk state the framework creates.\n *\n * ## Why the default is a dry run\n *\n * This deletes conversation history. Without `--apply` the command PRINTS the plan and changes\n * nothing, because a destructive retention policy an operator has never seen the output of is a\n * policy nobody reviewed. Making `--apply` the default would save one flag and cost the review.\n *\n * The plan is printed in both modes, not just the dry one: an operator applying a policy still needs\n * to see what it decided, and \"removed 12 sessions\" without which ones is a report nobody can act\n * on.\n */\n\n/**\n * Not exported: its only consumer is the signature below, in this same file.\n *\n * Publishing it would put a name in the package surface that nobody imports — the G7 shape knip\n * caught in M76. When a caller needs to hold these options in a typed variable, exporting it then is\n * one line; exporting it now is a promise to keep a name stable for an audience that does not exist.\n */\ninterface SessionsGcOptions {\n /** Actually delete. Absent ⇒ dry run. */\n readonly apply?: boolean\n /** Newest N sessions always survive (floor 1). */\n readonly keepLast?: number\n /** Only sessions older than this may go (floor 1). */\n readonly maxAgeDays?: number\n /** Where to collect. Defaults to the process cwd — the project the operator is standing in. */\n readonly cwd?: string\n}\n\n/** Defaults chosen to be boring: a month of history, never fewer than ten sessions. */\nconst DEFAULTS = { keepLast: 10, maxAgeDays: 30 } as const\n\n/** Render the plan for a human. Returns lines so the command is testable without capturing stdout. */\nexport function formatGcPlan(\n plan: TranscriptGCPlan,\n result: ReturnType<typeof runTranscriptGC>,\n): string[] {\n const lines: string[] = [result.dryRun ? ' Dry run — nothing was deleted.' : ' Applied.', '']\n\n if (result.removed.length === 0) {\n lines.push(' Nothing to collect.')\n } else {\n lines.push(` ${result.dryRun ? 'Would remove' : 'Removed'} ${String(result.removed.length)}:`)\n for (const id of result.removed) lines.push(` - ${id}`)\n }\n\n // The kept list carries the REASON per session. \"Skipped 4\" tells an operator nothing; \"kept\n // because it holds an active writer lease\" tells them whether to go stop something.\n if (plan.kept.length > 0) {\n lines.push('', ` Kept ${String(plan.kept.length)}:`)\n for (const keep of plan.kept) lines.push(` - ${keep.id} — ${keep.reason}`)\n }\n\n if (result.errors.length > 0) {\n lines.push('', ` ${String(result.errors.length)} failed (the rest still ran):`)\n for (const error of result.errors) lines.push(` ✗ ${error.id} — ${error.message}`)\n }\n\n return lines\n}\n\n/**\n * Plan and (optionally) apply transcript retention for one project.\n *\n * Returns the result so a caller can decide the exit code: a partial failure is reported, never\n * swallowed into a zero exit.\n */\nexport function sessionsGcCommand(options: SessionsGcOptions = {}): {\n readonly lines: readonly string[]\n readonly failed: number\n} {\n const plan = planTranscriptGC({\n cwd: options.cwd ?? process.cwd(),\n keepLast: options.keepLast ?? DEFAULTS.keepLast,\n maxAgeDays: options.maxAgeDays ?? DEFAULTS.maxAgeDays,\n })\n const result = runTranscriptGC(plan, { apply: options.apply === true })\n return { lines: formatGcPlan(plan, result), failed: result.errors.length }\n}\n"],"mappings":";;;;AAAA,SAAS,kBAAkB,uBAAuB;AAoClD,IAAM,WAAW,EAAE,UAAU,IAAI,YAAY,GAAG;AAGzC,SAAS,aACd,MACA,QACU;AACV,QAAM,QAAkB,CAAC,OAAO,SAAS,0CAAqC,cAAc,EAAE;AAE9F,MAAI,OAAO,QAAQ,WAAW,GAAG;AAC/B,UAAM,KAAK,uBAAuB;AAAA,EACpC,OAAO;AACL,UAAM,KAAK,KAAK,OAAO,SAAS,iBAAiB,SAAS,IAAI,OAAO,OAAO,QAAQ,MAAM,CAAC,GAAG;AAC9F,eAAW,MAAM,OAAO,QAAS,OAAM,KAAK,SAAS,EAAE,EAAE;AAAA,EAC3D;AAIA,MAAI,KAAK,KAAK,SAAS,GAAG;AACxB,UAAM,KAAK,IAAI,UAAU,OAAO,KAAK,KAAK,MAAM,CAAC,GAAG;AACpD,eAAW,QAAQ,KAAK,KAAM,OAAM,KAAK,SAAS,KAAK,EAAE,WAAM,KAAK,MAAM,EAAE;AAAA,EAC9E;AAEA,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,UAAM,KAAK,IAAI,KAAK,OAAO,OAAO,OAAO,MAAM,CAAC,+BAA+B;AAC/E,eAAW,SAAS,OAAO,OAAQ,OAAM,KAAK,cAAS,MAAM,EAAE,WAAM,MAAM,OAAO,EAAE;AAAA,EACtF;AAEA,SAAO;AACT;AAQO,SAAS,kBAAkB,UAA6B,CAAC,GAG9D;AACA,QAAM,OAAO,iBAAiB;AAAA,IAC5B,KAAK,QAAQ,OAAO,QAAQ,IAAI;AAAA,IAChC,UAAU,QAAQ,YAAY,SAAS;AAAA,IACvC,YAAY,QAAQ,cAAc,SAAS;AAAA,EAC7C,CAAC;AACD,QAAM,SAAS,gBAAgB,MAAM,EAAE,OAAO,QAAQ,UAAU,KAAK,CAAC;AACtE,SAAO,EAAE,OAAO,aAAa,MAAM,MAAM,GAAG,QAAQ,OAAO,OAAO,OAAO;AAC3E;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/start/index.ts","../src/server/define/health-route.ts","../src/cli/commands/start/assert-sdk-compatible.ts","../src/server/agent/sdk-compat.ts","../src/cli/commands/start/bootstrap-stages.ts","../src/cli/commands/start/graceful-shutdown.ts","../src/cli/commands/start/manifest-loader.ts","../src/cli/commands/start/request-handler.ts","../src/cli/commands/start/handlers.ts","../src/server/http/static.ts","../src/cli/commands/start/ssr-setup.ts","../src/cli/commands/start/websocket-handler.ts"],"sourcesContent":["/**\n * theokit start — production server orchestration spine.\n *\n * T4.2 (architecture-cleanup, ADR-0017): stages extracted to sibling modules.\n * - start-bootstrap-stages.ts — config/registry/storage bootstrap + resolveSsrEntry\n * - start-manifest-loader.ts — manifest.json or scan fallback\n * - start-ssr-setup.ts — SSR entry-server + HTML template split\n * - start-handlers.ts — branch handlers (action/route/static/404)\n * - start-request-handler.ts — request lifecycle wiring\n * - start-websocket-handler.ts — WS upgrade (opt-in)\n * - start-graceful-shutdown.ts — SIGTERM/SIGINT drain\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { createServer } from 'node:http'\nimport { join, resolve } from 'node:path'\n\nimport { loadConfig } from '../../../config/load-config.js'\nimport { loadEnv } from '../../../config/load-env.js'\nimport { defineHealthRoute } from '../../../server/define/health-route.js'\nimport { createPluginRunnerFromConfig } from '../../../server/plugins/load-plugins.js'\nimport { createRateLimiter } from '../../../server/rate-limit/rate-limit.js'\nimport { createProductionLoader } from '../../../server/scan/module-loader.js'\nimport { resolveTransformer } from '../../../server/transformer.js'\nimport { preflightNodeAndBindings } from '../../preflight-node-version.js'\nimport { CONTROLLER_MANIFEST_FILE } from '../build/emit-controllers.js'\n\nimport { assertSdkCompatible } from './assert-sdk-compatible.js'\nimport {\n configureAgentRegistryFromConfig,\n configureStorageManagerFromConfig,\n} from './bootstrap-stages.js'\nimport { installGracefulShutdown } from './graceful-shutdown.js'\nimport type { RequestHandlerCtx } from './handlers.js'\nimport { loadRoutesAndActions } from './manifest-loader.js'\nimport { createRequestHandler } from './request-handler.js'\nimport { setupSsr } from './ssr-setup.js'\nimport { attachWebSocketHandler } from './websocket-handler.js'\n\n// Backwards-compat: external test fixtures may import resolveSsrEntry from here.\nexport { resolveSsrEntry } from './bootstrap-stages.js'\n\ninterface StartOptions {\n port?: number\n}\n\nexport async function startCommand(options: StartOptions): Promise<void> {\n const cwd = process.cwd()\n // Preflight (FIRST — BEFORE anything that touches native bindings).\n preflightNodeAndBindings(cwd)\n loadEnv({ cwd, mode: 'production' })\n const config = await loadConfig(cwd)\n\n // M48 — fail fast if the installed @theokit/sdk is present but incompatible (before serving any\n // request). Absent SDK stays silent here (an api-only app is valid); the request path guards it lazily.\n assertSdkCompatible()\n\n await configureAgentRegistryFromConfig(config.agents?.registry)\n await configureStorageManagerFromConfig(config.storage)\n\n const distDir = resolve(cwd, '.theokit')\n const clientDir = resolve(distDir, 'client')\n // theokit#123 — compiled controllers, when `theokit build` emitted any.\n //\n // Keyed on the MANIFEST rather than on the directory existing: a stale `dist/controllers` left by\n // an earlier build whose sources were since deleted would otherwise keep serving routes the app\n // no longer declares. `theokit build` writes the manifest only when it compiles something, and\n // `cleanOutDir` removes both, so the manifest is the authoritative \"this build has controllers\".\n const controllersDistDir = existsSync(resolve(distDir, CONTROLLER_MANIFEST_FILE))\n ? resolve(distDir, 'controllers')\n : undefined\n // #95 — honor config `serverDir` (default \"server\") in production start, matching dev.\n const serverDir = resolve(cwd, config.serverDir)\n\n if (!existsSync(clientDir)) {\n throw new Error('No build found. Run `theo build` first.')\n }\n\n const indexHtml = readFileSync(join(clientDir, 'index.html'), 'utf-8')\n const loadModule = createProductionLoader()\n const port = options.port ?? config.port\n const pluginRunner = await createPluginRunnerFromConfig(config.plugins)\n const transformer = resolveTransformer(config.serialization)\n\n const custom404Path = join(clientDir, '404.html')\n const custom500Path = join(clientDir, '500.html')\n const custom404Html = existsSync(custom404Path) ? readFileSync(custom404Path, 'utf-8') : null\n const custom500Html = existsSync(custom500Path) ? readFileSync(custom500Path, 'utf-8') : null\n\n const {\n routes: cachedRoutes,\n actions: cachedActions,\n wsRoutes: cachedWsRoutes,\n agents: cachedAgents,\n } = loadRoutesAndActions(distDir, serverDir, config.agentsDir)\n\n // Rate limiter (legacy flat form only — per-route variant is handled in\n // api-middleware integration path, not this fallback).\n const flatRateLimit =\n config.rateLimit && 'windowMs' in config.rateLimit && 'max' in config.rateLimit\n ? config.rateLimit\n : undefined\n const rateLimiter = flatRateLimit ? createRateLimiter(flatRateLimit) : null\n\n const ssr = await setupSsr({\n distDir,\n indexHtml,\n ssrConfigEnabled: config.ssr,\n ssrStreamingConfig: config.ssrStreaming,\n })\n\n const server = createServer(\n createRequestHandler({\n buildCtx: (req, res, requestId, startTime): RequestHandlerCtx => ({\n req,\n res,\n url: req.url ?? '/',\n requestId,\n startTime,\n clientDir,\n custom404Html,\n cachedRoutes,\n cachedActions,\n cachedAgents,\n loadModule,\n serverDir,\n projectRoot: cwd,\n controllersDistDir,\n pluginRunner,\n transformer,\n csrfMode: config.security?.csrf ?? 'strict',\n disallowed: config.security?.disallowed,\n rateLimiter,\n }),\n securityHeadersConfig: config.security?.headers ?? {},\n ssrRender: ssr.render,\n ssrRenderStreaming: ssr.renderStreaming,\n ssrStreamingEnabled: ssr.streamingEnabled,\n htmlHead: ssr.htmlHead,\n htmlTail: ssr.htmlTail,\n indexHtml,\n custom500Html,\n // M7-2: serve a built-in liveness route on the Node listener. Readiness\n // probe wiring from theo.config.ts is a documented follow-up (see the M7\n // implementation summary § Scope note).\n reservedRoutes: { health: defineHealthRoute() },\n }),\n )\n\n await attachWebSocketHandler(server, cachedWsRoutes, loadModule)\n\n server.listen(port, () => {\n console.log(`\\n Theo production server`)\n console.log(` → http://localhost:${String(port)}\\n`)\n })\n\n installGracefulShutdown(server)\n}\n","/**\n * M7-2 — health/ready reserved routes for the convention/filesystem-route\n * server. Liveness (`/__theo/health`, always 200) and readiness\n * (`/__theo/ready`, 200/503 from a probe) are registered on a reserved\n * namespace BEFORE the user-route catch-all + 404 branch — mirroring nitro's\n * `/_nitro/*` reserved-namespace pattern (knowledge-base/references/nitro/src/\n * runtime/internal/routes/dev-tasks.ts). Liveness and readiness are kept\n * separate by design: liveness says \"the process is up\", readiness says\n * \"dependencies are up\".\n *\n * @public\n */\n\n/** Reserved path for the liveness endpoint. */\nexport const HEALTH_PATH = '/__theo/health'\n/** Reserved path for the readiness endpoint. */\nexport const READY_PATH = '/__theo/ready'\n\n/** Config produced by {@link defineHealthRoute}. */\nexport interface HealthRouteConfig {\n readonly kind: 'health'\n /** Returns the liveness body (auto-serialized to JSON). Default: `{ status: 'ok' }`. */\n readonly handler: () => unknown\n}\n\n/** Config produced by {@link defineReadyRoute}. */\nexport interface ReadyRouteConfig {\n readonly kind: 'ready'\n /** Resolves `true` when dependencies are ready. A throw/reject is treated as not-ready (503). */\n readonly probe: () => boolean | Promise<boolean>\n}\n\n/** The reserved-route registry consulted by {@link serveReservedRoute}. */\nexport interface ReservedRoutes {\n readonly health?: HealthRouteConfig\n readonly ready?: ReadyRouteConfig\n}\n\n/** A reserved-route response: an HTTP status + a JSON-serializable body. */\nexport interface ReservedResponse {\n readonly status: number\n readonly body: unknown\n}\n\n/**\n * Define the liveness route. The default handler returns `{ status: 'ok' }`.\n * Liveness is always 200 — it asserts the process is up, not that dependencies are.\n */\nexport function defineHealthRoute(\n handler: () => unknown = () => ({ status: 'ok' }),\n): HealthRouteConfig {\n return { kind: 'health', handler }\n}\n\n/**\n * Define the readiness route. The `probe` decides 200 (ready) vs 503 (not-ready).\n * A probe that throws/rejects is treated as not-ready (503) — never a 500 crash.\n */\nexport function defineReadyRoute(probe: () => boolean | Promise<boolean>): ReadyRouteConfig {\n return { kind: 'ready', probe }\n}\n\n/**\n * Pure dispatcher: map a request pathname to a reserved-route response, or\n * `null` when the path is not reserved (so the user catch-all + 404 take over).\n * Liveness defaults to 200 `{status:'ok'}`; readiness without a probe is\n * trivially ready (200). Registered BEFORE the user catch-all by the caller.\n */\nexport async function serveReservedRoute(\n pathname: string,\n routes: ReservedRoutes = {},\n): Promise<ReservedResponse | null> {\n if (pathname === HEALTH_PATH) {\n const handler = routes.health?.handler ?? (() => ({ status: 'ok' }))\n return { status: 200, body: handler() }\n }\n if (pathname === READY_PATH) {\n const probe = routes.ready?.probe\n if (probe === undefined) {\n return { status: 200, body: { status: 'ready' } }\n }\n try {\n const ready = await probe()\n return ready\n ? { status: 200, body: { status: 'ready' } }\n : { status: 503, body: { status: 'not-ready' } }\n } catch (err) {\n // 503 (the dependency is not ready) but NEVER swallow the cause — a\n // readiness probe failing silently is invisible to ops (project rule:\n // \"NEVER swallow exceptions\"). Log the cause, keep the 503 contract.\n console.error('[theo] readiness probe threw — treating as not-ready', err)\n return { status: 503, body: { status: 'not-ready' } }\n }\n }\n return null\n}\n","/**\n * M48 (ecosystem-integration-guarantee) T3.2 — boot-time SDK compatibility fail-fast.\n *\n * The agent runtime is `@theokit/sdk` (G2). Today a missing / mis-versioned SDK is invisible until\n * the FIRST agent request, where `sdk-adapter.ts` yields a lazy `SDK_NOT_INSTALLED` stream event.\n * This runs at `theokit start` boot instead: if the installed SDK is present but outside the\n * supported range it throws a typed error naming found-vs-required; if it is absent (a legitimately\n * api-only app — the SDK is an OPTIONAL peer) it stays silent unless the caller marks it required.\n *\n * CLI/adapter layer → `node:*` is allowed here (unlike `server/`). The version range check itself is\n * the pure `server/agent/sdk-compat.ts` helper (one source of truth with the contract-test drift guard).\n */\nimport { readFileSync } from 'node:fs'\nimport { createRequire } from 'node:module'\n\nimport { SUPPORTED_SDK_RANGE, satisfiesSdkRange } from '../../../server/agent/sdk-compat.js'\n\n/** Typed error surfaced at boot when the installed `@theokit/sdk` is incompatible or absent-but-required. */\nexport class SdkIncompatibleError extends Error {\n readonly code = 'SDK_INCOMPATIBLE' as const\n readonly found: string | undefined\n readonly required: string\n constructor(found: string | undefined, required: string) {\n super(\n found === undefined\n ? `@theokit/sdk is required but not installed — run: pnpm add @theokit/sdk@${required}`\n : `@theokit/sdk ${found} does not satisfy the required range ${required} — run: pnpm add @theokit/sdk@${required}`,\n )\n this.name = 'SdkIncompatibleError'\n this.found = found\n this.required = required\n }\n}\n\n/** Resolve the version of the ACTUALLY-installed `@theokit/sdk`, or `undefined` when absent. */\nfunction defaultResolveSdkVersion(): string | undefined {\n try {\n const require = createRequire(import.meta.url)\n const pkgPath = require.resolve('@theokit/sdk/package.json')\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { version?: string }\n return typeof pkg.version === 'string' ? pkg.version : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Fail fast at boot when the installed `@theokit/sdk` is incompatible.\n *\n * - present + in range → returns (silent)\n * - present + out of range → throws {@link SdkIncompatibleError} (found + required)\n * - absent + `required !== true` → returns (api-only app; the request path still guards lazily)\n * - absent + `required === true` → throws {@link SdkIncompatibleError}\n *\n * `resolveVersion` is injectable for tests (DIP); production uses {@link defaultResolveSdkVersion}.\n */\nexport function assertSdkCompatible(opts?: {\n required?: boolean\n resolveVersion?: () => string | undefined\n}): void {\n const version = (opts?.resolveVersion ?? defaultResolveSdkVersion)()\n if (version === undefined) {\n if (opts?.required === true) throw new SdkIncompatibleError(undefined, SUPPORTED_SDK_RANGE)\n return\n }\n if (!satisfiesSdkRange(version, SUPPORTED_SDK_RANGE)) {\n throw new SdkIncompatibleError(version, SUPPORTED_SDK_RANGE)\n }\n}\n","/**\n * M48 (ecosystem-integration-guarantee) — the supported `@theokit/sdk` version range + a pure,\n * dependency-free `||`-aware caret semver check. Shared by the contract test's version-drift guard\n * (`tests/integration/contract-sdk-seam.test.ts`) and the boot-time fail-fast\n * (`cli/commands/start/assert-sdk-compatible.ts`) — one source of truth for \"which SDK theokit runs on\".\n *\n * Web-Standards discipline (G8/R3a): `server/` code uses no `node:*`. This is pure string logic.\n * Rule 9 (Don't Reinvent) trade-off (ADR D1): a small inline caret checker instead of a `semver`\n * dependency, matching the theo-ui seam's existing precedent (`contract-usetheo-ui-vite-plugin.test.ts`).\n */\n\n/** The single source of truth for the supported SDK range. Mirrors the `package.json` peer floor. */\nexport const SUPPORTED_SDK_RANGE = '^4.0.1'\n\n// Bounded semver: three `\\d+` tuples + an optional `-tag.N` prerelease. No nested quantifiers →\n// no catastrophic backtracking; the security/detect-unsafe-regex heuristic false-positives here.\n// eslint-disable-next-line security/detect-unsafe-regex -- bounded \\d+ groups anchored by `.`/`$`, no backtracking\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-z]+)\\.(\\d+))?$/\n\ninterface Semver {\n major: string\n minor: string\n patch: string\n tag: string | undefined\n pre: string | undefined\n}\n\nfunction parseSemver(value: string): Semver | null {\n const m = SEMVER_RE.exec(value)\n if (!m) return null\n return { major: m[1], minor: m[2], patch: m[3], tag: m[4], pre: m[5] }\n}\n\n/**\n * Return `true` when `version` satisfies `range`, where `range` is a `||`-joined series of caret\n * pins (e.g. `^4.0.1` or `^0.14.0 || ^1.0.0`). A version satisfies the range when it satisfies ANY\n * clause. Covers the semver subset the monorepo uses (caret pins, optional `-tag.N` prerelease);\n * no range-sets or build metadata.\n */\nexport function satisfiesSdkRange(version: string, range: string): boolean {\n return range\n .split('||')\n .map((clause) => clause.trim())\n .some((clause) => satisfiesSingleCaret(version, clause))\n}\n\nfunction satisfiesSingleCaret(version: string, range: string): boolean {\n if (!range.startsWith('^')) return false\n const pin = parseSemver(range.slice(1))\n const ver = parseSemver(version)\n if (!pin || !ver) return false\n if (pin.tag !== undefined) return satisfiesPrereleaseCaret(ver, pin)\n if (ver.tag !== undefined) return false // a prerelease never satisfies a stable caret pin\n return satisfiesStableCaret(ver, pin)\n}\n\nfunction satisfiesPrereleaseCaret(ver: Semver, pin: Semver): boolean {\n // Prerelease pin: same X.Y.Z + same tag + prerelease number >= pin's.\n if (pin.major !== ver.major || pin.minor !== ver.minor || pin.patch !== ver.patch) return false\n if (ver.tag !== pin.tag) return false\n return Number(ver.pre ?? '0') >= Number(pin.pre ?? '0')\n}\n\nfunction satisfiesStableCaret(ver: Semver, pin: Semver): boolean {\n if (pin.major !== ver.major) return false\n if (pin.major === '0') {\n // 0.X.Y caret: minor must match exactly; patch can be >=.\n if (pin.minor !== ver.minor) return false\n return Number(ver.patch) >= Number(pin.patch)\n }\n // >= 1.0.0 caret: minor can be >=, patch anything within the same/greater minor.\n if (Number(ver.minor) > Number(pin.minor)) return true\n if (Number(ver.minor) === Number(pin.minor)) return Number(ver.patch) >= Number(pin.patch)\n return false\n}\n","/**\n * Bootstrap stages extracted from `start.ts` per T4.2 (architecture-cleanup, ADR-0017).\n *\n * The full goal of T4.2 is a ≤30-LOC `startCommand` spine + 6-8 stage files. This\n * file ships the first batch: the configure-from-config bootstrap helpers + the\n * SSR entry resolver. They are stand-alone, side-effect-free at module load, and\n * already individually testable.\n *\n * Remaining stages (request-handler extraction, graceful-shutdown extraction,\n * signal-handlers extraction) are deferred to a follow-up sprint — see plan\n * `docs/plans/architecture-cleanup-plan.md` T4.2 Deferred sub-tasks.\n */\n\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport { warnOnce } from '../../../server/observability/logger.js'\n\ninterface SdkAgentRegistry {\n configure?: (opts: { maxAgents?: number; idleTimeoutMs?: number }) => void\n}\ninterface SdkModule {\n Agent?: { registry?: SdkAgentRegistry }\n}\n\n/**\n * Configure SDK's Agent.registry from `theo.config.ts > agents.registry`.\n * Lazy at boot; EC-3 sync flag flip prevents race under concurrent boot.\n * Silent no-op when registry config is absent or SDK is uninstalled.\n */\nexport async function configureAgentRegistryFromConfig(\n registryConfig: { maxAgents: number; idleTimeoutMs: number } | undefined,\n): Promise<void> {\n if (registryConfig === undefined) return\n try {\n const sdk = (await import('@theokit/sdk').catch(() => null)) as SdkModule | null\n const sdkConfigure = sdk?.Agent?.registry?.configure\n if (sdkConfigure === undefined) return\n const { configureAgentRegistryOnce } =\n await import('../../../server/agent/configure-agent-registry.js')\n configureAgentRegistryOnce(\n {\n configure: (opts) => {\n sdkConfigure(opts)\n },\n },\n registryConfig,\n )\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n warnOnce('bootstrap.agent_registry_skip', {\n event: 'bootstrap.agent_registry_skip',\n message: msg,\n })\n }\n}\n\n/**\n * Configure the StorageManager from `theo.config.ts > storage` (ADR-0007).\n * Manager enforces configure-once internally (D3); this helper bridges the\n * config to the singleton with actionable error handling.\n */\nexport async function configureStorageManagerFromConfig(storageConfig: unknown): Promise<void> {\n if (storageConfig === undefined || storageConfig === null) return\n try {\n const { getStorageManager } = await import('../../../server/storage/storage-manager.js')\n const { storageSchema } = await import('../../../config/schema.js')\n // Re-validate at boot so a malformed config from a non-Zod source\n // (test fixtures, dynamic configs) surfaces a clear error early.\n const parsed = storageSchema.parse(storageConfig)\n getStorageManager().configure(parsed)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n warnOnce('bootstrap.storage_skip', {\n event: 'bootstrap.storage_skip',\n message: msg,\n })\n }\n}\n\nconst SSR_EXTENSIONS = ['.mjs', '.js'] as const\n\n/**\n * Resolve the SSR entry-server module path. tsup may emit `.mjs` or `.js`\n * depending on output format. Try `.mjs` first (modern default) then fall\n * back to `.js`. Returns null when neither exists — SSR stays disabled.\n *\n * Exported so unit tests can pin the resolution order without booting the\n * full CLI.\n */\nexport function resolveSsrEntry(distDir: string): string | null {\n for (const ext of SSR_EXTENSIONS) {\n const path = resolve(distDir, `server/entry-server${ext}`)\n\n if (existsSync(path)) return path\n }\n return null\n}\n","/**\n * Graceful shutdown stage for `theokit start` (T4.2 architecture-cleanup,\n * ADR-0007 D6 — SIGTERM evicts agents + drains StorageManager).\n *\n * EC-13: SIGTERM evicts agents IMMEDIATELY (no per-request drain). In-flight\n * requests get aborted mid-stream — acceptable because the platform LB\n * removed this pod from rotation BEFORE sending SIGTERM (K8s preStop hook +\n * terminationGracePeriodSeconds; same on Vercel/CF/Render).\n *\n * Re-entry guard: multiple SIGTERMs in quick succession run shutdown ONCE.\n */\n\nimport type { Server as HttpServer } from 'node:http'\n\nimport { warnOnce } from '../../../server/observability/logger.js'\n\nexport function installGracefulShutdown(server: HttpServer): void {\n let shuttingDown = false\n const shutdown = (signal: NodeJS.Signals): void => {\n if (shuttingDown) return\n shuttingDown = true\n console.log(`\\n [theokit] ${signal} received — evicting agents`)\n void (async () => {\n // Lazy-import SDK only at shutdown time to avoid forcing the dep on\n // apps that don't use agents at all.\n try {\n const sdk = (await import('@theokit/sdk').catch(() => null)) as {\n Agent?: { registry?: { evictAll?: () => Promise<void> } }\n } | null\n if (sdk?.Agent?.registry?.evictAll !== undefined) {\n await sdk.Agent.registry.evictAll()\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n warnOnce('shutdown.evict_error', {\n event: 'shutdown.evict_error',\n message: msg,\n })\n }\n // T3.1 — drain the StorageManager AFTER agent eviction. Order matters:\n // agents may still hold open pool refs while evicting; closing pools\n // first would break in-flight queries.\n try {\n const { getStorageManager } = await import('../../../server/storage/storage-manager.js')\n const manager = getStorageManager()\n await manager.dispose()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n warnOnce('shutdown.dispose_error', {\n event: 'shutdown.dispose_error',\n message: msg,\n })\n }\n console.log(` [theokit] shutdown complete`)\n server.close(() => {\n process.exit(0)\n })\n setTimeout(() => {\n warnOnce('shutdown.forced_exit', {\n event: 'shutdown.forced_exit',\n message: 'forced exit after 25s timeout',\n })\n process.exit(0)\n }, 25_000).unref()\n })()\n }\n process.on('SIGTERM', () => {\n shutdown('SIGTERM')\n })\n process.on('SIGINT', () => {\n shutdown('SIGINT')\n })\n}\n","/**\n * Manifest loading stage for `theokit start` (T4.2 architecture-cleanup).\n *\n * Loads pre-built manifest from `.theokit/manifest.json` if present; otherwise\n * scans server/ for routes/actions/ws at startup with a structured warn.\n */\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { dirname } from 'node:path'\n\nimport { warnOnce } from '../../../server/observability/logger.js'\nimport type { ActionNode } from '../../../server/scan/action-scan.js'\nimport { scanServerActions } from '../../../server/scan/action-scan.js'\nimport type { AgentNode } from '../../../server/scan/agent-scan.js'\nimport { scanAgents } from '../../../server/scan/agent-scan.js'\nimport { loadManifest } from '../../../server/scan/manifest.js'\nimport type { ServerRouteNode } from '../../../server/scan/match.js'\nimport { scanServerRoutes } from '../../../server/scan/scan.js'\nimport type { WebSocketRouteNode } from '../../../server/scan/ws-scan.js'\nimport { scanWebSocketRoutes } from '../../../server/scan/ws-scan.js'\n\ninterface LoadedRoutes {\n routes: ServerRouteNode[]\n actions: ActionNode[]\n wsRoutes: WebSocketRouteNode[]\n agents: AgentNode[]\n}\n\nexport function loadRoutesAndActions(\n distDir: string,\n serverDir: string,\n // #95 follow-up — agents dir name (config `agentsDir`, default \"agents\") for the live-scan fallback.\n agentsDir = 'agents',\n): LoadedRoutes {\n const manifestPath = join(distDir, 'manifest.json')\n\n if (existsSync(manifestPath)) {\n const manifest = loadManifest(distDir, serverDir)\n return {\n routes: manifest.routes,\n actions: manifest.actions,\n wsRoutes: manifest.websockets,\n agents: manifest.agents,\n }\n }\n warnOnce('bootstrap.manifest_not_found', {\n event: 'bootstrap.manifest_not_found',\n message:\n 'No manifest found, scanning routes at startup. Run \"theo build\" to generate manifest.',\n serverDir,\n })\n return {\n routes: scanServerRoutes(serverDir),\n actions: scanServerActions(serverDir),\n wsRoutes: scanWebSocketRoutes(serverDir),\n // Agents live at <projectRoot>/<agentsDir>; projectRoot = serverDir's parent for the canonical layout.\n agents: scanAgents(dirname(serverDir), agentsDir),\n }\n}\n","/**\n * Inline request handler for `theokit start` (T4.2 architecture-cleanup).\n *\n * Wires the per-request flow: security headers → action/route/static branches\n * → SSR fallback → CSR fallback → 500 page.\n *\n * Refactored: CC reduced from 33 to ≤10 per function\n * (architecture-remediation T2.1, 2026-06-12).\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\n\nimport { generateNonce } from '../../../server/auth/nonce.js'\nimport { type ReservedRoutes, serveReservedRoute } from '../../../server/define/health-route.js'\nimport { sendError } from '../../../server/http/send-response.js'\nimport { buildSecurityHeaders } from '../../../server/security/security-headers.js'\n\nimport {\n tryServeAction,\n tryServeAgent,\n tryServeAgentAux,\n tryServeApiRoute,\n tryServeCustom404,\n tryServeStatic,\n type RequestHandlerCtx,\n} from './handlers.js'\nimport {\n isSsrRenderResult,\n type SsrRender,\n type SsrRenderResult,\n type SsrRenderStreaming,\n} from './ssr-setup.js'\n\ninterface RequestHandlerContext {\n buildCtx: (\n req: IncomingMessage,\n res: ServerResponse,\n requestId: string,\n startTime: number,\n ) => RequestHandlerCtx\n securityHeadersConfig: Parameters<typeof buildSecurityHeaders>[0]\n ssrRender: SsrRender | null\n ssrRenderStreaming: SsrRenderStreaming | null\n ssrStreamingEnabled: boolean\n htmlHead: string\n htmlTail: string\n indexHtml: string\n custom500Html: string | null\n /** M7-2: reserved health/ready routes served before the user catch-all. */\n reservedRoutes?: ReservedRoutes\n}\n\n/**\n * M7-2: serve a reserved `/__theo/*` route (health/ready) before any user\n * branch. Returns true when the request was handled.\n */\nasync function tryServeReserved(\n ctx: RequestHandlerContext,\n url: string,\n res: ServerResponse,\n): Promise<boolean> {\n const pathname = new URL(url, 'http://localhost').pathname\n const reserved = await serveReservedRoute(pathname, ctx.reservedRoutes ?? {})\n if (reserved === null) return false\n const payload = JSON.stringify(reserved.body)\n res.writeHead(reserved.status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n })\n res.end(payload)\n return true\n}\n\nfunction asSsrRenderResult(value: SsrRenderResult): SsrRenderResult {\n return value\n}\n\nfunction isRedirectResult(result: unknown): result is { redirect: Response } {\n return result !== null && typeof result === 'object' && 'redirect' in result\n}\n\nfunction sendRedirect(res: ServerResponse, result: { redirect: Response }): void {\n res.writeHead(302, { Location: result.redirect.headers.get('location') ?? '/' })\n res.end()\n}\n\nfunction send500(res: ServerResponse, custom500Html: string | null): void {\n if (!res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'text/html' })\n }\n if (!res.writableEnded) {\n res.end(custom500Html ?? '<h1>500 — Server Error</h1>')\n }\n}\n\nfunction buildSsrHtml(\n ctx: RequestHandlerContext,\n result: string | SsrRenderResult,\n nonce: string,\n): string {\n if (typeof result === 'string') {\n return ctx.htmlHead + result + ctx.htmlTail\n }\n if (isSsrRenderResult(result)) {\n const rendered = asSsrRenderResult(result)\n const dataJson = JSON.stringify(rendered.hydrationData).replace(/</g, '\\\\u003c')\n const hydrationScript = `<script${\n nonce ? ` nonce=\"${nonce}\"` : ''\n }>window.__staticRouterHydrationData=${dataJson}</script>`\n return ctx.htmlHead + rendered.html + hydrationScript + ctx.htmlTail\n }\n return ctx.htmlHead + ctx.htmlTail\n}\n\nasync function handleSsrStreaming(\n ctx: RequestHandlerContext,\n req: IncomingMessage,\n res: ServerResponse,\n url: string,\n nonce: string,\n): Promise<boolean> {\n if (!ctx.ssrStreamingEnabled || !ctx.ssrRenderStreaming) return false\n\n const controller = new AbortController()\n const onClose = (): void => {\n controller.abort()\n }\n req.on('close', onClose)\n try {\n const result = await ctx.ssrRenderStreaming(url, res, {\n signal: controller.signal,\n nonce,\n })\n if (isRedirectResult(result)) sendRedirect(res, result)\n return true\n } catch (streamErr) {\n console.error('[SSR Stream Error]', (streamErr as Error).message)\n send500(res, ctx.custom500Html)\n return true\n } finally {\n req.removeListener('close', onClose)\n }\n}\n\nasync function handleSsrSync(\n ctx: RequestHandlerContext,\n res: ServerResponse,\n url: string,\n nonce: string,\n): Promise<boolean> {\n if (!ctx.ssrRender) return false\n\n try {\n const result = await ctx.ssrRender(url, { nonce })\n if (isRedirectResult(result)) {\n sendRedirect(res, result)\n return true\n }\n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(buildSsrHtml(ctx, result, nonce))\n return true\n } catch (ssrErr) {\n console.error('[SSR Error] Falling back to CSR:', (ssrErr as Error).message)\n return false\n }\n}\n\nfunction handleFatalError(ctx: RequestHandlerContext, res: ServerResponse, err: unknown): void {\n if (ctx.custom500Html && !res.headersSent) {\n res.writeHead(500, { 'Content-Type': 'text/html' })\n res.end(ctx.custom500Html)\n } else if (!res.headersSent) {\n sendError(res, 'INTERNAL_ERROR', (err as Error).message, 500)\n } else {\n res.end()\n }\n}\n\nexport function createRequestHandler(\n ctx: RequestHandlerContext,\n): (req: IncomingMessage, res: ServerResponse) => void {\n return (req: IncomingMessage, res: ServerResponse) => {\n void (async () => {\n const url = req.url ?? '/'\n const requestId = randomUUID()\n const start = Date.now()\n\n const nonce = generateNonce()\n const securityHeaders = buildSecurityHeaders(\n ctx.securityHeadersConfig,\n { production: true },\n { nonce },\n )\n for (const [k, v] of Object.entries(securityHeaders)) {\n res.setHeader(k, v)\n }\n\n const handlerCtx = ctx.buildCtx(req, res, requestId, start)\n\n try {\n if (await tryServeReserved(ctx, url, res)) return\n if (await tryServeAction(handlerCtx)) return\n if (await tryServeAgentAux(handlerCtx)) return\n if (await tryServeAgent(handlerCtx)) return\n if (await tryServeApiRoute(handlerCtx)) return\n if (tryServeStatic(handlerCtx)) return\n if (tryServeCustom404(handlerCtx)) return\n\n if (await handleSsrStreaming(ctx, req, res, url, nonce)) return\n if (await handleSsrSync(ctx, res, url, nonce)) return\n\n // CSR fallback\n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(ctx.indexHtml)\n } catch (err) {\n handleFatalError(ctx, res, err)\n }\n })()\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { extname } from 'node:path'\nimport { pathToFileURL } from 'node:url'\n\nimport { getApprovalRegistry } from '../../../server/agent/approval-registry.js'\nimport { handleAgentApproval, isApprovalPath } from '../../../server/agent/approve-agent.js'\nimport { mountAgent } from '../../../server/agent/mount-agent.js'\nimport { resolveProvider } from '../../../server/agent/provider-resolver.js'\nimport { serveAgentAuxRoute } from '../../../server/agent/serve-aux-routes.js'\nimport { executeAction } from '../../../server/http/action-execute.js'\nimport { dispatchControllerRequest } from '../../../server/http/controller-dispatch.js'\nimport { executeRoute } from '../../../server/http/execute.js'\nimport {\n incomingMessageToWebRequest,\n writeWebResponseToServerResponse,\n} from '../../../server/http/node-web-adapter.js'\nimport { sendError } from '../../../server/http/send-response.js'\nimport { serveStaticFile } from '../../../server/http/static.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 type { ActionNode } from '../../../server/scan/action-scan.js'\nimport type { AgentNode } from '../../../server/scan/agent-scan.js'\nimport { matchRoute } from '../../../server/scan/match.js'\nimport type { ServerRouteNode } from '../../../server/scan/match.js'\nimport type { LoadModule } from '../../../server/scan/module-loader.js'\nimport type { CsrfMode, DisallowedConfig } from '../../../server/security/csrf.js'\nimport type { TheoTransformer } from '../../../server/transformer.js'\n\n/**\n * Load a controller module that `theokit build` already compiled — theokit#123.\n *\n * A plain dynamic `import()`, deliberately: production must not need `@swc/core`. That peer is a\n * native binary the app would otherwise carry solely to re-do work the build already did, and a\n * missing optional peer would degrade into a runtime 404 instead of a build failure.\n */\nasync function loadCompiledController(absPath: string): Promise<Record<string, unknown>> {\n return (await import(pathToFileURL(absPath).href)) as Record<string, unknown>\n}\n\n/** Response header carrying the per-request correlation id. */\nconst X_REQUEST_ID = 'x-request-id'\n\n/**\n * T6.1 (PV-7 SRP): start.ts request orchestrator decomposed into 5 focused\n * per-branch handlers. Each handler returns `true` if it handled the\n * request (response sent) so the orchestrator can stop iterating.\n *\n * The original 455-LOC monolith closed over 14+ locals; the shared shape\n * `RequestHandlerCtx` makes the dependencies explicit + reviewable.\n */\nexport interface RequestHandlerCtx {\n req: IncomingMessage\n res: ServerResponse\n url: string\n requestId: string\n startTime: number\n // Pre-loaded build artifacts\n clientDir: string\n custom404Html: string | null\n // Manifest-resolved tables\n cachedRoutes: ServerRouteNode[]\n cachedActions: ActionNode[]\n cachedAgents: AgentNode[]\n // Runtime infra\n loadModule: LoadModule\n serverDir: string\n /** App root (= `process.cwd()` at `theokit start`); mountAgent points `.theokit/` discovery here. */\n projectRoot: string\n /**\n * theokit#123 — absolute path to the COMPILED controllers emitted by `theokit build`\n * (`<distDir>/controllers`), or `undefined` when the build produced none.\n *\n * `undefined` is the routes-only app, and it must stay free: no scan, no import, no cost.\n */\n controllersDistDir: string | undefined\n pluginRunner: PluginRunner | undefined\n transformer: TheoTransformer | undefined\n csrfMode: CsrfMode\n disallowed: DisallowedConfig | undefined\n rateLimiter:\n | ((req: IncomingMessage) => { limited: boolean; headers: Record<string, string> })\n | null\n}\n\n/** Apply rate limit; return true if request was limited (response sent). */\nfunction applyRateLimit(c: RequestHandlerCtx, method: string): boolean {\n if (!c.rateLimiter) return false\n const check = c.rateLimiter(c.req)\n for (const [k, v] of Object.entries(check.headers)) c.res.setHeader(k, v)\n if (check.limited) {\n sendError(c.res, 'RATE_LIMITED', 'Too many requests', 429, undefined, c.requestId)\n logRequest({\n method,\n url: c.url,\n status: 429,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n return false\n}\n\n/** Branch 1: action routes (`/api/__actions/{file}/{exportName}`). */\nexport async function tryServeAction(c: RequestHandlerCtx): Promise<boolean> {\n if (!c.url.startsWith('/api/__actions/')) return false\n c.res.setHeader(X_REQUEST_ID, c.requestId)\n\n if (applyRateLimit(c, c.req.method ?? 'POST')) return true\n\n const pathAfterPrefix = c.url.slice('/api/__actions/'.length).split('?')[0]\n const segments = pathAfterPrefix.split('/').filter(Boolean)\n if (segments.length < 2) {\n sendError(\n c.res,\n 'BAD_REQUEST',\n 'Action URL must be /api/__actions/{file}/{exportName}',\n 400,\n undefined,\n c.requestId,\n )\n logRequest({\n method: c.req.method ?? 'POST',\n url: c.url,\n status: 400,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n const exportName = segments[segments.length - 1]\n const actionPath = segments.slice(0, -1).join('/')\n const action = c.cachedActions.find((a) => a.actionPath === actionPath)\n if (!action) {\n const actionPaths = c.cachedActions.map((a) => a.actionPath)\n const suggestion = findSuggestion(actionPath, actionPaths)\n const msg = suggestion\n ? `Action \"${actionPath}\" not found. Did you mean: ${suggestion}?`\n : `Action \"${actionPath}\" not found`\n sendError(c.res, 'NOT_FOUND', msg, 404, undefined, c.requestId)\n logRequest({\n method: c.req.method ?? 'POST',\n url: c.url,\n status: 404,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n await executeAction(\n action.filePath,\n exportName,\n c.req,\n c.res,\n c.loadModule,\n c.serverDir,\n c.requestId,\n c.pluginRunner,\n c.csrfMode,\n c.disallowed,\n )\n logRequest({\n method: c.req.method ?? 'POST',\n url: c.url,\n status: c.res.statusCode,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n}\n\n/**\n * Branch 1.4: agent AUXILIARY routes served identically in dev + prod (M15/M16 follow-up) —\n * agent cards (`/.well-known/<name>/agent-card.json`), MCP (`/api/agents/<name>/mcp`), and the\n * pending-approvals listing (`/api/agents/<name>/approvals`). Before this, they were dev-only, so a\n * built/deployed app 404'd them. Delegates to the shared `serveAgentAuxRoute` dispatcher (DRY).\n */\nexport async function tryServeAgentAux(c: RequestHandlerCtx): Promise<boolean> {\n const urlPath = c.url.split('?')[0]\n const baseUrl = `http://${c.req.headers.host ?? 'localhost'}`\n const request = incomingMessageToWebRequest(c.req)\n const response = await serveAgentAuxRoute(request, urlPath, {\n agents: c.cachedAgents,\n loadModule: c.loadModule,\n baseUrl,\n // M34 (#97) — the MCP aux route drives the agent (spends tokens); enforce CSRF like the run route.\n csrfMode: c.csrfMode,\n // M39 — the thread follow-up route drives the agent; resolve the key on demand.\n resolveApiKey: () => resolveProvider().apiKey,\n })\n if (response === null) return false\n c.res.setHeader(X_REQUEST_ID, c.requestId)\n await writeWebResponseToServerResponse(response, c.res)\n logRequest({\n method: (c.req.method ?? 'GET').toUpperCase(),\n url: c.url,\n status: c.res.statusCode,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n}\n\n/**\n * Branch 1.5: agent convention routes (`/api/agents/<name>`, M2). Runs BEFORE the generic `/api/*`\n * branch so a scanned `agents/<name>.ts` owns its path (parity with dev). Loads the module, resolves\n * the provider apiKey (fail-fast), and streams the M0/M1 UIMessageStream via `mountAgent`.\n */\nexport async function tryServeAgent(c: RequestHandlerCtx): Promise<boolean> {\n if (!c.url.startsWith('/api/agents/')) return false\n const urlPath = c.url.split('?')[0]\n\n // HITL approve route (`/api/agents/<name>/approve/<id>`, M4) — resolve the pending approval.\n // Handled BEFORE the agent-path exact match (the approve path never equals an `agentPath`).\n if (isApprovalPath(urlPath)) {\n c.res.setHeader(X_REQUEST_ID, c.requestId)\n if (applyRateLimit(c, c.req.method ?? 'POST')) return true\n const method = (c.req.method ?? 'POST').toUpperCase()\n if (method !== 'POST') {\n sendError(\n c.res,\n 'METHOD_NOT_ALLOWED',\n 'Approve endpoints accept POST',\n 405,\n undefined,\n c.requestId,\n )\n logRequest({\n method,\n url: c.url,\n status: 405,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n try {\n const request = incomingMessageToWebRequest(c.req)\n const response = await handleAgentApproval(\n request,\n urlPath,\n getApprovalRegistry(),\n c.csrfMode,\n )\n await writeWebResponseToServerResponse(response, c.res)\n } catch (err) {\n sendError(\n c.res,\n 'INTERNAL',\n err instanceof Error ? err.message : 'Approve handler failed',\n 500,\n undefined,\n c.requestId,\n )\n }\n logRequest({\n method,\n url: c.url,\n status: c.res.statusCode,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n\n const agent = c.cachedAgents.find((a) => a.agentPath === urlPath)\n if (!agent) return false // fall through to the generic /api/* branch (may 404 there)\n\n c.res.setHeader(X_REQUEST_ID, c.requestId)\n if (applyRateLimit(c, c.req.method ?? 'POST')) return true\n\n const method = (c.req.method ?? 'POST').toUpperCase()\n if (method !== 'POST') {\n sendError(\n c.res,\n 'METHOD_NOT_ALLOWED',\n 'Agent endpoints accept POST',\n 405,\n undefined,\n c.requestId,\n )\n logRequest({\n method,\n url: c.url,\n status: 405,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n\n try {\n const mod = await c.loadModule(agent.filePath)\n const apiKey = resolveProvider().apiKey\n const request = incomingMessageToWebRequest(c.req)\n const response = await mountAgent(mod, request, apiKey, {\n source: agent.filePath,\n csrfMode: c.csrfMode,\n projectRoot: c.projectRoot,\n })\n await writeWebResponseToServerResponse(response, c.res)\n } catch (err) {\n sendError(\n c.res,\n 'INTERNAL',\n err instanceof Error ? err.message : 'Agent handler failed',\n 500,\n undefined,\n c.requestId,\n )\n }\n logRequest({\n method,\n url: c.url,\n status: c.res.statusCode,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n}\n\n/** Branch 2: API routes (`/api/*` excluding actions). */\nexport async function tryServeApiRoute(c: RequestHandlerCtx): Promise<boolean> {\n if (!c.url.startsWith('/api/')) return false\n c.res.setHeader(X_REQUEST_ID, c.requestId)\n\n if (applyRateLimit(c, c.req.method ?? 'GET')) return true\n\n const match = matchRoute(c.url, c.cachedRoutes)\n if (!match) {\n // theokit#123 — controller fall-through, mirroring the dev `api-middleware` arm.\n //\n // Before this, `theokit dev` served a decorator controller and `theokit start` 404'd it: the\n // production path has no Vite/swc transform, so an uncompiled `.controller.ts` could not load.\n // `theokit build` now emits compiled modules and this branch serves them, so the SAME app\n // answers the same routes in both. Reached only after a file-route miss, so file routes keep\n // precedence exactly as in dev.\n if (c.controllersDistDir !== undefined) {\n const handled = await dispatchControllerRequest({\n controllersDir: c.controllersDistDir,\n loadModule: loadCompiledController,\n req: c.req,\n res: c.res,\n csrfMode: c.csrfMode,\n disallowed: c.disallowed,\n requestId: c.requestId,\n })\n if (handled) return true\n }\n const urlPath = c.url.split('?')[0]\n const routePaths = c.cachedRoutes.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(c.res, 'NOT_FOUND', msg, 404, undefined, c.requestId)\n logRequest({\n method: c.req.method ?? 'GET',\n url: c.url,\n status: 404,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n }\n const method = (c.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: c.req,\n res: c.res,\n loadModule: c.loadModule,\n serverDir: c.serverDir,\n requestId: c.requestId,\n pluginRunner: c.pluginRunner,\n transformer: c.transformer,\n csrfMode: c.csrfMode,\n disallowed: c.disallowed,\n })\n logRequest({\n method,\n url: c.url,\n status: c.res.statusCode,\n duration: Date.now() - c.startTime,\n requestId: c.requestId,\n })\n return true\n}\n\n/** Branch 3: static files (returns true if a static asset was served). */\nexport function tryServeStatic(c: RequestHandlerCtx): boolean {\n return serveStaticFile(c.req, c.res, c.clientDir)\n}\n\n/** Branch 4: custom 404 for URLs that look like missing assets. */\nexport function tryServeCustom404(c: RequestHandlerCtx): boolean {\n const urlPath = c.url.split('?')[0]\n if (c.custom404Html && extname(urlPath)) {\n c.res.writeHead(404, { 'Content-Type': 'text/html' })\n c.res.end(c.custom404Html)\n return true\n }\n return false\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Static-file server. The URL path IS user-controlled, BUT before any fs\n * call we resolve to absolute and reject with 403 if the resolved path\n * escapes `clientDir` (see EC-1 guard at line below). The guard is\n * authoritative; the rule cannot see it.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { resolve, extname } from 'node:path'\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'application/javascript',\n '.mjs': 'application/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.txt': 'text/plain',\n '.map': 'application/json',\n}\n\nexport function serveStaticFile(\n req: IncomingMessage,\n res: ServerResponse,\n clientDir: string,\n): boolean {\n const urlPath = (req.url ?? '/').split('?')[0]\n\n // Path traversal prevention (EC-1)\n const filePath = resolve(clientDir, '.' + urlPath)\n if (!filePath.startsWith(clientDir)) {\n res.writeHead(403)\n res.end('Forbidden')\n return true\n }\n\n if (!existsSync(filePath)) return false\n\n const stat = statSync(filePath)\n if (!stat.isFile()) return false\n\n const ext = extname(filePath)\n const contentType = MIME_TYPES[ext] ?? 'application/octet-stream'\n const content = readFileSync(filePath)\n\n res.writeHead(200, {\n 'Content-Type': contentType,\n 'Content-Length': content.length,\n })\n res.end(content)\n return true\n}\n","/**\n * SSR setup stage for `theokit start` (T4.2 architecture-cleanup).\n *\n * Loads the SSR entry-server module if configured + builds template split\n * around the React root div. Returns null renderers when SSR is disabled.\n */\n\nimport type { ServerResponse } from 'node:http'\n\nimport { resolveSsrEntry } from './bootstrap-stages.js'\n\nexport interface SsrRenderResult {\n html: string\n hydrationData: {\n loaderData?: unknown\n actionData?: unknown\n errors?: unknown\n }\n}\n\nexport type RenderStreamingResult = { redirect: Response } | { streaming: true } | undefined\n\nexport type SsrRender = (\n url: string,\n options?: { nonce?: string },\n) => Promise<SsrRenderResult | { redirect: Response } | string>\n\nexport type SsrRenderStreaming = (\n url: string,\n response: ServerResponse,\n options?: { signal?: AbortSignal; nonce?: string },\n) => Promise<RenderStreamingResult>\n\ninterface SsrSetupResult {\n enabled: boolean\n streamingEnabled: boolean\n render: SsrRender | null\n renderStreaming: SsrRenderStreaming | null\n htmlHead: string\n htmlTail: string\n}\n\nexport function isSsrRenderResult(value: unknown): value is SsrRenderResult {\n if (typeof value !== 'object' || value === null) return false\n if (!('html' in value)) return false\n const html = (value as Record<string, unknown>).html\n if (typeof html !== 'string') return false\n return true\n}\n\ninterface SsrEntryServer {\n render: SsrRender\n renderStreaming?: SsrRenderStreaming\n}\n\nexport async function setupSsr(opts: {\n distDir: string\n indexHtml: string\n ssrConfigEnabled: boolean\n ssrStreamingConfig: boolean | undefined\n}): Promise<SsrSetupResult> {\n const ssrServerPath: string | null = opts.ssrConfigEnabled ? resolveSsrEntry(opts.distDir) : null\n const enabled = ssrServerPath !== null\n const streamingEnabled = enabled && Boolean(opts.ssrStreamingConfig)\n\n if (ssrServerPath === null) {\n return {\n enabled: false,\n streamingEnabled: false,\n render: null,\n renderStreaming: null,\n htmlHead: '',\n htmlTail: '',\n }\n }\n\n const mod = (await import(ssrServerPath)) as SsrEntryServer\n const render = mod.render\n const renderStreaming = typeof mod.renderStreaming === 'function' ? mod.renderStreaming : null\n\n // Split HTML template on root div\n let htmlHead = ''\n let htmlTail = ''\n const rootDivMatch = /<div id=[\"']root[\"'][^>]*>/.exec(opts.indexHtml)\n if (rootDivMatch) {\n const splitIdx = opts.indexHtml.indexOf(rootDivMatch[0]) + rootDivMatch[0].length\n htmlHead = opts.indexHtml.slice(0, splitIdx)\n htmlTail = opts.indexHtml.slice(splitIdx)\n }\n\n return { enabled, streamingEnabled, render, renderStreaming, htmlHead, htmlTail }\n}\n","/**\n * WebSocket upgrade handler for `theokit start` (T4.2 architecture-cleanup).\n *\n * Wires `server.on('upgrade')` for declared WS routes. Opt-in: only attached\n * when `wsRoutes.length > 0`. Lazy-imports `ws` package — throws an actionable\n * error when wsRoutes declared but `ws` not installed.\n */\n\nimport type { Server as HttpServer } from 'node:http'\n\nimport type * as WsLib from 'ws'\n\nimport type { WebSocketHandler } from '../../../server/define/define-websocket.js'\nimport type { LoadModule } from '../../../server/scan/module-loader.js'\nimport type { WebSocketRouteNode } from '../../../server/scan/ws-scan.js'\n\nexport async function attachWebSocketHandler(\n server: HttpServer,\n wsRoutes: WebSocketRouteNode[],\n loadModule: LoadModule,\n): Promise<void> {\n if (wsRoutes.length === 0) return\n\n let WebSocketServerCtor: typeof WsLib.WebSocketServer\n try {\n const wsModule = await import('ws')\n WebSocketServerCtor = wsModule.WebSocketServer\n } catch {\n throw new Error('WebSocket routes found but \"ws\" package is not installed. Run: npm install ws')\n }\n\n const wss = new WebSocketServerCtor({ noServer: true })\n\n server.on('upgrade', (request, socket, head) => {\n void (async () => {\n const url = request.url ?? '/'\n if (!url.startsWith('/ws/')) {\n socket.destroy()\n return\n }\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 loadModule(match.filePath)\n const handler = ((mod as { default?: unknown }).default ?? mod) as WebSocketHandler\n\n wss.handleUpgrade(request, socket, head, (ws) => {\n handler.onOpen?.(ws, request)\n ws.on('message', (data: Buffer) => {\n handler.onMessage?.(ws, data.toString())\n })\n ws.on('close', (code: number, reason: Buffer) => {\n handler.onClose?.(ws, code, reason)\n })\n ws.on('error', (err: Error) => {\n handler.onError?.(ws, err)\n })\n })\n } catch {\n socket.destroy()\n }\n })()\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAS,cAAAA,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,oBAAoB;AAC7B,SAAS,QAAAC,OAAM,WAAAC,gBAAe;;;ACDvB,IAAM,cAAc;AAEpB,IAAM,aAAa;AAgCnB,SAAS,kBACd,UAAyB,OAAO,EAAE,QAAQ,KAAK,IAC5B;AACnB,SAAO,EAAE,MAAM,UAAU,QAAQ;AACnC;AAgBA,eAAsB,mBACpB,UACA,SAAyB,CAAC,GACQ;AAClC,MAAI,aAAa,aAAa;AAC5B,UAAM,UAAU,OAAO,QAAQ,YAAY,OAAO,EAAE,QAAQ,KAAK;AACjE,WAAO,EAAE,QAAQ,KAAK,MAAM,QAAQ,EAAE;AAAA,EACxC;AACA,MAAI,aAAa,YAAY;AAC3B,UAAM,QAAQ,OAAO,OAAO;AAC5B,QAAI,UAAU,QAAW;AACvB,aAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,QAAQ,EAAE;AAAA,IAClD;AACA,QAAI;AACF,YAAM,QAAQ,MAAM,MAAM;AAC1B,aAAO,QACH,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,QAAQ,EAAE,IACzC,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,YAAY,EAAE;AAAA,IACnD,SAAS,KAAK;AAIZ,cAAQ,MAAM,6DAAwD,GAAG;AACzE,aAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,QAAQ,YAAY,EAAE;AAAA,IACtD;AAAA,EACF;AACA,SAAO;AACT;;;ACnFA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;;;ACDvB,IAAM,sBAAsB;AAKnC,IAAM,YAAY;AAUlB,SAAS,YAAY,OAA8B;AACjD,QAAM,IAAI,UAAU,KAAK,KAAK;AAC9B,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;AACvE;AAQO,SAAS,kBAAkB,SAAiB,OAAwB;AACzE,SAAO,MACJ,MAAM,IAAI,EACV,IAAI,CAAC,WAAW,OAAO,KAAK,CAAC,EAC7B,KAAK,CAAC,WAAW,qBAAqB,SAAS,MAAM,CAAC;AAC3D;AAEA,SAAS,qBAAqB,SAAiB,OAAwB;AACrE,MAAI,CAAC,MAAM,WAAW,GAAG,EAAG,QAAO;AACnC,QAAM,MAAM,YAAY,MAAM,MAAM,CAAC,CAAC;AACtC,QAAM,MAAM,YAAY,OAAO;AAC/B,MAAI,CAAC,OAAO,CAAC,IAAK,QAAO;AACzB,MAAI,IAAI,QAAQ,OAAW,QAAO,yBAAyB,KAAK,GAAG;AACnE,MAAI,IAAI,QAAQ,OAAW,QAAO;AAClC,SAAO,qBAAqB,KAAK,GAAG;AACtC;AAEA,SAAS,yBAAyB,KAAa,KAAsB;AAEnE,MAAI,IAAI,UAAU,IAAI,SAAS,IAAI,UAAU,IAAI,SAAS,IAAI,UAAU,IAAI,MAAO,QAAO;AAC1F,MAAI,IAAI,QAAQ,IAAI,IAAK,QAAO;AAChC,SAAO,OAAO,IAAI,OAAO,GAAG,KAAK,OAAO,IAAI,OAAO,GAAG;AACxD;AAEA,SAAS,qBAAqB,KAAa,KAAsB;AAC/D,MAAI,IAAI,UAAU,IAAI,MAAO,QAAO;AACpC,MAAI,IAAI,UAAU,KAAK;AAErB,QAAI,IAAI,UAAU,IAAI,MAAO,QAAO;AACpC,WAAO,OAAO,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK;AAAA,EAC9C;AAEA,MAAI,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,EAAG,QAAO;AAClD,MAAI,OAAO,IAAI,KAAK,MAAM,OAAO,IAAI,KAAK,EAAG,QAAO,OAAO,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK;AACzF,SAAO;AACT;;;ADxDO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EACrC,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACT,YAAY,OAA2B,UAAkB;AACvD;AAAA,MACE,UAAU,SACN,gFAA2E,QAAQ,KACnF,gBAAgB,KAAK,wCAAwC,QAAQ,sCAAiC,QAAQ;AAAA,IACpH;AACA,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,WAAW;AAAA,EAClB;AACF;AAGA,SAAS,2BAA+C;AACtD,MAAI;AACF,UAAMC,WAAU,cAAc,YAAY,GAAG;AAC7C,UAAM,UAAUA,SAAQ,QAAQ,2BAA2B;AAC3D,UAAM,MAAM,KAAK,MAAM,aAAa,SAAS,MAAM,CAAC;AACpD,WAAO,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYO,SAAS,oBAAoB,MAG3B;AACP,QAAM,WAAW,MAAM,kBAAkB,0BAA0B;AACnE,MAAI,YAAY,QAAW;AACzB,QAAI,MAAM,aAAa,KAAM,OAAM,IAAI,qBAAqB,QAAW,mBAAmB;AAC1F;AAAA,EACF;AACA,MAAI,CAAC,kBAAkB,SAAS,mBAAmB,GAAG;AACpD,UAAM,IAAI,qBAAqB,SAAS,mBAAmB;AAAA,EAC7D;AACF;;;AEvDA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AAgBxB,eAAsB,iCACpB,gBACe;AACf,MAAI,mBAAmB,OAAW;AAClC,MAAI;AACF,UAAM,MAAO,MAAM,OAAO,cAAc,EAAE,MAAM,MAAM,IAAI;AAC1D,UAAM,eAAe,KAAK,OAAO,UAAU;AAC3C,QAAI,iBAAiB,OAAW;AAChC,UAAM,EAAE,2BAA2B,IACjC,MAAM,OAAO,wCAAmD;AAClE;AAAA,MACE;AAAA,QACE,WAAW,CAAC,SAAS;AACnB,uBAAa,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,aAAS,iCAAiC;AAAA,MACxC,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAOA,eAAsB,kCAAkC,eAAuC;AAC7F,MAAI,kBAAkB,UAAa,kBAAkB,KAAM;AAC3D,MAAI;AACF,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,+BAA4C;AACvF,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAA2B;AAGlE,UAAM,SAAS,cAAc,MAAM,aAAa;AAChD,sBAAkB,EAAE,UAAU,MAAM;AAAA,EACtC,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,aAAS,0BAA0B;AAAA,MACjC,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAEA,IAAM,iBAAiB,CAAC,QAAQ,KAAK;AAU9B,SAAS,gBAAgB,SAAgC;AAC9D,aAAW,OAAO,gBAAgB;AAChC,UAAM,OAAO,QAAQ,SAAS,sBAAsB,GAAG,EAAE;AAEzD,QAAI,WAAW,IAAI,EAAG,QAAO;AAAA,EAC/B;AACA,SAAO;AACT;;;ACjFO,SAAS,wBAAwB,QAA0B;AAChE,MAAI,eAAe;AACnB,QAAM,WAAW,CAAC,WAAiC;AACjD,QAAI,aAAc;AAClB,mBAAe;AACf,YAAQ,IAAI;AAAA,cAAiB,MAAM,kCAA6B;AAChE,UAAM,YAAY;AAGhB,UAAI;AACF,cAAM,MAAO,MAAM,OAAO,cAAc,EAAE,MAAM,MAAM,IAAI;AAG1D,YAAI,KAAK,OAAO,UAAU,aAAa,QAAW;AAChD,gBAAM,IAAI,MAAM,SAAS,SAAS;AAAA,QACpC;AAAA,MACF,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,iBAAS,wBAAwB;AAAA,UAC/B,OAAO;AAAA,UACP,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAIA,UAAI;AACF,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,+BAA4C;AACvF,cAAM,UAAU,kBAAkB;AAClC,cAAM,QAAQ,QAAQ;AAAA,MACxB,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,iBAAS,0BAA0B;AAAA,UACjC,OAAO;AAAA,UACP,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA,cAAQ,IAAI,+BAA+B;AAC3C,aAAO,MAAM,MAAM;AACjB,gBAAQ,KAAK,CAAC;AAAA,MAChB,CAAC;AACD,iBAAW,MAAM;AACf,iBAAS,wBAAwB;AAAA,UAC/B,OAAO;AAAA,UACP,SAAS;AAAA,QACX,CAAC;AACD,gBAAQ,KAAK,CAAC;AAAA,MAChB,GAAG,IAAM,EAAE,MAAM;AAAA,IACnB,GAAG;AAAA,EACL;AACA,UAAQ,GAAG,WAAW,MAAM;AAC1B,aAAS,SAAS;AAAA,EACpB,CAAC;AACD,UAAQ,GAAG,UAAU,MAAM;AACzB,aAAS,QAAQ;AAAA,EACnB,CAAC;AACH;;;ACjEA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,YAAY;AACrB,SAAS,eAAe;AAoBjB,SAAS,qBACd,SACA,WAEA,YAAY,UACE;AACd,QAAM,eAAe,KAAK,SAAS,eAAe;AAElD,MAAIC,YAAW,YAAY,GAAG;AAC5B,UAAM,WAAW,aAAa,SAAS,SAAS;AAChD,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS;AAAA,MAClB,UAAU,SAAS;AAAA,MACnB,QAAQ,SAAS;AAAA,IACnB;AAAA,EACF;AACA,WAAS,gCAAgC;AAAA,IACvC,OAAO;AAAA,IACP,SACE;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,QAAQ,iBAAiB,SAAS;AAAA,IAClC,SAAS,kBAAkB,SAAS;AAAA,IACpC,UAAU,oBAAoB,SAAS;AAAA;AAAA,IAEvC,QAAQ,WAAW,QAAQ,SAAS,GAAG,SAAS;AAAA,EAClD;AACF;;;ACjDA,SAAS,kBAAkB;;;ACT3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,qBAAqB;;;ACI9B,SAAS,cAAAC,aAAY,gBAAAC,eAAc,gBAAgB;AAEnD,SAAS,WAAAC,UAAS,eAAe;AAEjC,IAAM,aAAqC;AAAA,EACzC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,SAAS,gBACd,KACA,KACA,WACS;AACT,QAAM,WAAW,IAAI,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC;AAG7C,QAAM,WAAWA,SAAQ,WAAW,MAAM,OAAO;AACjD,MAAI,CAAC,SAAS,WAAW,SAAS,GAAG;AACnC,QAAI,UAAU,GAAG;AACjB,QAAI,IAAI,WAAW;AACnB,WAAO;AAAA,EACT;AAEA,MAAI,CAACF,YAAW,QAAQ,EAAG,QAAO;AAElC,QAAM,OAAO,SAAS,QAAQ;AAC9B,MAAI,CAAC,KAAK,OAAO,EAAG,QAAO;AAE3B,QAAM,MAAM,QAAQ,QAAQ;AAC5B,QAAM,cAAc,WAAW,GAAG,KAAK;AACvC,QAAM,UAAUC,cAAa,QAAQ;AAErC,MAAI,UAAU,KAAK;AAAA,IACjB,gBAAgB;AAAA,IAChB,kBAAkB,QAAQ;AAAA,EAC5B,CAAC;AACD,MAAI,IAAI,OAAO;AACf,SAAO;AACT;;;ADvBA,eAAe,uBAAuB,SAAmD;AACvF,SAAQ,MAAM,OAAO,cAAc,OAAO,EAAE;AAC9C;AAGA,IAAM,eAAe;AA6CrB,SAAS,eAAe,GAAsB,QAAyB;AACrE,MAAI,CAAC,EAAE,YAAa,QAAO;AAC3B,QAAM,QAAQ,EAAE,YAAY,EAAE,GAAG;AACjC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,OAAO,EAAG,GAAE,IAAI,UAAU,GAAG,CAAC;AACxE,MAAI,MAAM,SAAS;AACjB,cAAU,EAAE,KAAK,gBAAgB,qBAAqB,KAAK,QAAW,EAAE,SAAS;AACjF,eAAW;AAAA,MACT;AAAA,MACA,KAAK,EAAE;AAAA,MACP,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGA,eAAsB,eAAe,GAAwC;AAC3E,MAAI,CAAC,EAAE,IAAI,WAAW,iBAAiB,EAAG,QAAO;AACjD,IAAE,IAAI,UAAU,cAAc,EAAE,SAAS;AAEzC,MAAI,eAAe,GAAG,EAAE,IAAI,UAAU,MAAM,EAAG,QAAO;AAEtD,QAAM,kBAAkB,EAAE,IAAI,MAAM,kBAAkB,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC;AAC1E,QAAM,WAAW,gBAAgB,MAAM,GAAG,EAAE,OAAO,OAAO;AAC1D,MAAI,SAAS,SAAS,GAAG;AACvB;AAAA,MACE,EAAE;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE;AAAA,IACJ;AACA,eAAW;AAAA,MACT,QAAQ,EAAE,IAAI,UAAU;AAAA,MACxB,KAAK,EAAE;AAAA,MACP,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AACA,QAAM,aAAa,SAAS,SAAS,SAAS,CAAC;AAC/C,QAAM,aAAa,SAAS,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AACjD,QAAM,SAAS,EAAE,cAAc,KAAK,CAAC,MAAM,EAAE,eAAe,UAAU;AACtE,MAAI,CAAC,QAAQ;AACX,UAAM,cAAc,EAAE,cAAc,IAAI,CAAC,MAAM,EAAE,UAAU;AAC3D,UAAM,aAAa,eAAe,YAAY,WAAW;AACzD,UAAM,MAAM,aACR,WAAW,UAAU,8BAA8B,UAAU,MAC7D,WAAW,UAAU;AACzB,cAAU,EAAE,KAAK,aAAa,KAAK,KAAK,QAAW,EAAE,SAAS;AAC9D,eAAW;AAAA,MACT,QAAQ,EAAE,IAAI,UAAU;AAAA,MACxB,KAAK,EAAE;AAAA,MACP,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AACA,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,IACF,EAAE;AAAA,EACJ;AACA,aAAW;AAAA,IACT,QAAQ,EAAE,IAAI,UAAU;AAAA,IACxB,KAAK,EAAE;AAAA,IACP,QAAQ,EAAE,IAAI;AAAA,IACd,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,IACzB,WAAW,EAAE;AAAA,EACf,CAAC;AACD,SAAO;AACT;AAQA,eAAsB,iBAAiB,GAAwC;AAC7E,QAAM,UAAU,EAAE,IAAI,MAAM,GAAG,EAAE,CAAC;AAClC,QAAM,UAAU,UAAU,EAAE,IAAI,QAAQ,QAAQ,WAAW;AAC3D,QAAM,UAAU,4BAA4B,EAAE,GAAG;AACjD,QAAM,WAAW,MAAM,mBAAmB,SAAS,SAAS;AAAA,IAC1D,QAAQ,EAAE;AAAA,IACV,YAAY,EAAE;AAAA,IACd;AAAA;AAAA,IAEA,UAAU,EAAE;AAAA;AAAA,IAEZ,eAAe,MAAM,gBAAgB,EAAE;AAAA,EACzC,CAAC;AACD,MAAI,aAAa,KAAM,QAAO;AAC9B,IAAE,IAAI,UAAU,cAAc,EAAE,SAAS;AACzC,QAAM,iCAAiC,UAAU,EAAE,GAAG;AACtD,aAAW;AAAA,IACT,SAAS,EAAE,IAAI,UAAU,OAAO,YAAY;AAAA,IAC5C,KAAK,EAAE;AAAA,IACP,QAAQ,EAAE,IAAI;AAAA,IACd,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,IACzB,WAAW,EAAE;AAAA,EACf,CAAC;AACD,SAAO;AACT;AAOA,eAAsB,cAAc,GAAwC;AAC1E,MAAI,CAAC,EAAE,IAAI,WAAW,cAAc,EAAG,QAAO;AAC9C,QAAM,UAAU,EAAE,IAAI,MAAM,GAAG,EAAE,CAAC;AAIlC,MAAI,eAAe,OAAO,GAAG;AAC3B,MAAE,IAAI,UAAU,cAAc,EAAE,SAAS;AACzC,QAAI,eAAe,GAAG,EAAE,IAAI,UAAU,MAAM,EAAG,QAAO;AACtD,UAAME,WAAU,EAAE,IAAI,UAAU,QAAQ,YAAY;AACpD,QAAIA,YAAW,QAAQ;AACrB;AAAA,QACE,EAAE;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,EAAE;AAAA,MACJ;AACA,iBAAW;AAAA,QACT,QAAAA;AAAA,QACA,KAAK,EAAE;AAAA,QACP,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,QACzB,WAAW,EAAE;AAAA,MACf,CAAC;AACD,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,UAAU,4BAA4B,EAAE,GAAG;AACjD,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA;AAAA,QACA,oBAAoB;AAAA,QACpB,EAAE;AAAA,MACJ;AACA,YAAM,iCAAiC,UAAU,EAAE,GAAG;AAAA,IACxD,SAAS,KAAK;AACZ;AAAA,QACE,EAAE;AAAA,QACF;AAAA,QACA,eAAe,QAAQ,IAAI,UAAU;AAAA,QACrC;AAAA,QACA;AAAA,QACA,EAAE;AAAA,MACJ;AAAA,IACF;AACA,eAAW;AAAA,MACT,QAAAA;AAAA,MACA,KAAK,EAAE;AAAA,MACP,QAAQ,EAAE,IAAI;AAAA,MACd,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,EAAE,aAAa,KAAK,CAAC,MAAM,EAAE,cAAc,OAAO;AAChE,MAAI,CAAC,MAAO,QAAO;AAEnB,IAAE,IAAI,UAAU,cAAc,EAAE,SAAS;AACzC,MAAI,eAAe,GAAG,EAAE,IAAI,UAAU,MAAM,EAAG,QAAO;AAEtD,QAAM,UAAU,EAAE,IAAI,UAAU,QAAQ,YAAY;AACpD,MAAI,WAAW,QAAQ;AACrB;AAAA,MACE,EAAE;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,EAAE;AAAA,IACJ;AACA,eAAW;AAAA,MACT;AAAA,MACA,KAAK,EAAE;AAAA,MACP,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,MAAM,EAAE,WAAW,MAAM,QAAQ;AAC7C,UAAM,SAAS,gBAAgB,EAAE;AACjC,UAAM,UAAU,4BAA4B,EAAE,GAAG;AACjD,UAAM,WAAW,MAAM,WAAW,KAAK,SAAS,QAAQ;AAAA,MACtD,QAAQ,MAAM;AAAA,MACd,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE;AAAA,IACjB,CAAC;AACD,UAAM,iCAAiC,UAAU,EAAE,GAAG;AAAA,EACxD,SAAS,KAAK;AACZ;AAAA,MACE,EAAE;AAAA,MACF;AAAA,MACA,eAAe,QAAQ,IAAI,UAAU;AAAA,MACrC;AAAA,MACA;AAAA,MACA,EAAE;AAAA,IACJ;AAAA,EACF;AACA,aAAW;AAAA,IACT;AAAA,IACA,KAAK,EAAE;AAAA,IACP,QAAQ,EAAE,IAAI;AAAA,IACd,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,IACzB,WAAW,EAAE;AAAA,EACf,CAAC;AACD,SAAO;AACT;AAGA,eAAsB,iBAAiB,GAAwC;AAC7E,MAAI,CAAC,EAAE,IAAI,WAAW,OAAO,EAAG,QAAO;AACvC,IAAE,IAAI,UAAU,cAAc,EAAE,SAAS;AAEzC,MAAI,eAAe,GAAG,EAAE,IAAI,UAAU,KAAK,EAAG,QAAO;AAErD,QAAM,QAAQ,WAAW,EAAE,KAAK,EAAE,YAAY;AAC9C,MAAI,CAAC,OAAO;AAQV,QAAI,EAAE,uBAAuB,QAAW;AACtC,YAAM,UAAU,MAAM,0BAA0B;AAAA,QAC9C,gBAAgB,EAAE;AAAA,QAClB,YAAY;AAAA,QACZ,KAAK,EAAE;AAAA,QACP,KAAK,EAAE;AAAA,QACP,UAAU,EAAE;AAAA,QACZ,YAAY,EAAE;AAAA,QACd,WAAW,EAAE;AAAA,MACf,CAAC;AACD,UAAI,QAAS,QAAO;AAAA,IACtB;AACA,UAAM,UAAU,EAAE,IAAI,MAAM,GAAG,EAAE,CAAC;AAClC,UAAM,aAAa,EAAE,aAAa,IAAI,CAAC,MAAM,EAAE,SAAS;AACxD,UAAM,aAAa,eAAe,SAAS,UAAU;AACrD,UAAM,MAAM,aACR,wBAAwB,OAAO,mBAAmB,UAAU,MAC5D;AACJ,cAAU,EAAE,KAAK,aAAa,KAAK,KAAK,QAAW,EAAE,SAAS;AAC9D,eAAW;AAAA,MACT,QAAQ,EAAE,IAAI,UAAU;AAAA,MACxB,KAAK,EAAE;AAAA,MACP,QAAQ;AAAA,MACR,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,MACzB,WAAW,EAAE;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT;AACA,QAAM,UAAU,EAAE,IAAI,UAAU,OAAO,YAAY;AAEnD,QAAM,aAAa;AAAA,IACjB,OAAO,MAAM;AAAA,IACb;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,KAAK,EAAE;AAAA,IACP,KAAK,EAAE;AAAA,IACP,YAAY,EAAE;AAAA,IACd,WAAW,EAAE;AAAA,IACb,WAAW,EAAE;AAAA,IACb,cAAc,EAAE;AAAA,IAChB,aAAa,EAAE;AAAA,IACf,UAAU,EAAE;AAAA,IACZ,YAAY,EAAE;AAAA,EAChB,CAAC;AACD,aAAW;AAAA,IACT;AAAA,IACA,KAAK,EAAE;AAAA,IACP,QAAQ,EAAE,IAAI;AAAA,IACd,UAAU,KAAK,IAAI,IAAI,EAAE;AAAA,IACzB,WAAW,EAAE;AAAA,EACf,CAAC;AACD,SAAO;AACT;AAGO,SAAS,eAAe,GAA+B;AAC5D,SAAO,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS;AAClD;AAGO,SAAS,kBAAkB,GAA+B;AAC/D,QAAM,UAAU,EAAE,IAAI,MAAM,GAAG,EAAE,CAAC;AAClC,MAAI,EAAE,iBAAiBC,SAAQ,OAAO,GAAG;AACvC,MAAE,IAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AACpD,MAAE,IAAI,IAAI,EAAE,aAAa;AACzB,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AE5WO,SAAS,kBAAkB,OAA0C;AAC1E,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI,EAAE,UAAU,OAAQ,QAAO;AAC/B,QAAM,OAAQ,MAAkC;AAChD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAO;AACT;AAOA,eAAsB,SAAS,MAKH;AAC1B,QAAM,gBAA+B,KAAK,mBAAmB,gBAAgB,KAAK,OAAO,IAAI;AAC7F,QAAM,UAAU,kBAAkB;AAClC,QAAM,mBAAmB,WAAW,QAAQ,KAAK,kBAAkB;AAEnE,MAAI,kBAAkB,MAAM;AAC1B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,kBAAkB;AAAA,MAClB,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,MAAO,MAAM,OAAO;AAC1B,QAAM,SAAS,IAAI;AACnB,QAAM,kBAAkB,OAAO,IAAI,oBAAoB,aAAa,IAAI,kBAAkB;AAG1F,MAAI,WAAW;AACf,MAAI,WAAW;AACf,QAAM,eAAe,6BAA6B,KAAK,KAAK,SAAS;AACrE,MAAI,cAAc;AAChB,UAAM,WAAW,KAAK,UAAU,QAAQ,aAAa,CAAC,CAAC,IAAI,aAAa,CAAC,EAAE;AAC3E,eAAW,KAAK,UAAU,MAAM,GAAG,QAAQ;AAC3C,eAAW,KAAK,UAAU,MAAM,QAAQ;AAAA,EAC1C;AAEA,SAAO,EAAE,SAAS,kBAAkB,QAAQ,iBAAiB,UAAU,SAAS;AAClF;;;AHlCA,eAAe,iBACb,KACA,KACA,KACkB;AAClB,QAAM,WAAW,IAAI,IAAI,KAAK,kBAAkB,EAAE;AAClD,QAAM,WAAW,MAAM,mBAAmB,UAAU,IAAI,kBAAkB,CAAC,CAAC;AAC5E,MAAI,aAAa,KAAM,QAAO;AAC9B,QAAM,UAAU,KAAK,UAAU,SAAS,IAAI;AAC5C,MAAI,UAAU,SAAS,QAAQ;AAAA,IAC7B,gBAAgB;AAAA,IAChB,kBAAkB,OAAO,WAAW,OAAO;AAAA,EAC7C,CAAC;AACD,MAAI,IAAI,OAAO;AACf,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAyC;AAClE,SAAO;AACT;AAEA,SAAS,iBAAiB,QAAmD;AAC3E,SAAO,WAAW,QAAQ,OAAO,WAAW,YAAY,cAAc;AACxE;AAEA,SAAS,aAAa,KAAqB,QAAsC;AAC/E,MAAI,UAAU,KAAK,EAAE,UAAU,OAAO,SAAS,QAAQ,IAAI,UAAU,KAAK,IAAI,CAAC;AAC/E,MAAI,IAAI;AACV;AAEA,SAAS,QAAQ,KAAqB,eAAoC;AACxE,MAAI,CAAC,IAAI,aAAa;AACpB,QAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAAA,EACpD;AACA,MAAI,CAAC,IAAI,eAAe;AACtB,QAAI,IAAI,iBAAiB,kCAA6B;AAAA,EACxD;AACF;AAEA,SAAS,aACP,KACA,QACA,OACQ;AACR,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,IAAI,WAAW,SAAS,IAAI;AAAA,EACrC;AACA,MAAI,kBAAkB,MAAM,GAAG;AAC7B,UAAM,WAAW,kBAAkB,MAAM;AACzC,UAAM,WAAW,KAAK,UAAU,SAAS,aAAa,EAAE,QAAQ,MAAM,SAAS;AAC/E,UAAM,kBAAkB,UACtB,QAAQ,WAAW,KAAK,MAAM,EAChC,uCAAuC,QAAQ;AAC/C,WAAO,IAAI,WAAW,SAAS,OAAO,kBAAkB,IAAI;AAAA,EAC9D;AACA,SAAO,IAAI,WAAW,IAAI;AAC5B;AAEA,eAAe,mBACb,KACA,KACA,KACA,KACA,OACkB;AAClB,MAAI,CAAC,IAAI,uBAAuB,CAAC,IAAI,mBAAoB,QAAO;AAEhE,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,MAAY;AAC1B,eAAW,MAAM;AAAA,EACnB;AACA,MAAI,GAAG,SAAS,OAAO;AACvB,MAAI;AACF,UAAM,SAAS,MAAM,IAAI,mBAAmB,KAAK,KAAK;AAAA,MACpD,QAAQ,WAAW;AAAA,MACnB;AAAA,IACF,CAAC;AACD,QAAI,iBAAiB,MAAM,EAAG,cAAa,KAAK,MAAM;AACtD,WAAO;AAAA,EACT,SAAS,WAAW;AAClB,YAAQ,MAAM,sBAAuB,UAAoB,OAAO;AAChE,YAAQ,KAAK,IAAI,aAAa;AAC9B,WAAO;AAAA,EACT,UAAE;AACA,QAAI,eAAe,SAAS,OAAO;AAAA,EACrC;AACF;AAEA,eAAe,cACb,KACA,KACA,KACA,OACkB;AAClB,MAAI,CAAC,IAAI,UAAW,QAAO;AAE3B,MAAI;AACF,UAAM,SAAS,MAAM,IAAI,UAAU,KAAK,EAAE,MAAM,CAAC;AACjD,QAAI,iBAAiB,MAAM,GAAG;AAC5B,mBAAa,KAAK,MAAM;AACxB,aAAO;AAAA,IACT;AACA,QAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,QAAI,IAAI,aAAa,KAAK,QAAQ,KAAK,CAAC;AACxC,WAAO;AAAA,EACT,SAAS,QAAQ;AACf,YAAQ,MAAM,oCAAqC,OAAiB,OAAO;AAC3E,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,KAA4B,KAAqB,KAAoB;AAC7F,MAAI,IAAI,iBAAiB,CAAC,IAAI,aAAa;AACzC,QAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,QAAI,IAAI,IAAI,aAAa;AAAA,EAC3B,WAAW,CAAC,IAAI,aAAa;AAC3B,cAAU,KAAK,kBAAmB,IAAc,SAAS,GAAG;AAAA,EAC9D,OAAO;AACL,QAAI,IAAI;AAAA,EACV;AACF;AAEO,SAAS,qBACd,KACqD;AACrD,SAAO,CAAC,KAAsB,QAAwB;AACpD,UAAM,YAAY;AAChB,YAAM,MAAM,IAAI,OAAO;AACvB,YAAM,YAAY,WAAW;AAC7B,YAAM,QAAQ,KAAK,IAAI;AAEvB,YAAM,QAAQ,cAAc;AAC5B,YAAM,kBAAkB;AAAA,QACtB,IAAI;AAAA,QACJ,EAAE,YAAY,KAAK;AAAA,QACnB,EAAE,MAAM;AAAA,MACV;AACA,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,eAAe,GAAG;AACpD,YAAI,UAAU,GAAG,CAAC;AAAA,MACpB;AAEA,YAAM,aAAa,IAAI,SAAS,KAAK,KAAK,WAAW,KAAK;AAE1D,UAAI;AACF,YAAI,MAAM,iBAAiB,KAAK,KAAK,GAAG,EAAG;AAC3C,YAAI,MAAM,eAAe,UAAU,EAAG;AACtC,YAAI,MAAM,iBAAiB,UAAU,EAAG;AACxC,YAAI,MAAM,cAAc,UAAU,EAAG;AACrC,YAAI,MAAM,iBAAiB,UAAU,EAAG;AACxC,YAAI,eAAe,UAAU,EAAG;AAChC,YAAI,kBAAkB,UAAU,EAAG;AAEnC,YAAI,MAAM,mBAAmB,KAAK,KAAK,KAAK,KAAK,KAAK,EAAG;AACzD,YAAI,MAAM,cAAc,KAAK,KAAK,KAAK,KAAK,EAAG;AAG/C,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI,IAAI,IAAI,SAAS;AAAA,MACvB,SAAS,KAAK;AACZ,yBAAiB,KAAK,KAAK,GAAG;AAAA,MAChC;AAAA,IACF,GAAG;AAAA,EACL;AACF;;;AI5MA,eAAsB,uBACpB,QACA,UACA,YACe;AACf,MAAI,SAAS,WAAW,EAAG;AAE3B,MAAI;AACJ,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,IAAI;AAClC,0BAAsB,SAAS;AAAA,EACjC,QAAQ;AACN,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AAEA,QAAM,MAAM,IAAI,oBAAoB,EAAE,UAAU,KAAK,CAAC;AAEtD,SAAO,GAAG,WAAW,CAAC,SAAS,QAAQ,SAAS;AAC9C,UAAM,YAAY;AAChB,YAAM,MAAM,QAAQ,OAAO;AAC3B,UAAI,CAAC,IAAI,WAAW,MAAM,GAAG;AAC3B,eAAO,QAAQ;AACf;AAAA,MACF;AAEA,YAAM,SAAS,IAAI,MAAM,GAAG,EAAE,CAAC;AAC/B,YAAM,QAAQ,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AACtD,UAAI,CAAC,OAAO;AACV,eAAO,QAAQ;AACf;AAAA,MACF;AAEA,UAAI;AACF,cAAM,MAAM,MAAM,WAAW,MAAM,QAAQ;AAC3C,cAAM,UAAY,IAA8B,WAAW;AAE3D,YAAI,cAAc,SAAS,QAAQ,MAAM,CAAC,OAAO;AAC/C,kBAAQ,SAAS,IAAI,OAAO;AAC5B,aAAG,GAAG,WAAW,CAAC,SAAiB;AACjC,oBAAQ,YAAY,IAAI,KAAK,SAAS,CAAC;AAAA,UACzC,CAAC;AACD,aAAG,GAAG,SAAS,CAAC,MAAc,WAAmB;AAC/C,oBAAQ,UAAU,IAAI,MAAM,MAAM;AAAA,UACpC,CAAC;AACD,aAAG,GAAG,SAAS,CAAC,QAAe;AAC7B,oBAAQ,UAAU,IAAI,GAAG;AAAA,UAC3B,CAAC;AAAA,QACH,CAAC;AAAA,MACH,QAAQ;AACN,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF,GAAG;AAAA,EACL,CAAC;AACH;;;AXvBA,eAAsB,aAAa,SAAsC;AACvE,QAAM,MAAM,QAAQ,IAAI;AAExB,2BAAyB,GAAG;AAC5B,UAAQ,EAAE,KAAK,MAAM,aAAa,CAAC;AACnC,QAAM,SAAS,MAAM,WAAW,GAAG;AAInC,sBAAoB;AAEpB,QAAM,iCAAiC,OAAO,QAAQ,QAAQ;AAC9D,QAAM,kCAAkC,OAAO,OAAO;AAEtD,QAAM,UAAUC,SAAQ,KAAK,UAAU;AACvC,QAAM,YAAYA,SAAQ,SAAS,QAAQ;AAO3C,QAAM,qBAAqBC,YAAWD,SAAQ,SAAS,wBAAwB,CAAC,IAC5EA,SAAQ,SAAS,aAAa,IAC9B;AAEJ,QAAM,YAAYA,SAAQ,KAAK,OAAO,SAAS;AAE/C,MAAI,CAACC,YAAW,SAAS,GAAG;AAC1B,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,QAAM,YAAYC,cAAaC,MAAK,WAAW,YAAY,GAAG,OAAO;AACrE,QAAM,aAAa,uBAAuB;AAC1C,QAAM,OAAO,QAAQ,QAAQ,OAAO;AACpC,QAAM,eAAe,MAAM,6BAA6B,OAAO,OAAO;AACtE,QAAM,cAAc,mBAAmB,OAAO,aAAa;AAE3D,QAAM,gBAAgBA,MAAK,WAAW,UAAU;AAChD,QAAM,gBAAgBA,MAAK,WAAW,UAAU;AAChD,QAAM,gBAAgBF,YAAW,aAAa,IAAIC,cAAa,eAAe,OAAO,IAAI;AACzF,QAAM,gBAAgBD,YAAW,aAAa,IAAIC,cAAa,eAAe,OAAO,IAAI;AAEzF,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,EACV,IAAI,qBAAqB,SAAS,WAAW,OAAO,SAAS;AAI7D,QAAM,gBACJ,OAAO,aAAa,cAAc,OAAO,aAAa,SAAS,OAAO,YAClE,OAAO,YACP;AACN,QAAM,cAAc,gBAAgB,kBAAkB,aAAa,IAAI;AAEvE,QAAM,MAAM,MAAM,SAAS;AAAA,IACzB;AAAA,IACA;AAAA,IACA,kBAAkB,OAAO;AAAA,IACzB,oBAAoB,OAAO;AAAA,EAC7B,CAAC;AAED,QAAM,SAAS;AAAA,IACb,qBAAqB;AAAA,MACnB,UAAU,CAAC,KAAK,KAAK,WAAW,eAAkC;AAAA,QAChE;AAAA,QACA;AAAA,QACA,KAAK,IAAI,OAAO;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU,OAAO,UAAU,QAAQ;AAAA,QACnC,YAAY,OAAO,UAAU;AAAA,QAC7B;AAAA,MACF;AAAA,MACA,uBAAuB,OAAO,UAAU,WAAW,CAAC;AAAA,MACpD,WAAW,IAAI;AAAA,MACf,oBAAoB,IAAI;AAAA,MACxB,qBAAqB,IAAI;AAAA,MACzB,UAAU,IAAI;AAAA,MACd,UAAU,IAAI;AAAA,MACd;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,MAIA,gBAAgB,EAAE,QAAQ,kBAAkB,EAAE;AAAA,IAChD,CAAC;AAAA,EACH;AAEA,QAAM,uBAAuB,QAAQ,gBAAgB,UAAU;AAE/D,SAAO,OAAO,MAAM,MAAM;AACxB,YAAQ,IAAI;AAAA,yBAA4B;AACxC,YAAQ,IAAI,6BAAwB,OAAO,IAAI,CAAC;AAAA,CAAI;AAAA,EACtD,CAAC;AAED,0BAAwB,MAAM;AAChC;","names":["existsSync","readFileSync","join","resolve","require","existsSync","existsSync","extname","existsSync","readFileSync","resolve","method","extname","resolve","existsSync","readFileSync","join"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/storage/storage-manager.ts"],"sourcesContent":["/**\n * StorageManager — per-process singleton coordinating pluggable storage\n * adapters (Postgres pools, Redis clients, in-memory adapters).\n *\n * Architectural decisions: see ADR-0007 (docs/adr/0007-storage-manager-singleton.md).\n *\n * Lifecycle:\n * 1. `getStorageManager()` returns the singleton (D1).\n * 2. `configure(storageConfig)` honored once per process (D3). Second call\n * warns and is ignored.\n * 3. `usePostgres(dbName, factory)` / `useRedis(serverName, factory)`\n * lazily create + cache (D2). Factory invoked exactly once per name.\n * 4. `register(adapter)` opts the adapter into the SIGTERM drain (D6).\n * 5. `dispose()` drains in parallel — adapters + pools + Redis (D5).\n * Idempotent. Adapter errors logged + swallowed (do not block shutdown).\n *\n * Test seam: `__resetForTests()` resets state. Test files MUST call it from\n * `beforeEach` to avoid pollution across `it` blocks (EC-3).\n */\n\nimport type {\n PoolLike,\n PostgresDatabaseConfig,\n RedisLike,\n RedisServerConfig,\n ServerConfig,\n StorageAdapter,\n StorageConfig,\n} from './storage-types.js'\n\nexport type PostgresFactory = (server: ServerConfig, db: PostgresDatabaseConfig) => PoolLike\nexport type RedisFactory = (config: RedisServerConfig) => RedisLike\n\nexport class StorageManager {\n #config: StorageConfig | undefined\n readonly #dbPools = new Map<string, PoolLike>()\n readonly #redisClients = new Map<string, RedisLike>()\n readonly #genericClients = new Map<string, unknown>()\n readonly #adapters = new Set<StorageAdapter>()\n #disposed = false\n\n /**\n * Apply the storage config block from `theo.config.ts`. Second call warns\n * and is ignored (D3). Reset only via `__resetForTests()`.\n */\n configure(config: StorageConfig): void {\n if (this.#config !== undefined) {\n console.warn('[theokit] StorageManager already configured; ignoring second configure() call')\n return\n }\n this.#config = config\n }\n\n /**\n * Generic cache + factory for ANY client (MySQL, Mongo, Turso, DynamoDB, …).\n * Returns the cached client OR invokes the factory and caches its return.\n *\n * EC-1 FIX: cache-hit check uses `Map.has(name)`, NOT `cached !== undefined`.\n * Factories returning `null` or `undefined` are valid (lazy connect, stubs);\n * the `!== undefined` check would re-invoke the factory infinitely for\n * undefined returns AND silently cache `null` cast as `T`.\n *\n * EC-2 (documented type hole): `useStorage<A>('x', fA)` followed by\n * `useStorage<B>('x', fB)` returns the cached A cast as B. Same trade-off\n * as `Map<string, unknown>` — caller is responsible for using unique names\n * per type.\n *\n * Lifecycle: generic clients are NOT auto-drained by `dispose()`. Call\n * `manager.register({ name, dispose })` separately to participate.\n *\n * Reserved name prefixes (do NOT use): `__pg:`, `__redis:`, `__unstorage:`,\n * `__db0:` — these are used internally by the typed helpers.\n */\n useStorage<T>(name: string, factory: () => T): T {\n if (this.#disposed) throw new Error('StorageManager is disposed')\n if (this.#genericClients.has(name)) return this.#genericClients.get(name) as T\n const client = factory()\n this.#genericClients.set(name, client)\n return client\n }\n\n /**\n * Return a Postgres pool for the named database. Lazy + cached. Factory\n * invoked exactly once per `dbName` (D2).\n *\n * Throws if:\n * - manager is disposed\n * - `dbName` is not in `config.databases`\n * - the referenced server is not in `config.servers` (EC-2: deferred\n * cross-field validation surfaces here, not at configure time)\n */\n usePostgres(dbName: string, factory: PostgresFactory): PoolLike {\n if (this.#disposed) throw new Error('StorageManager is disposed')\n const cached = this.#dbPools.get(dbName)\n if (cached !== undefined) return cached\n const dbConfig = this.#config?.databases?.[dbName]\n if (dbConfig === undefined) {\n throw new Error(\n `Database \"${dbName}\" not configured. Add it to theo.config.ts > storage.databases.`,\n )\n }\n const server = this.#config?.servers?.[dbConfig.server]\n if (server === undefined) {\n throw new Error(\n `Server \"${dbConfig.server}\" referenced by database \"${dbName}\" not found in theo.config.ts > storage.servers.`,\n )\n }\n const pool = factory(server, dbConfig)\n this.#dbPools.set(dbName, pool)\n return pool\n }\n\n /**\n * Return a Redis client for the named server. Lazy + cached. Factory\n * invoked exactly once per `serverName`.\n */\n useRedis(serverName: string, factory: RedisFactory): RedisLike {\n if (this.#disposed) throw new Error('StorageManager is disposed')\n const cached = this.#redisClients.get(serverName)\n if (cached !== undefined) return cached\n const serverConfig = this.#config?.redis?.[serverName]\n if (serverConfig === undefined) {\n throw new Error(\n `Redis server \"${serverName}\" not configured. Add it to theo.config.ts > storage.redis.`,\n )\n }\n const client = factory(serverConfig)\n this.#redisClients.set(serverName, client)\n return client\n }\n\n /**\n * Register an adapter for graceful shutdown coordination (D6).\n *\n * EC-4: throws if the manager is already disposed — prevents silent\n * leaks in test seams that reset+reuse the manager.\n */\n register(adapter: StorageAdapter): void {\n if (this.#disposed) {\n throw new Error(\n 'StorageManager is disposed; cannot register new adapter. Call __resetForTests() in test setup.',\n )\n }\n this.#adapters.add(adapter)\n }\n\n /**\n * Drain in parallel — registered adapters, then PG pools, then Redis\n * clients. Idempotent (D5). Errors per resource are logged and swallowed\n * — they do NOT prevent shutdown of the remaining resources.\n *\n * Caller must wrap in a timeout if a bound is needed (EC-7: documented).\n * In production, `start.ts` wraps the whole shutdown sequence in a 25 s\n * force-exit timer.\n */\n async dispose(): Promise<void> {\n if (this.#disposed) return\n this.#disposed = true\n\n const adapterDrains = Array.from(this.#adapters).map((a) =>\n a.dispose().catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`[theokit] adapter \"${a.name}\" dispose failed: ${msg}`)\n }),\n )\n await Promise.all(adapterDrains)\n\n const poolCloses = Array.from(this.#dbPools.values()).map((pool) => {\n // EC-5: pool without `.end()` is silently skipped (TS already enforces\n // shape at factory signature; this is the graceful runtime fallback if\n // user bypasses via `as` cast).\n if (pool.end === undefined) return Promise.resolve()\n return pool.end().catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`[theokit] PG pool close failed: ${msg}`)\n })\n })\n await Promise.all(poolCloses)\n\n const redisCloses = Array.from(this.#redisClients.values()).map((c) =>\n c.quit().catch((err: unknown) => {\n const msg = err instanceof Error ? err.message : String(err)\n console.warn(`[theokit] Redis quit failed, falling back to disconnect: ${msg}`)\n c.disconnect()\n }),\n )\n await Promise.all(redisCloses)\n\n this.#dbPools.clear()\n this.#redisClients.clear()\n this.#genericClients.clear()\n this.#adapters.clear()\n }\n\n /** @internal Testing seam — resets state so a single test file can re-use the singleton across `it` blocks (EC-3). */\n __resetForTests(): void {\n this.#config = undefined\n this.#dbPools.clear()\n this.#redisClients.clear()\n this.#genericClients.clear()\n this.#adapters.clear()\n this.#disposed = false\n }\n\n /** @internal Introspection helper for tests. */\n __isConfiguredForTests(): boolean {\n return this.#config !== undefined\n }\n\n /** @internal Introspection helper for tests. */\n __isDisposedForTests(): boolean {\n return this.#disposed\n }\n}\n\n// Singleton — one StorageManager per process (D1).\nlet __singleton: StorageManager | undefined\n\nexport function getStorageManager(): StorageManager {\n __singleton ??= new StorageManager()\n return __singleton\n}\n\n/** @internal Drops the module-level singleton — used by tests that need a fresh manager. */\nexport function __resetSingletonForTests(): void {\n __singleton = undefined\n}\n"],"mappings":"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","names":[]}