theokit 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{actions-virtual-module-3CDQTWOC.js → actions-virtual-module-G4BANOLW.js} +5 -3
  2. package/dist/{actions-virtual-module-3CDQTWOC.js.map → actions-virtual-module-G4BANOLW.js.map} +1 -1
  3. package/dist/agent-MN7XGJR3.js +209 -0
  4. package/dist/agent-MN7XGJR3.js.map +1 -0
  5. package/dist/{app-typed-client-CSOK7NPC.js → app-typed-client-Z6BHD4MF.js} +5 -3
  6. package/dist/{app-typed-client-CSOK7NPC.js.map → app-typed-client-Z6BHD4MF.js.map} +1 -1
  7. package/dist/{build-5K7LK77K.js → build-QDAFSKKW.js} +11 -7
  8. package/dist/{build-5K7LK77K.js.map → build-QDAFSKKW.js.map} +1 -1
  9. package/dist/chunk-34YQOXGM.js +37 -0
  10. package/dist/chunk-34YQOXGM.js.map +1 -0
  11. package/dist/{chunk-7YZHAQU7.js → chunk-567NA7Y6.js} +8 -99
  12. package/dist/chunk-567NA7Y6.js.map +1 -0
  13. package/dist/{chunk-BQDGES7C.js → chunk-GBXLKYIA.js} +19 -43
  14. package/dist/chunk-GBXLKYIA.js.map +1 -0
  15. package/dist/chunk-GDN3PXFH.js +101 -0
  16. package/dist/chunk-GDN3PXFH.js.map +1 -0
  17. package/dist/chunk-NBWB4S46.js +81 -0
  18. package/dist/chunk-NBWB4S46.js.map +1 -0
  19. package/dist/{chunk-F4YUPDJ2.js → chunk-NXTF5PPW.js} +15 -41
  20. package/dist/chunk-NXTF5PPW.js.map +1 -0
  21. package/dist/{chunk-S7Y5WLZY.js → chunk-OTFIRP6S.js} +76 -46
  22. package/dist/chunk-OTFIRP6S.js.map +1 -0
  23. package/dist/chunk-P37RZRFV.js +31 -0
  24. package/dist/chunk-P37RZRFV.js.map +1 -0
  25. package/dist/{chunk-RBHCJHRR.js → chunk-UOR6JTCI.js} +142 -7
  26. package/dist/chunk-UOR6JTCI.js.map +1 -0
  27. package/dist/{chunk-637WJB7Z.js → chunk-ZJDKAD3L.js} +55 -14
  28. package/dist/chunk-ZJDKAD3L.js.map +1 -0
  29. package/dist/cli/index.js +22 -6
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/{dev-QOEVYNBG.js → dev-TEE4T6ZB.js} +13 -8
  32. package/dist/{dev-QOEVYNBG.js.map → dev-TEE4T6ZB.js.map} +1 -1
  33. package/dist/{dev-emit-5MDSBP5D.js → dev-emit-VJ5CFMPY.js} +5 -3
  34. package/dist/{dev-emit-5MDSBP5D.js.map → dev-emit-VJ5CFMPY.js.map} +1 -1
  35. package/dist/index.js +1 -1
  36. package/dist/{info-OUEUZOT7.js → info-7PE2PZJI.js} +6 -5
  37. package/dist/{info-OUEUZOT7.js.map → info-7PE2PZJI.js.map} +1 -1
  38. package/dist/{internal-api-EFKZWIYZ.js → internal-api-J27TYE2I.js} +7 -4
  39. package/dist/load-config-JKYO5RFK.js +14 -0
  40. package/dist/{openapi-FHY6HC6I.js → openapi-MXMLZCXC.js} +7 -4
  41. package/dist/{openapi-FHY6HC6I.js.map → openapi-MXMLZCXC.js.map} +1 -1
  42. package/dist/{registry-34LL7NF4.js → registry-XJUYD2OU.js} +2 -2
  43. package/dist/{routes-EW7TP7NJ.js → routes-NNBEZSGN.js} +5 -3
  44. package/dist/{routes-EW7TP7NJ.js.map → routes-NNBEZSGN.js.map} +1 -1
  45. package/dist/{start-2KG4JSXM.js → start-7MQEEQH4.js} +68 -8
  46. package/dist/start-7MQEEQH4.js.map +1 -0
  47. package/dist/{static-55G3LX2I.js → static-7ARBVDJF.js} +4 -4
  48. package/dist/vite-plugin/index.js +1 -1
  49. package/dist/{vite-plugin-TDIDZ5U7.js → vite-plugin-GC6WCU4P.js} +11 -7
  50. package/dist/vite-plugin-GC6WCU4P.js.map +1 -0
  51. package/package.json +2 -2
  52. package/dist/chunk-637WJB7Z.js.map +0 -1
  53. package/dist/chunk-7YZHAQU7.js.map +0 -1
  54. package/dist/chunk-BQDGES7C.js.map +0 -1
  55. package/dist/chunk-F4YUPDJ2.js.map +0 -1
  56. package/dist/chunk-RBHCJHRR.js.map +0 -1
  57. package/dist/chunk-S7Y5WLZY.js.map +0 -1
  58. package/dist/start-2KG4JSXM.js.map +0 -1
  59. /package/dist/{internal-api-EFKZWIYZ.js.map → internal-api-J27TYE2I.js.map} +0 -0
  60. /package/dist/{vite-plugin-TDIDZ5U7.js.map → load-config-JKYO5RFK.js.map} +0 -0
  61. /package/dist/{registry-34LL7NF4.js.map → registry-XJUYD2OU.js.map} +0 -0
  62. /package/dist/{static-55G3LX2I.js.map → static-7ARBVDJF.js.map} +0 -0
package/dist/cli/index.js CHANGED
@@ -5,12 +5,12 @@ import "tsx/esm";
5
5
  import cac from "cac";
6
6
  var cli = cac("theokit");
7
7
  cli.command("dev", "Start development server").option("--port <port>", "Port number").action(async (options) => {
8
- const { devCommand } = await import("../dev-QOEVYNBG.js");
8
+ const { devCommand } = await import("../dev-TEE4T6ZB.js");
9
9
  await devCommand({ port: options.port ? Number(options.port) : void 0 });
10
10
  });
11
11
  cli.command("build", "Build for production").option("--target <target>", "Deploy target (node, vercel, cloudflare)").action(async (options) => {
12
12
  try {
13
- const { buildCommand } = await import("../build-5K7LK77K.js");
13
+ const { buildCommand } = await import("../build-QDAFSKKW.js");
14
14
  await buildCommand({ target: options.target });
15
15
  } catch (err) {
16
16
  const msg = err instanceof Error ? err.message : String(err);
@@ -22,7 +22,7 @@ cli.command("build", "Build for production").option("--target <target>", "Deploy
22
22
  });
23
23
  cli.command("start", "Start production server").option("--port <port>", "Port number").action(async (options) => {
24
24
  try {
25
- const { startCommand } = await import("../start-2KG4JSXM.js");
25
+ const { startCommand } = await import("../start-7MQEEQH4.js");
26
26
  await startCommand({ port: options.port ? Number(options.port) : void 0 });
27
27
  } catch (err) {
28
28
  const msg = err instanceof Error ? err.message : String(err);
@@ -47,9 +47,25 @@ cli.command(
47
47
  process.exit(1);
48
48
  }
49
49
  });
50
+ cli.command(
51
+ "agent <name> [message]",
52
+ "Run an agent in the terminal (stream + tool calls + approval)"
53
+ ).action(async (name, message) => {
54
+ try {
55
+ const { agentCommand } = await import("../agent-MN7XGJR3.js");
56
+ const { sawError } = await agentCommand(name, message);
57
+ if (sawError) process.exit(1);
58
+ } catch (err) {
59
+ const msg = err instanceof Error ? err.message : String(err);
60
+ console.error(`
61
+ \u2717 ${msg}
62
+ `);
63
+ process.exit(1);
64
+ }
65
+ });
50
66
  cli.command("routes", "List all routes, actions, and WebSocket endpoints").action(async () => {
51
67
  try {
52
- const { routesCommand } = await import("../routes-EW7TP7NJ.js");
68
+ const { routesCommand } = await import("../routes-NNBEZSGN.js");
53
69
  await routesCommand();
54
70
  } catch (err) {
55
71
  const msg = err instanceof Error ? err.message : String(err);
@@ -90,7 +106,7 @@ cli.command("add <package>", "Install a known TheoKit adapter or plugin (whiteli
90
106
  await addCommand(pkg);
91
107
  });
92
108
  cli.command("info", "Print environment info (runtime, config, routes)").action(async () => {
93
- const { infoCommand } = await import("../info-OUEUZOT7.js");
109
+ const { infoCommand } = await import("../info-7PE2PZJI.js");
94
110
  await infoCommand();
95
111
  });
96
112
  cli.command(
@@ -98,7 +114,7 @@ cli.command(
98
114
  "Generate <distDir>/openapi.json from route schemas (opt-in via config.openapi)"
99
115
  ).option("--dry-run", "Print the document to stdout without writing to disk (EC-3)").action(async (options) => {
100
116
  try {
101
- const { openapiCommand } = await import("../openapi-FHY6HC6I.js");
117
+ const { openapiCommand } = await import("../openapi-MXMLZCXC.js");
102
118
  await openapiCommand({ dryRun: Boolean(options.dryRun) });
103
119
  } catch (err) {
104
120
  const msg = err instanceof Error ? err.message : String(err);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["import cac from 'cac'\n\ninterface CliOptions {\n port?: string | number\n target?: string\n upgradeReadiness?: string | number\n json?: boolean\n allowWarnings?: boolean\n force?: boolean\n dryRun?: boolean\n}\n\nconst cli = cac('theokit')\n\ncli\n .command('dev', 'Start development server')\n .option('--port <port>', 'Port number')\n .action(async (options: CliOptions) => {\n const { devCommand } = await import('./commands/dev.js')\n await devCommand({ port: options.port ? Number(options.port) : undefined })\n })\n\ncli\n .command('build', 'Build for production')\n .option('--target <target>', 'Deploy target (node, vercel, cloudflare)')\n .action(async (options: CliOptions) => {\n try {\n const { buildCommand } = await import('./commands/build.js')\n await buildCommand({ target: options.target })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('start', 'Start production server')\n .option('--port <port>', 'Port number')\n .action(async (options: CliOptions) => {\n try {\n const { startCommand } = await import('./commands/start/index.js')\n await startCommand({ port: options.port ? Number(options.port) : undefined })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command(\n 'generate <type> <name> [...fields]',\n 'Generate a route, action, page, ws, controller, or resource (resource accepts field:type args)',\n )\n .action(async (type: string, name: string, fields: string[]) => {\n try {\n const { generateCommand } = await import('./commands/generate.js')\n await generateCommand(type, name, fields.length > 0 ? fields : undefined)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli.command('routes', 'List all routes, actions, and WebSocket endpoints').action(async () => {\n try {\n const { routesCommand } = await import('./commands/routes.js')\n await routesCommand()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n})\n\ncli\n .command('check', 'Run typecheck + scan + (optional) eslint')\n .option(\n '--upgrade-readiness <version>',\n 'Scan source for anticipated breakage under a future TheoKit version (currently supports 0.3). See docs/migration/0.2-to-0.3.md',\n )\n .option('--json', 'Emit machine-readable JSON (only with --upgrade-readiness)')\n .option(\n '--allow-warnings',\n 'Do not fail the build when violations are present (only with --upgrade-readiness)',\n )\n .action(async (options: CliOptions) => {\n // cac may coerce `0.3` to a JS number — normalize before comparing.\n const targetRaw = options.upgradeReadiness\n if (targetRaw !== undefined) {\n const target = String(targetRaw)\n if (target !== '0.3') {\n console.error(`\\n ✗ --upgrade-readiness: only '0.3' is supported (got '${target}')\\n`)\n process.exit(1)\n }\n const { upgradeReadinessCommand } = await import('./commands/upgrade-readiness.js')\n await upgradeReadinessCommand({\n json: Boolean(options.json),\n allowWarnings: Boolean(options.allowWarnings),\n })\n return\n }\n const { checkCommand } = await import('./commands/check.js')\n await checkCommand()\n })\n\ncli\n .command('add <package>', 'Install a known TheoKit adapter or plugin (whitelist-only)')\n .action(async (pkg: string) => {\n const { addCommand } = await import('./commands/add.js')\n await addCommand(pkg)\n })\n\ncli.command('info', 'Print environment info (runtime, config, routes)').action(async () => {\n const { infoCommand } = await import('./commands/info.js')\n await infoCommand()\n})\n\ncli\n .command(\n 'openapi',\n 'Generate <distDir>/openapi.json from route schemas (opt-in via config.openapi)',\n )\n .option('--dry-run', 'Print the document to stdout without writing to disk (EC-3)')\n .action(async (options: CliOptions) => {\n try {\n const { openapiCommand } = await import('./commands/openapi.js')\n await openapiCommand({ dryRun: Boolean(options.dryRun) })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command(\n 'migrate <kind>',\n 'Run a one-shot convention migration. Supported: router (G6 dotted→nested), services-json-v1-to-v2 (Plan v1.2 T2.3)',\n )\n .option('--dry-run', 'Print the migration plan but do not touch the filesystem')\n .option('--force', 'Skip the dev-server port pre-flight check (CI / non-TTY)')\n .option('--name <slug>', 'Explicit project name (DNS-1123). Services-json migrate only.')\n .action(async (kind: string, options: CliOptions & { name?: string }) => {\n try {\n if (kind === 'router') {\n const { routerMigrateCommand } = await import('./commands/migrate/router.js')\n await routerMigrateCommand({\n dryRun: Boolean(options.dryRun),\n force: Boolean(options.force),\n })\n return\n }\n if (kind === 'services-json-v1-to-v2' || kind === 'services-json') {\n const { servicesJsonMigrateCommand } = await import('./commands/migrate/services-json.js')\n await servicesJsonMigrateCommand({\n dryRun: Boolean(options.dryRun),\n name: options.name,\n })\n return\n }\n console.error(\n `\\n ✗ Unknown migration kind: ${kind}. Supported: router, services-json-v1-to-v2\\n`,\n )\n process.exit(1)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('docker', 'Generate Dockerfile for production')\n .option('--force', 'Overwrite existing Dockerfile')\n .action(async (options: CliOptions) => {\n try {\n const { dockerCommand } = await import('./commands/docker.js')\n await dockerCommand({ force: options.force })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('db <action>', 'Database commands: migrate (push schema), generate (SQL files), seed')\n .action(async (action: string) => {\n try {\n const { dbCommandCli } = await import('./commands/db.js')\n dbCommandCli(action)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli.help()\ncli.version('0.1.0-alpha.0')\n\nexport function main(): void {\n cli.parse()\n}\n\n// Auto-execute when run as script\nmain()\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["import cac from 'cac'\n\ninterface CliOptions {\n port?: string | number\n target?: string\n upgradeReadiness?: string | number\n json?: boolean\n allowWarnings?: boolean\n force?: boolean\n dryRun?: boolean\n}\n\nconst cli = cac('theokit')\n\ncli\n .command('dev', 'Start development server')\n .option('--port <port>', 'Port number')\n .action(async (options: CliOptions) => {\n const { devCommand } = await import('./commands/dev.js')\n await devCommand({ port: options.port ? Number(options.port) : undefined })\n })\n\ncli\n .command('build', 'Build for production')\n .option('--target <target>', 'Deploy target (node, vercel, cloudflare)')\n .action(async (options: CliOptions) => {\n try {\n const { buildCommand } = await import('./commands/build.js')\n await buildCommand({ target: options.target })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('start', 'Start production server')\n .option('--port <port>', 'Port number')\n .action(async (options: CliOptions) => {\n try {\n const { startCommand } = await import('./commands/start/index.js')\n await startCommand({ port: options.port ? Number(options.port) : undefined })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command(\n 'generate <type> <name> [...fields]',\n 'Generate a route, action, page, ws, controller, or resource (resource accepts field:type args)',\n )\n .action(async (type: string, name: string, fields: string[]) => {\n try {\n const { generateCommand } = await import('./commands/generate.js')\n await generateCommand(type, name, fields.length > 0 ? fields : undefined)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command(\n 'agent <name> [message]',\n 'Run an agent in the terminal (stream + tool calls + approval)',\n )\n .action(async (name: string, message: string | undefined) => {\n try {\n const { agentCommand } = await import('./commands/agent.js')\n const { sawError } = await agentCommand(name, message)\n // The run ended with an error chunk (already rendered) — exit non-zero so `$?` / CI reflects it.\n if (sawError) process.exit(1)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli.command('routes', 'List all routes, actions, and WebSocket endpoints').action(async () => {\n try {\n const { routesCommand } = await import('./commands/routes.js')\n await routesCommand()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n})\n\ncli\n .command('check', 'Run typecheck + scan + (optional) eslint')\n .option(\n '--upgrade-readiness <version>',\n 'Scan source for anticipated breakage under a future TheoKit version (currently supports 0.3). See docs/migration/0.2-to-0.3.md',\n )\n .option('--json', 'Emit machine-readable JSON (only with --upgrade-readiness)')\n .option(\n '--allow-warnings',\n 'Do not fail the build when violations are present (only with --upgrade-readiness)',\n )\n .action(async (options: CliOptions) => {\n // cac may coerce `0.3` to a JS number — normalize before comparing.\n const targetRaw = options.upgradeReadiness\n if (targetRaw !== undefined) {\n const target = String(targetRaw)\n if (target !== '0.3') {\n console.error(`\\n ✗ --upgrade-readiness: only '0.3' is supported (got '${target}')\\n`)\n process.exit(1)\n }\n const { upgradeReadinessCommand } = await import('./commands/upgrade-readiness.js')\n await upgradeReadinessCommand({\n json: Boolean(options.json),\n allowWarnings: Boolean(options.allowWarnings),\n })\n return\n }\n const { checkCommand } = await import('./commands/check.js')\n await checkCommand()\n })\n\ncli\n .command('add <package>', 'Install a known TheoKit adapter or plugin (whitelist-only)')\n .action(async (pkg: string) => {\n const { addCommand } = await import('./commands/add.js')\n await addCommand(pkg)\n })\n\ncli.command('info', 'Print environment info (runtime, config, routes)').action(async () => {\n const { infoCommand } = await import('./commands/info.js')\n await infoCommand()\n})\n\ncli\n .command(\n 'openapi',\n 'Generate <distDir>/openapi.json from route schemas (opt-in via config.openapi)',\n )\n .option('--dry-run', 'Print the document to stdout without writing to disk (EC-3)')\n .action(async (options: CliOptions) => {\n try {\n const { openapiCommand } = await import('./commands/openapi.js')\n await openapiCommand({ dryRun: Boolean(options.dryRun) })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command(\n 'migrate <kind>',\n 'Run a one-shot convention migration. Supported: router (G6 dotted→nested), services-json-v1-to-v2 (Plan v1.2 T2.3)',\n )\n .option('--dry-run', 'Print the migration plan but do not touch the filesystem')\n .option('--force', 'Skip the dev-server port pre-flight check (CI / non-TTY)')\n .option('--name <slug>', 'Explicit project name (DNS-1123). Services-json migrate only.')\n .action(async (kind: string, options: CliOptions & { name?: string }) => {\n try {\n if (kind === 'router') {\n const { routerMigrateCommand } = await import('./commands/migrate/router.js')\n await routerMigrateCommand({\n dryRun: Boolean(options.dryRun),\n force: Boolean(options.force),\n })\n return\n }\n if (kind === 'services-json-v1-to-v2' || kind === 'services-json') {\n const { servicesJsonMigrateCommand } = await import('./commands/migrate/services-json.js')\n await servicesJsonMigrateCommand({\n dryRun: Boolean(options.dryRun),\n name: options.name,\n })\n return\n }\n console.error(\n `\\n ✗ Unknown migration kind: ${kind}. Supported: router, services-json-v1-to-v2\\n`,\n )\n process.exit(1)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('docker', 'Generate Dockerfile for production')\n .option('--force', 'Overwrite existing Dockerfile')\n .action(async (options: CliOptions) => {\n try {\n const { dockerCommand } = await import('./commands/docker.js')\n await dockerCommand({ force: options.force })\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli\n .command('db <action>', 'Database commands: migrate (push schema), generate (SQL files), seed')\n .action(async (action: string) => {\n try {\n const { dbCommandCli } = await import('./commands/db.js')\n dbCommandCli(action)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n })\n\ncli.help()\ncli.version('0.1.0-alpha.0')\n\nexport function main(): void {\n cli.parse()\n}\n\n// Auto-execute when run as script\nmain()\n"],"mappings":"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","names":[]}
@@ -8,12 +8,16 @@ import {
8
8
  } from "./chunk-HNBWZKIQ.js";
9
9
  import {
10
10
  theoPluginAsync
11
- } from "./chunk-637WJB7Z.js";
12
- import "./chunk-S7Y5WLZY.js";
11
+ } from "./chunk-ZJDKAD3L.js";
12
+ import "./chunk-OTFIRP6S.js";
13
+ import "./chunk-NBWB4S46.js";
14
+ import "./chunk-IEES3CHD.js";
15
+ import {
16
+ loadConfig
17
+ } from "./chunk-567NA7Y6.js";
13
18
  import {
14
- loadConfig,
15
19
  loadEnv
16
- } from "./chunk-7YZHAQU7.js";
20
+ } from "./chunk-GDN3PXFH.js";
17
21
  import "./chunk-YJAUJXZS.js";
18
22
  import {
19
23
  orchestrateDev
@@ -21,10 +25,11 @@ import {
21
25
  import "./chunk-5ODOE6EF.js";
22
26
  import "./chunk-KXA37ONC.js";
23
27
  import "./chunk-WR4F4EEZ.js";
24
- import "./chunk-F4YUPDJ2.js";
25
- import "./chunk-BQDGES7C.js";
28
+ import "./chunk-NXTF5PPW.js";
29
+ import "./chunk-34YQOXGM.js";
30
+ import "./chunk-GBXLKYIA.js";
31
+ import "./chunk-P37RZRFV.js";
26
32
  import "./chunk-HGZL5EOI.js";
27
- import "./chunk-IEES3CHD.js";
28
33
 
29
34
  // src/cli/commands/dev.ts
30
35
  import react from "@vitejs/plugin-react";
@@ -99,4 +104,4 @@ export {
99
104
  devCommand,
100
105
  startDevServer
101
106
  };
102
- //# sourceMappingURL=dev-QOEVYNBG.js.map
107
+ //# sourceMappingURL=dev-TEE4T6ZB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/dev.ts"],"sourcesContent":["import react from '@vitejs/plugin-react'\nimport { createServer, type Plugin, type ViteDevServer } from 'vite'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { loadEnv } from '../../config/load-env.js'\nimport { validateProjectStructure } from '../../config/validate-structure.js'\nimport { orchestrateDev } from '../../services/index.js'\nimport { theoPluginAsync } from '../../vite-plugin/index.js'\nimport { preflightNodeAndBindings } from '../preflight-node-version.js'\n\ninterface DevOptions {\n port?: number\n}\n\nexport async function startDevServer(cwd: string, options?: DevOptions): Promise<ViteDevServer> {\n // Preflight (FIRST — BEFORE anything that touches native bindings):\n // verifies Node version + native binding ABI match. Emits actionable\n // error referencing `nvm use` + `pnpm rebuild` when the dev server\n // was spawned under the wrong Node (common gotcha with `nohup env ...`\n // stripping the nvm PATH prefix).\n preflightNodeAndBindings(cwd)\n\n // Phase 1 (T1.2) — Load .env files into process.env BEFORE any module\n // reads them. Must run before loadConfig() so theo.config.ts functions\n // referencing process.env.* resolve correctly.\n loadEnv({ cwd, mode: 'development' })\n\n const config = await loadConfig(cwd)\n validateProjectStructure(cwd)\n\n // Wave 2 (T1.1) — spawn polyglot services BEFORE Vite. Healthcheck gates\n // readiness. Empty `services: {}` → early return (Wave 1 BC preserved).\n const orchestration = await orchestrateDev({\n cwd,\n services: config.services,\n })\n if (!orchestration.allHealthy) {\n await orchestration.stop()\n throw new Error(\n `[services] services failed healthcheck: ${orchestration.unhealthy.join(', ')}. ` +\n `Check that each declared service binds its port and responds 200 on its ` +\n `healthcheck path within 30s.`,\n )\n }\n\n // Phase 7 — legacy fs-mtime sweep removed: SDK's Agent.registry handles\n // LRU + idle eviction natively (configurable via theo.config.ts >\n // agents.registry; lazy-configured on first request).\n\n const port = options?.port ?? config.port\n // Narrow the rateLimit union: only the legacy flat shape (windowMs+max)\n // flows into the theoPlugin's RateLimitConfig parameter. The per-route\n // variant is consumed inside the api-middleware via the loaded user\n // config separately.\n const flatRateLimit =\n config.rateLimit && 'windowMs' in config.rateLimit && 'max' in config.rateLimit\n ? config.rateLimit\n : undefined\n // theoPluginAsync auto-chains @theokit/ui + @tailwindcss/vite via\n // top-level Plugin[] return (sync `theoPlugin()` factory's config()\n // hook returning {plugins:[...]} is silently dropped by Vite — see\n // commit history). Spread the result so Vite flattens them.\n let server: ViteDevServer\n try {\n const theoPlugins = await theoPluginAsync({\n root: cwd,\n rateLimit: flatRateLimit,\n ssr: config.ssr,\n // Wave 2 (T3.1) — wire typed-client plugin when services declared.\n services: config.services,\n // T4.1 (canvas-ecosystem-refactor / ADR D6) — passthrough peer-deps\n // that plugins import dynamically (e.g., mermaid via plugin-canvas).\n viteOptimizeDeps: config.viteOptimizeDeps,\n })\n server = await createServer({\n root: cwd,\n plugins: [react(), ...theoPlugins] as Plugin[],\n server: {\n port,\n host: config.host,\n open: config.open,\n strictPort: config.strictPort,\n warmup: config.warmup ?? {\n clientFiles: ['./app/**/*.tsx', './app/**/*.ts'],\n },\n },\n logLevel: options?.port === 0 ? 'silent' : undefined,\n })\n\n await server.listen()\n } catch (err) {\n // EC-1 / try-finally pattern: if Vite create/listen fails AFTER services\n // started, stop them so we don't leak child processes.\n await orchestration.stop()\n throw err\n }\n\n // EC-1 fix: attach orchestration.stop() to the underlying HTTP server's\n // close event via Node-native API. We do NOT mutate `server.close`\n // (fragile across Vite upgrades). httpServer is `http.Server | null`.\n server.httpServer?.on('close', () => {\n void orchestration.stop()\n })\n\n return server\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n try {\n const cwd = process.cwd()\n const server = await startDevServer(cwd, options)\n server.printUrls()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,WAAW;AAClB,SAAS,oBAAqD;AAa9D,eAAsB,eAAe,KAAa,SAA8C;AAM9F,2BAAyB,GAAG;AAK5B,UAAQ,EAAE,KAAK,MAAM,cAAc,CAAC;AAEpC,QAAM,SAAS,MAAM,WAAW,GAAG;AACnC,2BAAyB,GAAG;AAI5B,QAAM,gBAAgB,MAAM,eAAe;AAAA,IACzC;AAAA,IACA,UAAU,OAAO;AAAA,EACnB,CAAC;AACD,MAAI,CAAC,cAAc,YAAY;AAC7B,UAAM,cAAc,KAAK;AACzB,UAAM,IAAI;AAAA,MACR,2CAA2C,cAAc,UAAU,KAAK,IAAI,CAAC;AAAA,IAG/E;AAAA,EACF;AAMA,QAAM,OAAO,SAAS,QAAQ,OAAO;AAKrC,QAAM,gBACJ,OAAO,aAAa,cAAc,OAAO,aAAa,SAAS,OAAO,YAClE,OAAO,YACP;AAKN,MAAI;AACJ,MAAI;AACF,UAAM,cAAc,MAAM,gBAAgB;AAAA,MACxC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,KAAK,OAAO;AAAA;AAAA,MAEZ,UAAU,OAAO;AAAA;AAAA;AAAA,MAGjB,kBAAkB,OAAO;AAAA,IAC3B,CAAC;AACD,aAAS,MAAM,aAAa;AAAA,MAC1B,MAAM;AAAA,MACN,SAAS,CAAC,MAAM,GAAG,GAAG,WAAW;AAAA,MACjC,QAAQ;AAAA,QACN;AAAA,QACA,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,QAAQ,OAAO,UAAU;AAAA,UACvB,aAAa,CAAC,kBAAkB,eAAe;AAAA,QACjD;AAAA,MACF;AAAA,MACA,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,IAC7C,CAAC;AAED,UAAM,OAAO,OAAO;AAAA,EACtB,SAAS,KAAK;AAGZ,UAAM,cAAc,KAAK;AACzB,UAAM;AAAA,EACR;AAKA,SAAO,YAAY,GAAG,SAAS,MAAM;AACnC,SAAK,cAAc,KAAK;AAAA,EAC1B,CAAC;AAED,SAAO;AACT;AAEA,eAAsB,WAAW,SAAoC;AACnE,MAAI;AACF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,SAAS,MAAM,eAAe,KAAK,OAAO;AAChD,WAAO,UAAU;AAAA,EACnB,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAQ,MAAM;AAAA,WAAS,GAAG;AAAA,CAAI;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/dev.ts"],"sourcesContent":["import react from '@vitejs/plugin-react'\nimport { createServer, type Plugin, type ViteDevServer } from 'vite'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { loadEnv } from '../../config/load-env.js'\nimport { validateProjectStructure } from '../../config/validate-structure.js'\nimport { orchestrateDev } from '../../services/index.js'\nimport { theoPluginAsync } from '../../vite-plugin/index.js'\nimport { preflightNodeAndBindings } from '../preflight-node-version.js'\n\ninterface DevOptions {\n port?: number\n}\n\nexport async function startDevServer(cwd: string, options?: DevOptions): Promise<ViteDevServer> {\n // Preflight (FIRST — BEFORE anything that touches native bindings):\n // verifies Node version + native binding ABI match. Emits actionable\n // error referencing `nvm use` + `pnpm rebuild` when the dev server\n // was spawned under the wrong Node (common gotcha with `nohup env ...`\n // stripping the nvm PATH prefix).\n preflightNodeAndBindings(cwd)\n\n // Phase 1 (T1.2) — Load .env files into process.env BEFORE any module\n // reads them. Must run before loadConfig() so theo.config.ts functions\n // referencing process.env.* resolve correctly.\n loadEnv({ cwd, mode: 'development' })\n\n const config = await loadConfig(cwd)\n validateProjectStructure(cwd)\n\n // Wave 2 (T1.1) — spawn polyglot services BEFORE Vite. Healthcheck gates\n // readiness. Empty `services: {}` → early return (Wave 1 BC preserved).\n const orchestration = await orchestrateDev({\n cwd,\n services: config.services,\n })\n if (!orchestration.allHealthy) {\n await orchestration.stop()\n throw new Error(\n `[services] services failed healthcheck: ${orchestration.unhealthy.join(', ')}. ` +\n `Check that each declared service binds its port and responds 200 on its ` +\n `healthcheck path within 30s.`,\n )\n }\n\n // Phase 7 — legacy fs-mtime sweep removed: SDK's Agent.registry handles\n // LRU + idle eviction natively (configurable via theo.config.ts >\n // agents.registry; lazy-configured on first request).\n\n const port = options?.port ?? config.port\n // Narrow the rateLimit union: only the legacy flat shape (windowMs+max)\n // flows into the theoPlugin's RateLimitConfig parameter. The per-route\n // variant is consumed inside the api-middleware via the loaded user\n // config separately.\n const flatRateLimit =\n config.rateLimit && 'windowMs' in config.rateLimit && 'max' in config.rateLimit\n ? config.rateLimit\n : undefined\n // theoPluginAsync auto-chains @theokit/ui + @tailwindcss/vite via\n // top-level Plugin[] return (sync `theoPlugin()` factory's config()\n // hook returning {plugins:[...]} is silently dropped by Vite — see\n // commit history). Spread the result so Vite flattens them.\n let server: ViteDevServer\n try {\n const theoPlugins = await theoPluginAsync({\n root: cwd,\n rateLimit: flatRateLimit,\n ssr: config.ssr,\n // Wave 2 (T3.1) — wire typed-client plugin when services declared.\n services: config.services,\n // T4.1 (canvas-ecosystem-refactor / ADR D6) — passthrough peer-deps\n // that plugins import dynamically (e.g., mermaid via plugin-canvas).\n viteOptimizeDeps: config.viteOptimizeDeps,\n })\n server = await createServer({\n root: cwd,\n plugins: [react(), ...theoPlugins] as Plugin[],\n server: {\n port,\n host: config.host,\n open: config.open,\n strictPort: config.strictPort,\n warmup: config.warmup ?? {\n clientFiles: ['./app/**/*.tsx', './app/**/*.ts'],\n },\n },\n logLevel: options?.port === 0 ? 'silent' : undefined,\n })\n\n await server.listen()\n } catch (err) {\n // EC-1 / try-finally pattern: if Vite create/listen fails AFTER services\n // started, stop them so we don't leak child processes.\n await orchestration.stop()\n throw err\n }\n\n // EC-1 fix: attach orchestration.stop() to the underlying HTTP server's\n // close event via Node-native API. We do NOT mutate `server.close`\n // (fragile across Vite upgrades). httpServer is `http.Server | null`.\n server.httpServer?.on('close', () => {\n void orchestration.stop()\n })\n\n return server\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n try {\n const cwd = process.cwd()\n const server = await startDevServer(cwd, options)\n server.printUrls()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n console.error(`\\n ✗ ${msg}\\n`)\n process.exit(1)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,WAAW;AAClB,SAAS,oBAAqD;AAa9D,eAAsB,eAAe,KAAa,SAA8C;AAM9F,2BAAyB,GAAG;AAK5B,UAAQ,EAAE,KAAK,MAAM,cAAc,CAAC;AAEpC,QAAM,SAAS,MAAM,WAAW,GAAG;AACnC,2BAAyB,GAAG;AAI5B,QAAM,gBAAgB,MAAM,eAAe;AAAA,IACzC;AAAA,IACA,UAAU,OAAO;AAAA,EACnB,CAAC;AACD,MAAI,CAAC,cAAc,YAAY;AAC7B,UAAM,cAAc,KAAK;AACzB,UAAM,IAAI;AAAA,MACR,2CAA2C,cAAc,UAAU,KAAK,IAAI,CAAC;AAAA,IAG/E;AAAA,EACF;AAMA,QAAM,OAAO,SAAS,QAAQ,OAAO;AAKrC,QAAM,gBACJ,OAAO,aAAa,cAAc,OAAO,aAAa,SAAS,OAAO,YAClE,OAAO,YACP;AAKN,MAAI;AACJ,MAAI;AACF,UAAM,cAAc,MAAM,gBAAgB;AAAA,MACxC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,KAAK,OAAO;AAAA;AAAA,MAEZ,UAAU,OAAO;AAAA;AAAA;AAAA,MAGjB,kBAAkB,OAAO;AAAA,IAC3B,CAAC;AACD,aAAS,MAAM,aAAa;AAAA,MAC1B,MAAM;AAAA,MACN,SAAS,CAAC,MAAM,GAAG,GAAG,WAAW;AAAA,MACjC,QAAQ;AAAA,QACN;AAAA,QACA,MAAM,OAAO;AAAA,QACb,MAAM,OAAO;AAAA,QACb,YAAY,OAAO;AAAA,QACnB,QAAQ,OAAO,UAAU;AAAA,UACvB,aAAa,CAAC,kBAAkB,eAAe;AAAA,QACjD;AAAA,MACF;AAAA,MACA,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,IAC7C,CAAC;AAED,UAAM,OAAO,OAAO;AAAA,EACtB,SAAS,KAAK;AAGZ,UAAM,cAAc,KAAK;AACzB,UAAM;AAAA,EACR;AAKA,SAAO,YAAY,GAAG,SAAS,MAAM;AACnC,SAAK,cAAc,KAAK;AAAA,EAC1B,CAAC;AAED,SAAO;AACT;AAEA,eAAsB,WAAW,SAAoC;AACnE,MAAI;AACF,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,SAAS,MAAM,eAAe,KAAK,OAAO;AAChD,WAAO,UAAU;AAAA,EACnB,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAQ,MAAM;AAAA,WAAS,GAAG;AAAA,CAAI;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","names":[]}
@@ -6,8 +6,10 @@ import {
6
6
  } from "./chunk-JAIKGP3Q.js";
7
7
  import {
8
8
  generateManifest
9
- } from "./chunk-F4YUPDJ2.js";
10
- import "./chunk-BQDGES7C.js";
9
+ } from "./chunk-NXTF5PPW.js";
10
+ import "./chunk-34YQOXGM.js";
11
+ import "./chunk-GBXLKYIA.js";
12
+ import "./chunk-P37RZRFV.js";
11
13
 
12
14
  // src/vite-plugin/openapi-emit/dev-emit.ts
13
15
  var inFlight = false;
@@ -39,4 +41,4 @@ export {
39
41
  _resetInFlightForTests,
40
42
  reEmitOpenApi
41
43
  };
42
- //# sourceMappingURL=dev-emit-5MDSBP5D.js.map
44
+ //# sourceMappingURL=dev-emit-VJ5CFMPY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vite-plugin/openapi-emit/dev-emit.ts"],"sourcesContent":["/**\n * Dev-mode OpenAPI emit helper for `theokit dev`.\n *\n * Per P#3 plan v1.3 T1.1 (ADRs D3 + D4 + EC-8). Called once on `theokit dev`\n * boot AND on every chokidar 'change'/'add'/'unlink' watcher event for\n * route files when `config.openapi !== undefined`. Re-runs G2's\n * `emitOpenApi()` orchestrator to keep `<distDir>/openapi.json` always\n * fresh in dev.\n *\n * EC-8 absorbed (single-flight guard): if a previous invocation is still\n * awaiting `loadRoutesForOpenApi` (Vite SSR loader can hang on circular\n * imports or syntax errors), skip the new call and emit a `console.warn`\n * so watcher events don't pile up + dev server doesn't deadlock.\n *\n * Best-effort: ALL errors caught + warned. Never throws out of the\n * exported function (would crash Vite dev's chokidar handler).\n *\n * NEVER ship to runtime — dev-only artifact gated on `config.openapi`.\n */\nimport { generateManifest } from '../../server/scan/manifest.js'\n\nimport { emitOpenApi } from './emit.js'\nimport { loadRoutesForOpenApi } from './load-routes.js'\n\ninterface DevEmitConfig {\n servers: { url: string; description?: string }[]\n specVersion: '3.1.0' | '3.0.3'\n title: string\n version: string\n}\n\nlet inFlight = false\n\nexport async function reEmitOpenApi(\n serverDir: string,\n distDir: string,\n openApiConfig: DevEmitConfig,\n): Promise<void> {\n if (inFlight) {\n console.warn(\n '[openapi-emit] previous emit still running; skipping watcher event (EC-8 single-flight guard)',\n )\n return\n }\n inFlight = true\n try {\n const manifest = generateManifest(serverDir)\n const hydrated = await loadRoutesForOpenApi({ serverDir, routes: manifest.routes })\n emitOpenApi({\n manifest: hydrated,\n config: { ...openApiConfig, outDir: distDir },\n })\n } catch (err) {\n console.warn(`[openapi-emit] re-emit failed: ${(err as Error).message}`)\n } finally {\n inFlight = false\n }\n}\n\n/** Test seam — resets the inFlight flag between tests. NOT for production use. */\nexport function _resetInFlightForTests(): void {\n inFlight = false\n}\n"],"mappings":";;;;;;;;;;;;AA+BA,IAAI,WAAW;AAEf,eAAsB,cACpB,WACA,SACA,eACe;AACf,MAAI,UAAU;AACZ,YAAQ;AAAA,MACN;AAAA,IACF;AACA;AAAA,EACF;AACA,aAAW;AACX,MAAI;AACF,UAAM,WAAW,iBAAiB,SAAS;AAC3C,UAAM,WAAW,MAAM,qBAAqB,EAAE,WAAW,QAAQ,SAAS,OAAO,CAAC;AAClF,gBAAY;AAAA,MACV,UAAU;AAAA,MACV,QAAQ,EAAE,GAAG,eAAe,QAAQ,QAAQ;AAAA,IAC9C,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,KAAK,kCAAmC,IAAc,OAAO,EAAE;AAAA,EACzE,UAAE;AACA,eAAW;AAAA,EACb;AACF;AAGO,SAAS,yBAA+B;AAC7C,aAAW;AACb;","names":[]}
1
+ {"version":3,"sources":["../src/vite-plugin/openapi-emit/dev-emit.ts"],"sourcesContent":["/**\n * Dev-mode OpenAPI emit helper for `theokit dev`.\n *\n * Per P#3 plan v1.3 T1.1 (ADRs D3 + D4 + EC-8). Called once on `theokit dev`\n * boot AND on every chokidar 'change'/'add'/'unlink' watcher event for\n * route files when `config.openapi !== undefined`. Re-runs G2's\n * `emitOpenApi()` orchestrator to keep `<distDir>/openapi.json` always\n * fresh in dev.\n *\n * EC-8 absorbed (single-flight guard): if a previous invocation is still\n * awaiting `loadRoutesForOpenApi` (Vite SSR loader can hang on circular\n * imports or syntax errors), skip the new call and emit a `console.warn`\n * so watcher events don't pile up + dev server doesn't deadlock.\n *\n * Best-effort: ALL errors caught + warned. Never throws out of the\n * exported function (would crash Vite dev's chokidar handler).\n *\n * NEVER ship to runtime — dev-only artifact gated on `config.openapi`.\n */\nimport { generateManifest } from '../../server/scan/manifest.js'\n\nimport { emitOpenApi } from './emit.js'\nimport { loadRoutesForOpenApi } from './load-routes.js'\n\ninterface DevEmitConfig {\n servers: { url: string; description?: string }[]\n specVersion: '3.1.0' | '3.0.3'\n title: string\n version: string\n}\n\nlet inFlight = false\n\nexport async function reEmitOpenApi(\n serverDir: string,\n distDir: string,\n openApiConfig: DevEmitConfig,\n): Promise<void> {\n if (inFlight) {\n console.warn(\n '[openapi-emit] previous emit still running; skipping watcher event (EC-8 single-flight guard)',\n )\n return\n }\n inFlight = true\n try {\n const manifest = generateManifest(serverDir)\n const hydrated = await loadRoutesForOpenApi({ serverDir, routes: manifest.routes })\n emitOpenApi({\n manifest: hydrated,\n config: { ...openApiConfig, outDir: distDir },\n })\n } catch (err) {\n console.warn(`[openapi-emit] re-emit failed: ${(err as Error).message}`)\n } finally {\n inFlight = false\n }\n}\n\n/** Test seam — resets the inFlight flag between tests. NOT for production use. */\nexport function _resetInFlightForTests(): void {\n inFlight = false\n}\n"],"mappings":";;;;;;;;;;;;;;AA+BA,IAAI,WAAW;AAEf,eAAsB,cACpB,WACA,SACA,eACe;AACf,MAAI,UAAU;AACZ,YAAQ;AAAA,MACN;AAAA,IACF;AACA;AAAA,EACF;AACA,aAAW;AACX,MAAI;AACF,UAAM,WAAW,iBAAiB,SAAS;AAC3C,UAAM,WAAW,MAAM,qBAAqB,EAAE,WAAW,QAAQ,SAAS,OAAO,CAAC;AAClF,gBAAY;AAAA,MACV,UAAU;AAAA,MACV,QAAQ,EAAE,GAAG,eAAe,QAAQ,QAAQ;AAAA,IAC9C,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,KAAK,kCAAmC,IAAc,OAAO,EAAE;AAAA,EACzE,UAAE;AACA,eAAW;AAAA,EACb;AACF;AAGO,SAAS,yBAA+B;AAC7C,aAAW;AACb;","names":[]}
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  scanRoutes,
9
9
  theoConfigSchema,
10
10
  theoPlugin
11
- } from "./chunk-RBHCJHRR.js";
11
+ } from "./chunk-UOR6JTCI.js";
12
12
  import "./chunk-D7ZH7DTG.js";
13
13
  import "./chunk-RSVN727G.js";
14
14
  import "./chunk-7BIM27LV.js";
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import "tsx/esm";
3
+ import {
4
+ scanRoutes
5
+ } from "./chunk-IEES3CHD.js";
3
6
  import {
4
7
  loadConfig
5
- } from "./chunk-7YZHAQU7.js";
8
+ } from "./chunk-567NA7Y6.js";
9
+ import "./chunk-GDN3PXFH.js";
6
10
  import "./chunk-YJAUJXZS.js";
7
11
  import "./chunk-45C3WUQ7.js";
8
- import {
9
- scanRoutes
10
- } from "./chunk-IEES3CHD.js";
11
12
 
12
13
  // src/cli/commands/info.ts
13
14
  import { existsSync, readFileSync } from "fs";
@@ -100,4 +101,4 @@ export {
100
101
  buildInfo,
101
102
  infoCommand
102
103
  };
103
- //# sourceMappingURL=info-OUEUZOT7.js.map
104
+ //# sourceMappingURL=info-7PE2PZJI.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/info.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * CLI `theo info` reader. Reads `package.json`, `theo.config.*`, lock\n * files under the user's `cwd`. Read-only build-time tool. No HTTP input.\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { scanRoutes } from '../../router/scan.js'\n\nexport interface RuntimeInfo {\n name: 'node' | 'bun' | 'deno' | 'unknown'\n version: string\n}\n\nexport interface PackageJsonMinimal {\n name?: string\n version?: string\n}\n\nexport interface ConfigSummary {\n ok: boolean\n summary: string\n}\n\nexport interface BuildInfoDeps {\n cwd: string\n readPackageJson?: () => PackageJsonMinimal | null\n detectRuntime?: () => RuntimeInfo\n loadConfig?: () => Promise<ConfigSummary>\n countRoutes?: () => number\n}\n\nfunction defaultDetectRuntime(): RuntimeInfo {\n const g = globalThis as { Bun?: { version: string }; Deno?: { version: { deno: string } } }\n if (g.Bun?.version) {\n return { name: 'bun', version: g.Bun.version }\n }\n if (g.Deno?.version) {\n return { name: 'deno', version: g.Deno.version.deno }\n }\n if (typeof process !== 'undefined' && process.versions.node) {\n return { name: 'node', version: process.versions.node }\n }\n return { name: 'unknown', version: '?' }\n}\n\nfunction defaultReadPackageJson(cwd: string): PackageJsonMinimal | null {\n const path = resolve(cwd, 'package.json')\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as PackageJsonMinimal\n return parsed\n } catch {\n return null\n }\n}\n\nasync function defaultLoadConfig(cwd: string): Promise<ConfigSummary> {\n try {\n await loadConfig(cwd)\n return { ok: true, summary: 'config OK' }\n } catch (err) {\n return { ok: false, summary: (err as Error).message }\n }\n}\n\nfunction defaultCountRoutes(cwd: string): number {\n const appDir = resolve(cwd, 'app')\n if (!existsSync(appDir)) return 0\n const tree = scanRoutes(appDir)\n let count = 0\n function walk(node: { page?: string; children: { page?: string; children: unknown[] }[] }): void {\n if (node.page) count++\n for (const child of node.children) walk(child as never)\n }\n walk(tree)\n return count\n}\n\nexport async function buildInfo(deps: BuildInfoDeps): Promise<string> {\n const cwd = deps.cwd\n const readPkg = deps.readPackageJson ?? (() => defaultReadPackageJson(cwd))\n const runtime = (deps.detectRuntime ?? defaultDetectRuntime)()\n const loadCfg = deps.loadConfig ?? (() => defaultLoadConfig(cwd))\n const countRts = deps.countRoutes ?? (() => defaultCountRoutes(cwd))\n\n const pkg = readPkg()\n const config = await loadCfg()\n\n let routesCount = 0\n let scanError: string | null = null\n try {\n routesCount = countRts()\n } catch (err) {\n scanError = (err as Error).message\n }\n\n const projectLine = pkg?.name ? `${pkg.name}@${pkg.version ?? '?'}` : '(missing)'\n\n const configLine = config.ok ? 'OK' : `INVALID — ${config.summary}`\n\n const routesLine = scanError ? `Scan failed: ${scanError}` : `Routes: ${routesCount}`\n\n return [\n `# Theo info`,\n ``,\n `## Project`,\n `Project: ${projectLine}`,\n ``,\n `## Runtime`,\n `${runtime.name} ${runtime.version}`,\n ``,\n `## Config`,\n `Config: ${configLine}`,\n ``,\n `## App`,\n routesLine,\n ``,\n ].join('\\n')\n}\n\nexport async function infoCommand(): Promise<void> {\n const cwd = process.cwd()\n const output = await buildInfo({ cwd })\n console.log(output)\n}\n"],"mappings":";;;;;;;;;;;;AAIA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe;AA4BxB,SAAS,uBAAoC;AAC3C,QAAM,IAAI;AACV,MAAI,EAAE,KAAK,SAAS;AAClB,WAAO,EAAE,MAAM,OAAO,SAAS,EAAE,IAAI,QAAQ;AAAA,EAC/C;AACA,MAAI,EAAE,MAAM,SAAS;AACnB,WAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,KAAK,QAAQ,KAAK;AAAA,EACtD;AACA,MAAI,OAAO,YAAY,eAAe,QAAQ,SAAS,MAAM;AAC3D,WAAO,EAAE,MAAM,QAAQ,SAAS,QAAQ,SAAS,KAAK;AAAA,EACxD;AACA,SAAO,EAAE,MAAM,WAAW,SAAS,IAAI;AACzC;AAEA,SAAS,uBAAuB,KAAwC;AACtE,QAAM,OAAO,QAAQ,KAAK,cAAc;AACxC,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,MAAM,aAAa,MAAM,OAAO;AACtC,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,kBAAkB,KAAqC;AACpE,MAAI;AACF,UAAM,WAAW,GAAG;AACpB,WAAO,EAAE,IAAI,MAAM,SAAS,YAAY;AAAA,EAC1C,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,SAAU,IAAc,QAAQ;AAAA,EACtD;AACF;AAEA,SAAS,mBAAmB,KAAqB;AAC/C,QAAM,SAAS,QAAQ,KAAK,KAAK;AACjC,MAAI,CAAC,WAAW,MAAM,EAAG,QAAO;AAChC,QAAM,OAAO,WAAW,MAAM;AAC9B,MAAI,QAAQ;AACZ,WAAS,KAAK,MAAmF;AAC/F,QAAI,KAAK,KAAM;AACf,eAAW,SAAS,KAAK,SAAU,MAAK,KAAc;AAAA,EACxD;AACA,OAAK,IAAI;AACT,SAAO;AACT;AAEA,eAAsB,UAAU,MAAsC;AACpE,QAAM,MAAM,KAAK;AACjB,QAAM,UAAU,KAAK,oBAAoB,MAAM,uBAAuB,GAAG;AACzE,QAAM,WAAW,KAAK,iBAAiB,sBAAsB;AAC7D,QAAM,UAAU,KAAK,eAAe,MAAM,kBAAkB,GAAG;AAC/D,QAAM,WAAW,KAAK,gBAAgB,MAAM,mBAAmB,GAAG;AAElE,QAAM,MAAM,QAAQ;AACpB,QAAM,SAAS,MAAM,QAAQ;AAE7B,MAAI,cAAc;AAClB,MAAI,YAA2B;AAC/B,MAAI;AACF,kBAAc,SAAS;AAAA,EACzB,SAAS,KAAK;AACZ,gBAAa,IAAc;AAAA,EAC7B;AAEA,QAAM,cAAc,KAAK,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,WAAW,GAAG,KAAK;AAEtE,QAAM,aAAa,OAAO,KAAK,OAAO,kBAAa,OAAO,OAAO;AAEjE,QAAM,aAAa,YAAY,gBAAgB,SAAS,KAAK,WAAW,WAAW;AAEnF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,WAAW;AAAA,IACvB;AAAA,IACA;AAAA,IACA,GAAG,QAAQ,IAAI,IAAI,QAAQ,OAAO;AAAA,IAClC;AAAA,IACA;AAAA,IACA,WAAW,UAAU;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,eAAsB,cAA6B;AACjD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,UAAU,EAAE,IAAI,CAAC;AACtC,UAAQ,IAAI,MAAM;AACpB;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/info.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * CLI `theo info` reader. Reads `package.json`, `theo.config.*`, lock\n * files under the user's `cwd`. Read-only build-time tool. No HTTP input.\n */\nimport { existsSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { scanRoutes } from '../../router/scan.js'\n\nexport interface RuntimeInfo {\n name: 'node' | 'bun' | 'deno' | 'unknown'\n version: string\n}\n\nexport interface PackageJsonMinimal {\n name?: string\n version?: string\n}\n\nexport interface ConfigSummary {\n ok: boolean\n summary: string\n}\n\nexport interface BuildInfoDeps {\n cwd: string\n readPackageJson?: () => PackageJsonMinimal | null\n detectRuntime?: () => RuntimeInfo\n loadConfig?: () => Promise<ConfigSummary>\n countRoutes?: () => number\n}\n\nfunction defaultDetectRuntime(): RuntimeInfo {\n const g = globalThis as { Bun?: { version: string }; Deno?: { version: { deno: string } } }\n if (g.Bun?.version) {\n return { name: 'bun', version: g.Bun.version }\n }\n if (g.Deno?.version) {\n return { name: 'deno', version: g.Deno.version.deno }\n }\n if (typeof process !== 'undefined' && process.versions.node) {\n return { name: 'node', version: process.versions.node }\n }\n return { name: 'unknown', version: '?' }\n}\n\nfunction defaultReadPackageJson(cwd: string): PackageJsonMinimal | null {\n const path = resolve(cwd, 'package.json')\n if (!existsSync(path)) return null\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as PackageJsonMinimal\n return parsed\n } catch {\n return null\n }\n}\n\nasync function defaultLoadConfig(cwd: string): Promise<ConfigSummary> {\n try {\n await loadConfig(cwd)\n return { ok: true, summary: 'config OK' }\n } catch (err) {\n return { ok: false, summary: (err as Error).message }\n }\n}\n\nfunction defaultCountRoutes(cwd: string): number {\n const appDir = resolve(cwd, 'app')\n if (!existsSync(appDir)) return 0\n const tree = scanRoutes(appDir)\n let count = 0\n function walk(node: { page?: string; children: { page?: string; children: unknown[] }[] }): void {\n if (node.page) count++\n for (const child of node.children) walk(child as never)\n }\n walk(tree)\n return count\n}\n\nexport async function buildInfo(deps: BuildInfoDeps): Promise<string> {\n const cwd = deps.cwd\n const readPkg = deps.readPackageJson ?? (() => defaultReadPackageJson(cwd))\n const runtime = (deps.detectRuntime ?? defaultDetectRuntime)()\n const loadCfg = deps.loadConfig ?? (() => defaultLoadConfig(cwd))\n const countRts = deps.countRoutes ?? (() => defaultCountRoutes(cwd))\n\n const pkg = readPkg()\n const config = await loadCfg()\n\n let routesCount = 0\n let scanError: string | null = null\n try {\n routesCount = countRts()\n } catch (err) {\n scanError = (err as Error).message\n }\n\n const projectLine = pkg?.name ? `${pkg.name}@${pkg.version ?? '?'}` : '(missing)'\n\n const configLine = config.ok ? 'OK' : `INVALID — ${config.summary}`\n\n const routesLine = scanError ? `Scan failed: ${scanError}` : `Routes: ${routesCount}`\n\n return [\n `# Theo info`,\n ``,\n `## Project`,\n `Project: ${projectLine}`,\n ``,\n `## Runtime`,\n `${runtime.name} ${runtime.version}`,\n ``,\n `## Config`,\n `Config: ${configLine}`,\n ``,\n `## App`,\n routesLine,\n ``,\n ].join('\\n')\n}\n\nexport async function infoCommand(): Promise<void> {\n const cwd = process.cwd()\n const output = await buildInfo({ cwd })\n console.log(output)\n}\n"],"mappings":";;;;;;;;;;;;;AAIA,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe;AA4BxB,SAAS,uBAAoC;AAC3C,QAAM,IAAI;AACV,MAAI,EAAE,KAAK,SAAS;AAClB,WAAO,EAAE,MAAM,OAAO,SAAS,EAAE,IAAI,QAAQ;AAAA,EAC/C;AACA,MAAI,EAAE,MAAM,SAAS;AACnB,WAAO,EAAE,MAAM,QAAQ,SAAS,EAAE,KAAK,QAAQ,KAAK;AAAA,EACtD;AACA,MAAI,OAAO,YAAY,eAAe,QAAQ,SAAS,MAAM;AAC3D,WAAO,EAAE,MAAM,QAAQ,SAAS,QAAQ,SAAS,KAAK;AAAA,EACxD;AACA,SAAO,EAAE,MAAM,WAAW,SAAS,IAAI;AACzC;AAEA,SAAS,uBAAuB,KAAwC;AACtE,QAAM,OAAO,QAAQ,KAAK,cAAc;AACxC,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,MAAM,aAAa,MAAM,OAAO;AACtC,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,kBAAkB,KAAqC;AACpE,MAAI;AACF,UAAM,WAAW,GAAG;AACpB,WAAO,EAAE,IAAI,MAAM,SAAS,YAAY;AAAA,EAC1C,SAAS,KAAK;AACZ,WAAO,EAAE,IAAI,OAAO,SAAU,IAAc,QAAQ;AAAA,EACtD;AACF;AAEA,SAAS,mBAAmB,KAAqB;AAC/C,QAAM,SAAS,QAAQ,KAAK,KAAK;AACjC,MAAI,CAAC,WAAW,MAAM,EAAG,QAAO;AAChC,QAAM,OAAO,WAAW,MAAM;AAC9B,MAAI,QAAQ;AACZ,WAAS,KAAK,MAAmF;AAC/F,QAAI,KAAK,KAAM;AACf,eAAW,SAAS,KAAK,SAAU,MAAK,KAAc;AAAA,EACxD;AACA,OAAK,IAAI;AACT,SAAO;AACT;AAEA,eAAsB,UAAU,MAAsC;AACpE,QAAM,MAAM,KAAK;AACjB,QAAM,UAAU,KAAK,oBAAoB,MAAM,uBAAuB,GAAG;AACzE,QAAM,WAAW,KAAK,iBAAiB,sBAAsB;AAC7D,QAAM,UAAU,KAAK,eAAe,MAAM,kBAAkB,GAAG;AAC/D,QAAM,WAAW,KAAK,gBAAgB,MAAM,mBAAmB,GAAG;AAElE,QAAM,MAAM,QAAQ;AACpB,QAAM,SAAS,MAAM,QAAQ;AAE7B,MAAI,cAAc;AAClB,MAAI,YAA2B;AAC/B,MAAI;AACF,kBAAc,SAAS;AAAA,EACzB,SAAS,KAAK;AACZ,gBAAa,IAAc;AAAA,EAC7B;AAEA,QAAM,cAAc,KAAK,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,WAAW,GAAG,KAAK;AAEtE,QAAM,aAAa,OAAO,KAAK,OAAO,kBAAa,OAAO,OAAO;AAEjE,QAAM,aAAa,YAAY,gBAAgB,SAAS,KAAK,WAAW,WAAW;AAEnF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,WAAW;AAAA,IACvB;AAAA,IACA;AAAA,IACA,GAAG,QAAQ,IAAI,IAAI,QAAQ,OAAO;AAAA,IAClC;AAAA,IACA;AAAA,IACA,WAAW,UAAU;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,eAAsB,cAA6B;AACjD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,UAAU,EAAE,IAAI,CAAC;AACtC,UAAQ,IAAI,MAAM;AACpB;","names":[]}
@@ -24,16 +24,19 @@ import {
24
24
  sendError
25
25
  } from "./chunk-WR4F4EEZ.js";
26
26
  import {
27
- generateManifest,
27
+ generateManifest
28
+ } from "./chunk-NXTF5PPW.js";
29
+ import {
28
30
  scanAgents
29
- } from "./chunk-F4YUPDJ2.js";
31
+ } from "./chunk-34YQOXGM.js";
30
32
  import {
31
33
  matchRoute,
32
34
  scanServerActions,
33
35
  scanServerActionsEnriched,
34
36
  scanServerRoutes,
35
37
  scanWebSocketRoutes
36
- } from "./chunk-BQDGES7C.js";
38
+ } from "./chunk-GBXLKYIA.js";
39
+ import "./chunk-P37RZRFV.js";
37
40
  import "./chunk-HGZL5EOI.js";
38
41
  export {
39
42
  BATCH_PATH,
@@ -63,4 +66,4 @@ export {
63
66
  scanWebSocketRoutes,
64
67
  sendError
65
68
  };
66
- //# sourceMappingURL=internal-api-EFKZWIYZ.js.map
69
+ //# sourceMappingURL=internal-api-J27TYE2I.js.map
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+ import {
4
+ deepMerge,
5
+ loadConfig
6
+ } from "./chunk-567NA7Y6.js";
7
+ import "./chunk-GDN3PXFH.js";
8
+ import "./chunk-YJAUJXZS.js";
9
+ import "./chunk-45C3WUQ7.js";
10
+ export {
11
+ deepMerge,
12
+ loadConfig
13
+ };
14
+ //# sourceMappingURL=load-config-JKYO5RFK.js.map
@@ -6,13 +6,16 @@ import {
6
6
  } from "./chunk-JAIKGP3Q.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-7YZHAQU7.js";
9
+ } from "./chunk-567NA7Y6.js";
10
+ import "./chunk-GDN3PXFH.js";
10
11
  import "./chunk-YJAUJXZS.js";
11
12
  import "./chunk-45C3WUQ7.js";
12
13
  import {
13
14
  generateManifest
14
- } from "./chunk-F4YUPDJ2.js";
15
- import "./chunk-BQDGES7C.js";
15
+ } from "./chunk-NXTF5PPW.js";
16
+ import "./chunk-34YQOXGM.js";
17
+ import "./chunk-GBXLKYIA.js";
18
+ import "./chunk-P37RZRFV.js";
16
19
 
17
20
  // src/cli/commands/openapi.ts
18
21
  import { mkdtempSync, rmSync } from "fs";
@@ -79,4 +82,4 @@ function emitOpenApiInMemory(manifest, config) {
79
82
  export {
80
83
  openapiCommand
81
84
  };
82
- //# sourceMappingURL=openapi-FHY6HC6I.js.map
85
+ //# sourceMappingURL=openapi-MXMLZCXC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/openapi.ts"],"sourcesContent":["/**\n * `theokit openapi` — regenerate `<distDir>/openapi.json` standalone.\n *\n * Mirrors trpc-openapi's `pnpm codegen` script. Useful in dev workflows\n * when only schemas changed and a full `theokit build` would be\n * overkill.\n *\n * Per G2 plan v1.1 T2.3. Single output (dev location only) — for the\n * dist artifact, run `theokit build`.\n *\n * Flags:\n * --dry-run Validate + print the document to stdout; skip the\n * filesystem write (EC-3 absorbed).\n */\nimport { mkdtempSync, rmSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { generateManifest } from '../../server/scan/manifest.js'\nimport { emitOpenApi } from '../../vite-plugin/openapi-emit/emit.js'\nimport { loadRoutesForOpenApi } from '../../vite-plugin/openapi-emit/load-routes.js'\n\nconst MIGRATION_GUIDE_URL = 'docs/concepts/openapi.md'\n\nexport interface OpenApiCommandOptions {\n /** Project root (defaults to `process.cwd()`). */\n cwd?: string\n /** Skip the filesystem write; print the document to stdout (EC-3). */\n dryRun?: boolean\n}\n\nexport async function openapiCommand(options: OpenApiCommandOptions = {}): Promise<void> {\n const cwd = options.cwd ?? process.cwd()\n const config = await loadConfig(cwd)\n\n if (config.openapi === undefined) {\n console.error(\n `\\n ✗ openapi: not configured in theo.config.ts\\n\\n` +\n ` Add the \\`openapi\\` block to opt in:\\n\\n` +\n ` export default defineConfig({\\n` +\n ` openapi: {\\n` +\n ` title: 'My App',\\n` +\n ` version: '1.0.0',\\n` +\n ` },\\n` +\n ` })\\n\\n` +\n ` See ${MIGRATION_GUIDE_URL} for the full reference.\\n`,\n )\n process.exit(1)\n return\n }\n\n const serverDir = resolve(cwd, config.serverDir)\n const manifest = generateManifest(serverDir)\n const hydrated = await loadRoutesForOpenApi({ serverDir, routes: manifest.routes })\n\n if (options.dryRun) {\n // Build the document without writing — for the dry-run we still want a\n // valid emit pass, but with an in-memory output dir we never touch disk.\n const result = emitOpenApiInMemory(hydrated, config.openapi)\n console.log(`\\n ✓ openapi.json (dry-run): ${String(hydrated.length)} ops`)\n console.log(JSON.stringify(result.document, null, 2))\n console.log(`\\n Docs: ${MIGRATION_GUIDE_URL}\\n`)\n return\n }\n\n const distDir = resolve(cwd, config.distDir)\n const result = emitOpenApi({\n manifest: hydrated,\n config: { ...config.openapi, outDir: distDir },\n })\n console.log(\n `\\n ✓ openapi.json: ${String(hydrated.length)} ops → ${result.path}\\n` +\n ` Docs: ${MIGRATION_GUIDE_URL}\\n`,\n )\n}\n\n/**\n * Dry-run helper: build the OpenAPI doc without writing. Routes through\n * the same `emitOpenApi` but discards the side-effecting write by\n * targeting a temp directory we immediately ignore.\n *\n * Honest tradeoff: this still calls `mkdirSync` (no-op on existing tmpdir)\n * + a synchronous write to a discardable tempfile. Cost is < 1ms and the\n * code stays the single transformation. A pure no-write helper would\n * duplicate the orchestration in `emit.ts` — KISS prefers reuse.\n */\nfunction emitOpenApiInMemory(\n manifest: Parameters<typeof emitOpenApi>[0]['manifest'],\n config: Omit<Parameters<typeof emitOpenApi>[0]['config'], 'outDir'>,\n): { document: unknown } {\n const tmp = mkdtempSync(join(tmpdir(), 'theokit-openapi-dryrun-'))\n try {\n const result = emitOpenApi({ manifest, config: { ...config, outDir: tmp } })\n return { document: result.document }\n } finally {\n rmSync(tmp, { recursive: true, force: true })\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAcA,SAAS,aAAa,cAAc;AACpC,SAAS,cAAc;AACvB,SAAS,MAAM,eAAe;AAO9B,IAAM,sBAAsB;AAS5B,eAAsB,eAAe,UAAiC,CAAC,GAAkB;AACvF,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,QAAM,SAAS,MAAM,WAAW,GAAG;AAEnC,MAAI,OAAO,YAAY,QAAW;AAChC,YAAQ;AAAA,MACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQW,mBAAmB;AAAA;AAAA,IAChC;AACA,YAAQ,KAAK,CAAC;AACd;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,KAAK,OAAO,SAAS;AAC/C,QAAM,WAAW,iBAAiB,SAAS;AAC3C,QAAM,WAAW,MAAM,qBAAqB,EAAE,WAAW,QAAQ,SAAS,OAAO,CAAC;AAElF,MAAI,QAAQ,QAAQ;AAGlB,UAAMA,UAAS,oBAAoB,UAAU,OAAO,OAAO;AAC3D,YAAQ,IAAI;AAAA,mCAAiC,OAAO,SAAS,MAAM,CAAC,MAAM;AAC1E,YAAQ,IAAI,KAAK,UAAUA,QAAO,UAAU,MAAM,CAAC,CAAC;AACpD,YAAQ,IAAI;AAAA,UAAa,mBAAmB;AAAA,CAAI;AAChD;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,KAAK,OAAO,OAAO;AAC3C,QAAM,SAAS,YAAY;AAAA,IACzB,UAAU;AAAA,IACV,QAAQ,EAAE,GAAG,OAAO,SAAS,QAAQ,QAAQ;AAAA,EAC/C,CAAC;AACD,UAAQ;AAAA,IACN;AAAA,yBAAuB,OAAO,SAAS,MAAM,CAAC,eAAU,OAAO,IAAI;AAAA,UACtD,mBAAmB;AAAA;AAAA,EAClC;AACF;AAYA,SAAS,oBACP,UACA,QACuB;AACvB,QAAM,MAAM,YAAY,KAAK,OAAO,GAAG,yBAAyB,CAAC;AACjE,MAAI;AACF,UAAM,SAAS,YAAY,EAAE,UAAU,QAAQ,EAAE,GAAG,QAAQ,QAAQ,IAAI,EAAE,CAAC;AAC3E,WAAO,EAAE,UAAU,OAAO,SAAS;AAAA,EACrC,UAAE;AACA,WAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAC9C;AACF;","names":["result"]}
1
+ {"version":3,"sources":["../src/cli/commands/openapi.ts"],"sourcesContent":["/**\n * `theokit openapi` — regenerate `<distDir>/openapi.json` standalone.\n *\n * Mirrors trpc-openapi's `pnpm codegen` script. Useful in dev workflows\n * when only schemas changed and a full `theokit build` would be\n * overkill.\n *\n * Per G2 plan v1.1 T2.3. Single output (dev location only) — for the\n * dist artifact, run `theokit build`.\n *\n * Flags:\n * --dry-run Validate + print the document to stdout; skip the\n * filesystem write (EC-3 absorbed).\n */\nimport { mkdtempSync, rmSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { generateManifest } from '../../server/scan/manifest.js'\nimport { emitOpenApi } from '../../vite-plugin/openapi-emit/emit.js'\nimport { loadRoutesForOpenApi } from '../../vite-plugin/openapi-emit/load-routes.js'\n\nconst MIGRATION_GUIDE_URL = 'docs/concepts/openapi.md'\n\nexport interface OpenApiCommandOptions {\n /** Project root (defaults to `process.cwd()`). */\n cwd?: string\n /** Skip the filesystem write; print the document to stdout (EC-3). */\n dryRun?: boolean\n}\n\nexport async function openapiCommand(options: OpenApiCommandOptions = {}): Promise<void> {\n const cwd = options.cwd ?? process.cwd()\n const config = await loadConfig(cwd)\n\n if (config.openapi === undefined) {\n console.error(\n `\\n ✗ openapi: not configured in theo.config.ts\\n\\n` +\n ` Add the \\`openapi\\` block to opt in:\\n\\n` +\n ` export default defineConfig({\\n` +\n ` openapi: {\\n` +\n ` title: 'My App',\\n` +\n ` version: '1.0.0',\\n` +\n ` },\\n` +\n ` })\\n\\n` +\n ` See ${MIGRATION_GUIDE_URL} for the full reference.\\n`,\n )\n process.exit(1)\n return\n }\n\n const serverDir = resolve(cwd, config.serverDir)\n const manifest = generateManifest(serverDir)\n const hydrated = await loadRoutesForOpenApi({ serverDir, routes: manifest.routes })\n\n if (options.dryRun) {\n // Build the document without writing — for the dry-run we still want a\n // valid emit pass, but with an in-memory output dir we never touch disk.\n const result = emitOpenApiInMemory(hydrated, config.openapi)\n console.log(`\\n ✓ openapi.json (dry-run): ${String(hydrated.length)} ops`)\n console.log(JSON.stringify(result.document, null, 2))\n console.log(`\\n Docs: ${MIGRATION_GUIDE_URL}\\n`)\n return\n }\n\n const distDir = resolve(cwd, config.distDir)\n const result = emitOpenApi({\n manifest: hydrated,\n config: { ...config.openapi, outDir: distDir },\n })\n console.log(\n `\\n ✓ openapi.json: ${String(hydrated.length)} ops → ${result.path}\\n` +\n ` Docs: ${MIGRATION_GUIDE_URL}\\n`,\n )\n}\n\n/**\n * Dry-run helper: build the OpenAPI doc without writing. Routes through\n * the same `emitOpenApi` but discards the side-effecting write by\n * targeting a temp directory we immediately ignore.\n *\n * Honest tradeoff: this still calls `mkdirSync` (no-op on existing tmpdir)\n * + a synchronous write to a discardable tempfile. Cost is < 1ms and the\n * code stays the single transformation. A pure no-write helper would\n * duplicate the orchestration in `emit.ts` — KISS prefers reuse.\n */\nfunction emitOpenApiInMemory(\n manifest: Parameters<typeof emitOpenApi>[0]['manifest'],\n config: Omit<Parameters<typeof emitOpenApi>[0]['config'], 'outDir'>,\n): { document: unknown } {\n const tmp = mkdtempSync(join(tmpdir(), 'theokit-openapi-dryrun-'))\n try {\n const result = emitOpenApi({ manifest, config: { ...config, outDir: tmp } })\n return { document: result.document }\n } finally {\n rmSync(tmp, { recursive: true, force: true })\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAcA,SAAS,aAAa,cAAc;AACpC,SAAS,cAAc;AACvB,SAAS,MAAM,eAAe;AAO9B,IAAM,sBAAsB;AAS5B,eAAsB,eAAe,UAAiC,CAAC,GAAkB;AACvF,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,QAAM,SAAS,MAAM,WAAW,GAAG;AAEnC,MAAI,OAAO,YAAY,QAAW;AAChC,YAAQ;AAAA,MACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQW,mBAAmB;AAAA;AAAA,IAChC;AACA,YAAQ,KAAK,CAAC;AACd;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,KAAK,OAAO,SAAS;AAC/C,QAAM,WAAW,iBAAiB,SAAS;AAC3C,QAAM,WAAW,MAAM,qBAAqB,EAAE,WAAW,QAAQ,SAAS,OAAO,CAAC;AAElF,MAAI,QAAQ,QAAQ;AAGlB,UAAMA,UAAS,oBAAoB,UAAU,OAAO,OAAO;AAC3D,YAAQ,IAAI;AAAA,mCAAiC,OAAO,SAAS,MAAM,CAAC,MAAM;AAC1E,YAAQ,IAAI,KAAK,UAAUA,QAAO,UAAU,MAAM,CAAC,CAAC;AACpD,YAAQ,IAAI;AAAA,UAAa,mBAAmB;AAAA,CAAI;AAChD;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,KAAK,OAAO,OAAO;AAC3C,QAAM,SAAS,YAAY;AAAA,IACzB,UAAU;AAAA,IACV,QAAQ,EAAE,GAAG,OAAO,SAAS,QAAQ,QAAQ;AAAA,EAC/C,CAAC;AACD,UAAQ;AAAA,IACN;AAAA,yBAAuB,OAAO,SAAS,MAAM,CAAC,eAAU,OAAO,IAAI;AAAA,UACtD,mBAAmB;AAAA;AAAA,EAClC;AACF;AAYA,SAAS,oBACP,UACA,QACuB;AACvB,QAAM,MAAM,YAAY,KAAK,OAAO,GAAG,yBAAyB,CAAC;AACjE,MAAI;AACF,UAAM,SAAS,YAAY,EAAE,UAAU,QAAQ,EAAE,GAAG,QAAQ,QAAQ,IAAI,EAAE,CAAC;AAC3E,WAAO,EAAE,UAAU,OAAO,SAAS;AAAA,EACrC,UAAE;AACA,WAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAC9C;AACF;","names":["result"]}
@@ -6,7 +6,7 @@ var adapterRegistry = {
6
6
  node: async () => (await import("./node-BPJ3Z4DT.js")).nodeAdapter,
7
7
  vercel: async () => (await import("./vercel-J6G7ZHYQ.js")).vercelAdapter,
8
8
  cloudflare: async () => (await import("./cloudflare-C6E5SPAE.js")).cloudflareAdapter,
9
- static: async () => (await import("./static-55G3LX2I.js")).staticAdapter,
9
+ static: async () => (await import("./static-7ARBVDJF.js")).staticAdapter,
10
10
  bun: async () => (await import("./bun-KP2KES6S.js")).bunAdapter,
11
11
  "deno-deploy": async () => (await import("./deno-deploy-RFZN56X4.js")).denoDeployAdapter,
12
12
  netlify: async () => (await import("./netlify-PMLHVPN4.js")).netlifyAdapter,
@@ -21,4 +21,4 @@ export {
21
21
  adapterRegistry,
22
22
  resolveAdapter
23
23
  };
24
- //# sourceMappingURL=registry-34LL7NF4.js.map
24
+ //# sourceMappingURL=registry-XJUYD2OU.js.map
@@ -5,14 +5,16 @@ import {
5
5
  } from "./chunk-JQSFBJR5.js";
6
6
  import {
7
7
  loadConfig
8
- } from "./chunk-7YZHAQU7.js";
8
+ } from "./chunk-567NA7Y6.js";
9
+ import "./chunk-GDN3PXFH.js";
9
10
  import "./chunk-YJAUJXZS.js";
10
11
  import "./chunk-45C3WUQ7.js";
11
12
  import {
12
13
  scanServerActions,
13
14
  scanServerRoutes,
14
15
  scanWebSocketRoutes
15
- } from "./chunk-BQDGES7C.js";
16
+ } from "./chunk-GBXLKYIA.js";
17
+ import "./chunk-P37RZRFV.js";
16
18
 
17
19
  // src/cli/commands/routes.ts
18
20
  import { resolve, relative } from "path";
@@ -60,4 +62,4 @@ async function routesCommand() {
60
62
  export {
61
63
  routesCommand
62
64
  };
63
- //# sourceMappingURL=routes-EW7TP7NJ.js.map
65
+ //# sourceMappingURL=routes-NNBEZSGN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/routes.ts"],"sourcesContent":["import { resolve, relative } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { validateProjectStructure } from '../../config/validate-structure.js'\nimport { scanServerActions } from '../../server/scan/action-scan.js'\nimport { scanServerRoutes } from '../../server/scan/scan.js'\nimport { scanWebSocketRoutes } from '../../server/scan/ws-scan.js'\n\nexport async function routesCommand(): Promise<void> {\n const cwd = process.cwd()\n const config = await loadConfig(cwd)\n validateProjectStructure(cwd)\n\n const serverDir = resolve(cwd, config.serverDir)\n\n const apiRoutes = scanServerRoutes(serverDir)\n const actions = scanServerActions(serverDir)\n const wsRoutes = scanWebSocketRoutes(serverDir)\n\n const totalCount = apiRoutes.length + actions.length + wsRoutes.length\n\n if (totalCount === 0) {\n console.log('\\n No routes found.\\n')\n return\n }\n\n // API Routes\n if (apiRoutes.length > 0) {\n console.log('\\n API Routes')\n console.log(' ' + '─'.repeat(60))\n for (const route of apiRoutes) {\n const rel = relative(cwd, route.filePath)\n console.log(` GET/POST ${route.routePath.padEnd(30)} ${rel}`)\n }\n }\n\n // Actions\n if (actions.length > 0) {\n console.log('\\n Actions')\n console.log(' ' + '─'.repeat(60))\n for (const action of actions) {\n const rel = relative(cwd, action.filePath)\n console.log(` POST /api/__actions/${action.actionPath.padEnd(18)} ${rel}`)\n }\n }\n\n // WebSocket\n if (wsRoutes.length > 0) {\n console.log('\\n WebSocket')\n console.log(' ' + '─'.repeat(60))\n for (const route of wsRoutes) {\n const rel = relative(cwd, route.filePath)\n console.log(` WS ${route.wsPath.padEnd(30)} ${rel}`)\n }\n }\n\n console.log(`\\n Total: ${totalCount} endpoints\\n`)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,gBAAgB;AAQlC,eAAsB,gBAA+B;AACnD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,WAAW,GAAG;AACnC,2BAAyB,GAAG;AAE5B,QAAM,YAAY,QAAQ,KAAK,OAAO,SAAS;AAE/C,QAAM,YAAY,iBAAiB,SAAS;AAC5C,QAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAM,WAAW,oBAAoB,SAAS;AAE9C,QAAM,aAAa,UAAU,SAAS,QAAQ,SAAS,SAAS;AAEhE,MAAI,eAAe,GAAG;AACpB,YAAQ,IAAI,wBAAwB;AACpC;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,GAAG;AACxB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,SAAS,WAAW;AAC7B,YAAM,MAAM,SAAS,KAAK,MAAM,QAAQ;AACxC,cAAQ,IAAI,eAAe,MAAM,UAAU,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IAChE;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,aAAa;AACzB,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,UAAU,SAAS;AAC5B,YAAM,MAAM,SAAS,KAAK,OAAO,QAAQ;AACzC,cAAQ,IAAI,8BAA8B,OAAO,WAAW,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IACjF;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,SAAS,UAAU;AAC5B,YAAM,MAAM,SAAS,KAAK,MAAM,QAAQ;AACxC,cAAQ,IAAI,eAAe,MAAM,OAAO,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IAC7D;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,WAAc,UAAU;AAAA,CAAc;AACpD;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/routes.ts"],"sourcesContent":["import { resolve, relative } from 'node:path'\n\nimport { loadConfig } from '../../config/load-config.js'\nimport { validateProjectStructure } from '../../config/validate-structure.js'\nimport { scanServerActions } from '../../server/scan/action-scan.js'\nimport { scanServerRoutes } from '../../server/scan/scan.js'\nimport { scanWebSocketRoutes } from '../../server/scan/ws-scan.js'\n\nexport async function routesCommand(): Promise<void> {\n const cwd = process.cwd()\n const config = await loadConfig(cwd)\n validateProjectStructure(cwd)\n\n const serverDir = resolve(cwd, config.serverDir)\n\n const apiRoutes = scanServerRoutes(serverDir)\n const actions = scanServerActions(serverDir)\n const wsRoutes = scanWebSocketRoutes(serverDir)\n\n const totalCount = apiRoutes.length + actions.length + wsRoutes.length\n\n if (totalCount === 0) {\n console.log('\\n No routes found.\\n')\n return\n }\n\n // API Routes\n if (apiRoutes.length > 0) {\n console.log('\\n API Routes')\n console.log(' ' + '─'.repeat(60))\n for (const route of apiRoutes) {\n const rel = relative(cwd, route.filePath)\n console.log(` GET/POST ${route.routePath.padEnd(30)} ${rel}`)\n }\n }\n\n // Actions\n if (actions.length > 0) {\n console.log('\\n Actions')\n console.log(' ' + '─'.repeat(60))\n for (const action of actions) {\n const rel = relative(cwd, action.filePath)\n console.log(` POST /api/__actions/${action.actionPath.padEnd(18)} ${rel}`)\n }\n }\n\n // WebSocket\n if (wsRoutes.length > 0) {\n console.log('\\n WebSocket')\n console.log(' ' + '─'.repeat(60))\n for (const route of wsRoutes) {\n const rel = relative(cwd, route.filePath)\n console.log(` WS ${route.wsPath.padEnd(30)} ${rel}`)\n }\n }\n\n console.log(`\\n Total: ${totalCount} endpoints\\n`)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS,gBAAgB;AAQlC,eAAsB,gBAA+B;AACnD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,WAAW,GAAG;AACnC,2BAAyB,GAAG;AAE5B,QAAM,YAAY,QAAQ,KAAK,OAAO,SAAS;AAE/C,QAAM,YAAY,iBAAiB,SAAS;AAC5C,QAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAM,WAAW,oBAAoB,SAAS;AAE9C,QAAM,aAAa,UAAU,SAAS,QAAQ,SAAS,SAAS;AAEhE,MAAI,eAAe,GAAG;AACpB,YAAQ,IAAI,wBAAwB;AACpC;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,GAAG;AACxB,YAAQ,IAAI,gBAAgB;AAC5B,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,SAAS,WAAW;AAC7B,YAAM,MAAM,SAAS,KAAK,MAAM,QAAQ;AACxC,cAAQ,IAAI,eAAe,MAAM,UAAU,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IAChE;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,IAAI,aAAa;AACzB,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,UAAU,SAAS;AAC5B,YAAM,MAAM,SAAS,KAAK,OAAO,QAAQ;AACzC,cAAQ,IAAI,8BAA8B,OAAO,WAAW,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IACjF;AAAA,EACF;AAGA,MAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC;AACjC,eAAW,SAAS,UAAU;AAC5B,YAAM,MAAM,SAAS,KAAK,MAAM,QAAQ;AACxC,cAAQ,IAAI,eAAe,MAAM,OAAO,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;AAAA,IAC7D;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,WAAc,UAAU;AAAA,CAAc;AACpD;","names":[]}
@@ -4,16 +4,23 @@ import {
4
4
  preflightNodeAndBindings
5
5
  } from "./chunk-HNBWZKIQ.js";
6
6
  import {
7
+ handleAgentApproval,
7
8
  incomingMessageToWebRequest,
9
+ isApprovalPath,
8
10
  mountAgent,
9
- resolveProvider,
10
11
  resolveTransformer,
11
12
  writeWebResponseToServerResponse
12
- } from "./chunk-S7Y5WLZY.js";
13
+ } from "./chunk-OTFIRP6S.js";
14
+ import {
15
+ getApprovalRegistry,
16
+ resolveProvider
17
+ } from "./chunk-NBWB4S46.js";
18
+ import {
19
+ loadConfig
20
+ } from "./chunk-567NA7Y6.js";
13
21
  import {
14
- loadConfig,
15
22
  loadEnv
16
- } from "./chunk-7YZHAQU7.js";
23
+ } from "./chunk-GDN3PXFH.js";
17
24
  import "./chunk-YJAUJXZS.js";
18
25
  import "./chunk-45C3WUQ7.js";
19
26
  import {
@@ -30,15 +37,18 @@ import {
30
37
  warnOnce
31
38
  } from "./chunk-WR4F4EEZ.js";
32
39
  import {
33
- loadManifest,
40
+ loadManifest
41
+ } from "./chunk-NXTF5PPW.js";
42
+ import {
34
43
  scanAgents
35
- } from "./chunk-F4YUPDJ2.js";
44
+ } from "./chunk-34YQOXGM.js";
36
45
  import {
37
46
  matchRoute,
38
47
  scanServerActions,
39
48
  scanServerRoutes,
40
49
  scanWebSocketRoutes
41
- } from "./chunk-BQDGES7C.js";
50
+ } from "./chunk-GBXLKYIA.js";
51
+ import "./chunk-P37RZRFV.js";
42
52
  import "./chunk-HGZL5EOI.js";
43
53
 
44
54
  // src/cli/commands/start/index.ts
@@ -337,6 +347,56 @@ async function tryServeAction(c) {
337
347
  async function tryServeAgent(c) {
338
348
  if (!c.url.startsWith("/api/agents/")) return false;
339
349
  const urlPath = c.url.split("?")[0];
350
+ if (isApprovalPath(urlPath)) {
351
+ c.res.setHeader("x-request-id", c.requestId);
352
+ if (applyRateLimit(c, c.req.method ?? "POST")) return true;
353
+ const method2 = (c.req.method ?? "POST").toUpperCase();
354
+ if (method2 !== "POST") {
355
+ sendError(
356
+ c.res,
357
+ "METHOD_NOT_ALLOWED",
358
+ "Approve endpoints accept POST",
359
+ 405,
360
+ void 0,
361
+ c.requestId
362
+ );
363
+ logRequest({
364
+ method: method2,
365
+ url: c.url,
366
+ status: 405,
367
+ duration: Date.now() - c.startTime,
368
+ requestId: c.requestId
369
+ });
370
+ return true;
371
+ }
372
+ try {
373
+ const request = incomingMessageToWebRequest(c.req);
374
+ const response = await handleAgentApproval(
375
+ request,
376
+ urlPath,
377
+ getApprovalRegistry(),
378
+ c.csrfMode
379
+ );
380
+ await writeWebResponseToServerResponse(response, c.res);
381
+ } catch (err) {
382
+ sendError(
383
+ c.res,
384
+ "INTERNAL",
385
+ err instanceof Error ? err.message : "Approve handler failed",
386
+ 500,
387
+ void 0,
388
+ c.requestId
389
+ );
390
+ }
391
+ logRequest({
392
+ method: method2,
393
+ url: c.url,
394
+ status: c.res.statusCode,
395
+ duration: Date.now() - c.startTime,
396
+ requestId: c.requestId
397
+ });
398
+ return true;
399
+ }
340
400
  const agent = c.cachedAgents.find((a) => a.agentPath === urlPath);
341
401
  if (!agent) return false;
342
402
  c.res.setHeader("x-request-id", c.requestId);
@@ -734,4 +794,4 @@ export {
734
794
  resolveSsrEntry,
735
795
  startCommand
736
796
  };
737
- //# sourceMappingURL=start-2KG4JSXM.js.map
797
+ //# sourceMappingURL=start-7MQEEQH4.js.map