theokit 0.15.2 → 0.17.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 (100) hide show
  1. package/dist/actions-virtual-module-G4BANOLW.js +0 -0
  2. package/dist/add-W6FNTAFS.js +0 -0
  3. package/dist/{agent-MN7XGJR3.js → agent-7DBAK65H.js} +3 -3
  4. package/dist/{agents-typed-client-SAWAAH7K.js → agents-typed-client-D3LXWGCF.js} +6 -4
  5. package/dist/agents-typed-client-D3LXWGCF.js.map +1 -0
  6. package/dist/{agents-typed-client-UTEQUA63.js → agents-typed-client-LQ36PCHL.js} +6 -4
  7. package/dist/agents-typed-client-LQ36PCHL.js.map +1 -0
  8. package/dist/app-typed-client-Z6BHD4MF.js +0 -0
  9. package/dist/aws-lambda-7GSCNLPY.js +0 -0
  10. package/dist/body-parser-web-FV5HWCY3.js +0 -0
  11. package/dist/broadcast-LUMOJIJT.js +0 -0
  12. package/dist/{build-QDAFSKKW.js → build-MTI4RAI3.js} +2 -2
  13. package/dist/build-request-body-preview-QMWD2IXK.js +0 -0
  14. package/dist/bun-KP2KES6S.js +0 -0
  15. package/dist/check-PD2FTKMM.js +0 -0
  16. package/dist/chunk-34YQOXGM.js +0 -0
  17. package/dist/{chunk-5UUOGAJH.js → chunk-3FNZG6Q3.js} +36 -1
  18. package/dist/chunk-3FNZG6Q3.js.map +1 -0
  19. package/dist/chunk-45C3WUQ7.js +0 -0
  20. package/dist/{chunk-ZJDKAD3L.js → chunk-4FOPDXKT.js} +270 -37
  21. package/dist/chunk-4FOPDXKT.js.map +1 -0
  22. package/dist/{chunk-OTFIRP6S.js → chunk-4JDYVNSY.js} +28 -6
  23. package/dist/chunk-4JDYVNSY.js.map +1 -0
  24. package/dist/chunk-567NA7Y6.js +0 -0
  25. package/dist/chunk-5ODOE6EF.js +0 -0
  26. package/dist/{chunk-KGFNWIMS.js → chunk-CWVBDUDC.js} +18 -4
  27. package/dist/chunk-CWVBDUDC.js.map +1 -0
  28. package/dist/chunk-FOZIR3TG.js +0 -0
  29. package/dist/chunk-GBXLKYIA.js +0 -0
  30. package/dist/chunk-GDN3PXFH.js +0 -0
  31. package/dist/chunk-HGZL5EOI.js +0 -0
  32. package/dist/chunk-HNBWZKIQ.js +0 -0
  33. package/dist/chunk-IEES3CHD.js +0 -0
  34. package/dist/chunk-JAIKGP3Q.js +0 -0
  35. package/dist/chunk-JQSFBJR5.js +0 -0
  36. package/dist/chunk-KXA37ONC.js +0 -0
  37. package/dist/{chunk-NBWB4S46.js → chunk-M6NMS5LR.js} +17 -7
  38. package/dist/{chunk-NBWB4S46.js.map → chunk-M6NMS5LR.js.map} +1 -1
  39. package/dist/chunk-NXTF5PPW.js +0 -0
  40. package/dist/chunk-P37RZRFV.js +0 -0
  41. package/dist/chunk-WR4F4EEZ.js +0 -0
  42. package/dist/{chunk-UOR6JTCI.js → chunk-X6COGWHN.js} +296 -48
  43. package/dist/chunk-X6COGWHN.js.map +1 -0
  44. package/dist/chunk-YJAUJXZS.js +0 -0
  45. package/dist/cli/index.js +4 -4
  46. package/dist/client/index.d.ts +59 -2
  47. package/dist/client/index.js +43 -0
  48. package/dist/client/index.js.map +1 -1
  49. package/dist/cloudflare-C6E5SPAE.js +0 -0
  50. package/dist/configure-agent-registry-ZOBVU3MV.js +0 -0
  51. package/dist/db-3UNAMSFK.js +0 -0
  52. package/dist/deno-deploy-RFZN56X4.js +0 -0
  53. package/dist/{dev-TEE4T6ZB.js → dev-SVHKR2VR.js} +4 -4
  54. package/dist/dev-emit-VJ5CFMPY.js +0 -0
  55. package/dist/dispatcher-EJHL6JMJ.js +0 -0
  56. package/dist/docker-LZZB4D5E.js +0 -0
  57. package/dist/generate-OMKHQ7OM.js +0 -0
  58. package/dist/index.js +2 -2
  59. package/dist/info-7PE2PZJI.js +0 -0
  60. package/dist/internal-api-J27TYE2I.js +0 -0
  61. package/dist/load-config-JKYO5RFK.js +0 -0
  62. package/dist/netlify-PMLHVPN4.js +0 -0
  63. package/dist/node-BPJ3Z4DT.js +0 -0
  64. package/dist/openapi-MXMLZCXC.js +0 -0
  65. package/dist/registry-XJUYD2OU.js +0 -0
  66. package/dist/router-TLEAOFID.js +0 -0
  67. package/dist/routes-NNBEZSGN.js +0 -0
  68. package/dist/scan-7MJC6PYU.js +0 -0
  69. package/dist/schema-7CAY6IZR.js +0 -0
  70. package/dist/server/define/index.d.ts +42 -6
  71. package/dist/server/define/index.js +3 -1
  72. package/dist/server/index.d.ts +278 -4
  73. package/dist/server/index.js +232 -2
  74. package/dist/server/index.js.map +1 -1
  75. package/dist/server-error-to-envelope-UUXDSLAZ.js +0 -0
  76. package/dist/server-routes-hmr-VZXOP5YT.js +0 -0
  77. package/dist/services-json-Y3XODNB5.js +0 -0
  78. package/dist/services-typed-client-32KMTTXR.js +0 -0
  79. package/dist/{start-7MQEEQH4.js → start-SDZTFJNQ.js} +3 -3
  80. package/dist/static-7ARBVDJF.js +0 -0
  81. package/dist/storage-manager-ZSQFLEYT.js +0 -0
  82. package/dist/theo-cloud-DQRP6S6M.js +0 -0
  83. package/dist/upgrade-readiness-ACGW44JC.js +0 -0
  84. package/dist/vercel-J6G7ZHYQ.js +0 -0
  85. package/dist/vite-plugin/index.js +2 -2
  86. package/dist/{vite-plugin-GC6WCU4P.js → vite-plugin-ZZYTMWZY.js} +4 -4
  87. package/package.json +12 -11
  88. package/LICENSE +0 -201
  89. package/dist/agents-typed-client-SAWAAH7K.js.map +0 -1
  90. package/dist/agents-typed-client-UTEQUA63.js.map +0 -1
  91. package/dist/chunk-5UUOGAJH.js.map +0 -1
  92. package/dist/chunk-KGFNWIMS.js.map +0 -1
  93. package/dist/chunk-OTFIRP6S.js.map +0 -1
  94. package/dist/chunk-UOR6JTCI.js.map +0 -1
  95. package/dist/chunk-ZJDKAD3L.js.map +0 -1
  96. /package/dist/{agent-MN7XGJR3.js.map → agent-7DBAK65H.js.map} +0 -0
  97. /package/dist/{build-QDAFSKKW.js.map → build-MTI4RAI3.js.map} +0 -0
  98. /package/dist/{dev-TEE4T6ZB.js.map → dev-SVHKR2VR.js.map} +0 -0
  99. /package/dist/{start-7MQEEQH4.js.map → start-SDZTFJNQ.js.map} +0 -0
  100. /package/dist/{vite-plugin-GC6WCU4P.js.map → vite-plugin-ZZYTMWZY.js.map} +0 -0
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "theokit",
3
- "version": "0.15.2",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "Apache-2.0",
7
+ "scripts": {
8
+ "build": "tsup",
9
+ "test": "echo 'theokit tests run from root: pnpm test'"
10
+ },
7
11
  "bin": {
8
12
  "theokit": "./dist/cli/index.js"
9
13
  },
@@ -101,6 +105,8 @@
101
105
  "dist"
102
106
  ],
103
107
  "dependencies": {
108
+ "@theokit/agents": "workspace:^",
109
+ "@theokit/http": "workspace:^",
104
110
  "@vitejs/plugin-react": "^4.7.0",
105
111
  "busboy": "^1.6.0",
106
112
  "cac": "^6.7.14",
@@ -114,12 +120,10 @@
114
120
  "superjson": "^2.2.6",
115
121
  "tsx": "^4.22.4",
116
122
  "typescript": "^5.9.3",
117
- "vite": "^6.4.3",
118
- "@theokit/agents": "^0.30.1",
119
- "@theokit/http": "^0.5.4"
123
+ "vite": "^6.4.3"
120
124
  },
121
125
  "peerDependencies": {
122
- "@theokit/sdk": ">=2.9.0",
126
+ "@theokit/sdk": ">=2.20.0",
123
127
  "@theokit/ui": "^0.14.0 || ^0.18.0 || ^0.19.0 || ^1.0.0",
124
128
  "ai": ">=7.0.0",
125
129
  "db0": "^0.3.0",
@@ -151,7 +155,7 @@
151
155
  }
152
156
  },
153
157
  "devDependencies": {
154
- "@theokit/sdk": "^2.13.0",
158
+ "@theokit/sdk": "^2.20.0",
155
159
  "@types/busboy": "^1.5.4",
156
160
  "ai": "^7.0.14",
157
161
  "@types/pg": "^8.20.0",
@@ -163,13 +167,10 @@
163
167
  "unstorage": "^1.17.5"
164
168
  },
165
169
  "publishConfig": {
170
+ "provenance": false,
166
171
  "access": "public"
167
172
  },
168
173
  "engines": {
169
174
  "node": ">=22.12.0"
170
- },
171
- "scripts": {
172
- "build": "tsup",
173
- "test": "echo 'theokit tests run from root: pnpm test'"
174
175
  }
175
- }
176
+ }
package/LICENSE DELETED
@@ -1,201 +0,0 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for describing the origin of the Work and
141
- reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright 2026 usetheo.dev
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/vite-plugin/agents-typed-client.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Codegen-time fs ops: all paths derive from `opts.projectRoot` / `opts.distDir`\n * (vite plugin opts — trusted, set by the framework's CLI). Never serves HTTP input.\n */\n/**\n * M2 (theokit-ai-first) — end-to-end typed binding for the `agents/*.ts` convention.\n *\n * Sibling of `app-typed-client.ts` (kept separate so the `@theo/client` output stays\n * byte-unchanged). Two parts:\n *\n * 1. `generateAgentsDts({ manifest, dtsOutPath, projectRoot })` — pure function emitting\n * `.theokit/agents.d.ts` (the virtual `@theo/agents` module) with `AppAgents` mapping\n * each scanned agent to `InferAgentInput` of its `defineAgent({ input })` schema, plus a\n * typed `useAgent` signature — so the client binds to `/api/agents/<name>` with the right\n * request type and ZERO manual wiring (DoD line 2).\n * 2. `agentsTypedClientPlugin(opts)` — Vite plugin that emits (1), rewrites on `agents/*`\n * changes, and serves the virtual `@theo/agents` runtime (`useAgent` from `theokit/client`).\n */\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, posix } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport type { TheoManifest } from '../server/internal-api.js'\n\nconst FILE_HEADER = `// AUTO-GENERATED by theokit — do not edit.\n// Source: theokit/packages/theo/src/vite-plugin/agents-typed-client.ts (M2).\n// To refresh: \\`pnpm dev\\` or \\`pnpm build\\` regenerates this on every agents/ change.\n\n/* eslint-disable */\n`\n\n/** A safe TS identifier alias for an agent (name may contain path separators). */\nfunction aliasFor(name: string): string {\n return `_agent_${name.replace(/[^\\w$]/g, '_')}`\n}\n\n/** Relative `import type` path from the .d.ts dir to the agent source (extension stripped). */\nfunction importPath(dtsOutPath: string, projectRoot: string, filePath: string): string {\n const fromDir = dirname(dtsOutPath).replace(/\\\\/g, '/')\n const abs = posix.join(projectRoot.replace(/\\\\/g, '/'), filePath.replace(/\\\\/g, '/'))\n const noExt = abs.replace(/\\.[jt]sx?$/, '')\n let rel = posix.relative(fromDir, noExt)\n if (!rel.startsWith('.')) rel = `./${rel}`\n return rel\n}\n\nexport interface GenerateAgentsDtsOptions {\n manifest: TheoManifest\n /** Absolute path to the .d.ts that will be emitted (drives the import paths). */\n dtsOutPath: string\n /** Absolute project root — agents live at `<projectRoot>/agents`. */\n projectRoot: string\n}\n\nexport function generateAgentsDts({\n manifest,\n dtsOutPath,\n projectRoot,\n}: GenerateAgentsDtsOptions): string {\n const agents = manifest.agents ?? []\n const imports: string[] = []\n const entries: string[] = []\n for (const agent of agents) {\n const alias = aliasFor(agent.name)\n imports.push(\n ` import type ${alias} from '${importPath(dtsOutPath, projectRoot, agent.filePath)}'`,\n )\n entries.push(` '${agent.name}': { input: InferAgentInput<${alias}> }`)\n }\n\n const body =\n entries.length > 0\n ? `{\\n${entries.join('\\n')}\\n }`\n : `{\\n // No agents detected — add \\`agents/*.ts\\` to populate this binding.\\n }`\n\n const importBlock = imports.length > 0 ? `${imports.join('\\n')}\\n` : ''\n\n return `${FILE_HEADER}\ndeclare module '@theo/agents' {\n import type { InferAgentInput } from '@theokit/agents'\n import type { UseAgentReturn } from 'theokit/client'\n${importBlock}\n export interface AppAgents ${body}\n\n export function useAgent<K extends keyof AppAgents>(\n name: K,\n ): UseAgentReturn<AppAgents[K]['input']>\n}\n`\n}\n\n// ─── Vite plugin ─────────────────────────────────────────────────────────────\n\nconst VIRTUAL_AGENTS_ID = '@theo/agents'\nconst RESOLVED_AGENTS_ID = '\\0@theo/agents'\n\nexport interface AgentsTypedClientPluginOptions {\n /** Absolute project root (agents live at `<projectRoot>/agents`). */\n projectRoot: string\n /** Absolute `.theokit/` output dir (where `agents.d.ts` lands). */\n distDir: string\n /** Injects the scanned agents; returns the current manifest-shaped agent list. */\n scanManifest: (projectRoot: string) => TheoManifest\n}\n\n/** Atomic write via tmp + rename; skips when content is unchanged. */\nfunction writeIfChanged(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n try {\n if (readFileSync(filePath, 'utf-8') === content) return\n } catch {\n /* fall through to write */\n }\n }\n mkdirSync(dirname(filePath), { recursive: true })\n const tmp = `${filePath}.${process.pid}.tmp`\n writeFileSync(tmp, content)\n renameSync(tmp, filePath)\n}\n\nfunction emitAgentsDts(opts: AgentsTypedClientPluginOptions): string {\n const dtsOutPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'agents.d.ts')\n const content = generateAgentsDts({\n manifest: opts.scanManifest(opts.projectRoot),\n dtsOutPath,\n projectRoot: opts.projectRoot,\n })\n writeIfChanged(dtsOutPath, content)\n return dtsOutPath\n}\n\nexport function agentsTypedClientPlugin(opts: AgentsTypedClientPluginOptions): Plugin {\n let debounce: NodeJS.Timeout | undefined\n let viteServer: ViteDevServer | undefined\n\n const scheduleEmit = (): void => {\n if (debounce) clearTimeout(debounce)\n debounce = setTimeout(() => {\n try {\n emitAgentsDts(opts)\n if (viteServer) {\n const mod = viteServer.moduleGraph.getModuleById(RESOLVED_AGENTS_ID)\n if (mod) viteServer.moduleGraph.invalidateModule(mod)\n }\n } catch (err) {\n console.error('[theokit:agents-typed-client] codegen error:', err)\n }\n }, 100)\n }\n\n return {\n name: 'theokit:agents-typed-client',\n enforce: 'post',\n configResolved() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] initial codegen error:', err)\n }\n },\n buildEnd() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] buildEnd codegen error:', err)\n }\n },\n configureServer(server) {\n viteServer = server\n const agentsGlob = posix.join(opts.projectRoot.replace(/\\\\/g, '/'), 'agents')\n const onFile = (file: string): void => {\n if (file.replace(/\\\\/g, '/').startsWith(agentsGlob)) scheduleEmit()\n }\n server.watcher.on('add', onFile)\n server.watcher.on('change', onFile)\n server.watcher.on('unlink', onFile)\n },\n resolveId(id) {\n return id === VIRTUAL_AGENTS_ID ? RESOLVED_AGENTS_ID : null\n },\n load(id) {\n if (id === RESOLVED_AGENTS_ID) {\n return `export { useAgent } from 'theokit/client'\\n`\n }\n return null\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/vite-plugin/agents-typed-client.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Codegen-time fs ops: all paths derive from `opts.projectRoot` / `opts.distDir`\n * (vite plugin opts — trusted, set by the framework's CLI). Never serves HTTP input.\n */\n/**\n * M2 (theokit-ai-first) — end-to-end typed binding for the `agents/*.ts` convention.\n *\n * Sibling of `app-typed-client.ts` (kept separate so the `@theo/client` output stays\n * byte-unchanged). Two parts:\n *\n * 1. `generateAgentsDts({ manifest, dtsOutPath, projectRoot })` — pure function emitting\n * `.theokit/agents.d.ts` (the virtual `@theo/agents` module) with `AppAgents` mapping\n * each scanned agent to `InferAgentInput` of its `defineAgent({ input })` schema, plus a\n * typed `useAgent` signature — so the client binds to `/api/agents/<name>` with the right\n * request type and ZERO manual wiring (DoD line 2).\n * 2. `agentsTypedClientPlugin(opts)` — Vite plugin that emits (1), rewrites on `agents/*`\n * changes, and serves the virtual `@theo/agents` runtime (`useAgent` from `theokit/client`).\n */\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, posix } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport type { TheoManifest } from '../server/internal-api.js'\n\nconst FILE_HEADER = `// AUTO-GENERATED by theokit — do not edit.\n// Source: theokit/packages/theo/src/vite-plugin/agents-typed-client.ts (M2).\n// To refresh: \\`pnpm dev\\` or \\`pnpm build\\` regenerates this on every agents/ change.\n\n/* eslint-disable */\n`\n\n/** A safe TS identifier alias for an agent (name may contain path separators). */\nfunction aliasFor(name: string): string {\n return `_agent_${name.replace(/[^\\w$]/g, '_')}`\n}\n\n/** Relative `import type` path from the .d.ts dir to the agent source (extension stripped). */\nfunction importPath(dtsOutPath: string, projectRoot: string, filePath: string): string {\n const fromDir = dirname(dtsOutPath).replace(/\\\\/g, '/')\n const abs = posix.join(projectRoot.replace(/\\\\/g, '/'), filePath.replace(/\\\\/g, '/'))\n const noExt = abs.replace(/\\.[jt]sx?$/, '')\n let rel = posix.relative(fromDir, noExt)\n if (!rel.startsWith('.')) rel = `./${rel}`\n return rel\n}\n\nexport interface GenerateAgentsDtsOptions {\n manifest: TheoManifest\n /** Absolute path to the .d.ts that will be emitted (drives the import paths). */\n dtsOutPath: string\n /** Absolute project root — agents live at `<projectRoot>/agents`. */\n projectRoot: string\n}\n\nexport function generateAgentsDts({\n manifest,\n dtsOutPath,\n projectRoot,\n}: GenerateAgentsDtsOptions): string {\n const agents = manifest.agents ?? []\n const imports: string[] = []\n const entries: string[] = []\n for (const agent of agents) {\n const alias = aliasFor(agent.name)\n imports.push(\n ` import type ${alias} from '${importPath(dtsOutPath, projectRoot, agent.filePath)}'`,\n )\n entries.push(` '${agent.name}': { input: InferAgentInput<${alias}> }`)\n }\n\n const body =\n entries.length > 0\n ? `{\\n${entries.join('\\n')}\\n }`\n : `{\\n // No agents detected — add \\`agents/*.ts\\` to populate this binding.\\n }`\n\n const importBlock = imports.length > 0 ? `${imports.join('\\n')}\\n` : ''\n\n return `${FILE_HEADER}\ndeclare module '@theo/agents' {\n import type { InferAgentInput } from '@theokit/agents'\n import type { UseAgentReturn } from 'theokit/client'\n${importBlock}\n export interface AppAgents ${body}\n\n export function useAgent<K extends keyof AppAgents>(\n name: K,\n ): UseAgentReturn<AppAgents[K]['input']>\n}\n`\n}\n\n// ─── Vite plugin ─────────────────────────────────────────────────────────────\n\nconst VIRTUAL_AGENTS_ID = '@theo/agents'\nconst RESOLVED_AGENTS_ID = '\\0@theo/agents'\n\nexport interface AgentsTypedClientPluginOptions {\n /** Absolute project root (agents live at `<projectRoot>/agents`). */\n projectRoot: string\n /** Absolute `.theokit/` output dir (where `agents.d.ts` lands). */\n distDir: string\n /** Injects the scanned agents; returns the current manifest-shaped agent list. */\n scanManifest: (projectRoot: string) => TheoManifest\n}\n\n/** Atomic write via tmp + rename; skips when content is unchanged. */\nfunction writeIfChanged(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n try {\n if (readFileSync(filePath, 'utf-8') === content) return\n } catch {\n /* fall through to write */\n }\n }\n mkdirSync(dirname(filePath), { recursive: true })\n const tmp = `${filePath}.${process.pid}.tmp`\n writeFileSync(tmp, content)\n renameSync(tmp, filePath)\n}\n\nfunction emitAgentsDts(opts: AgentsTypedClientPluginOptions): string {\n const dtsOutPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'agents.d.ts')\n const content = generateAgentsDts({\n manifest: opts.scanManifest(opts.projectRoot),\n dtsOutPath,\n projectRoot: opts.projectRoot,\n })\n writeIfChanged(dtsOutPath, content)\n return dtsOutPath\n}\n\nexport function agentsTypedClientPlugin(opts: AgentsTypedClientPluginOptions): Plugin {\n let debounce: NodeJS.Timeout | undefined\n let viteServer: ViteDevServer | undefined\n\n const scheduleEmit = (): void => {\n if (debounce) clearTimeout(debounce)\n debounce = setTimeout(() => {\n try {\n emitAgentsDts(opts)\n if (viteServer) {\n const mod = viteServer.moduleGraph.getModuleById(RESOLVED_AGENTS_ID)\n if (mod) viteServer.moduleGraph.invalidateModule(mod)\n }\n } catch (err) {\n console.error('[theokit:agents-typed-client] codegen error:', err)\n }\n }, 100)\n }\n\n return {\n name: 'theokit:agents-typed-client',\n enforce: 'post',\n configResolved() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] initial codegen error:', err)\n }\n },\n buildEnd() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] buildEnd codegen error:', err)\n }\n },\n configureServer(server) {\n viteServer = server\n const agentsGlob = posix.join(opts.projectRoot.replace(/\\\\/g, '/'), 'agents')\n const onFile = (file: string): void => {\n if (file.replace(/\\\\/g, '/').startsWith(agentsGlob)) scheduleEmit()\n }\n server.watcher.on('add', onFile)\n server.watcher.on('change', onFile)\n server.watcher.on('unlink', onFile)\n },\n resolveId(id) {\n return id === VIRTUAL_AGENTS_ID ? RESOLVED_AGENTS_ID : null\n },\n load(id) {\n if (id === RESOLVED_AGENTS_ID) {\n return `export { useAgent } from 'theokit/client'\\n`\n }\n return null\n },\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/load-env.ts","../src/server/transformer.ts","../src/server/http/web-middleware-runner.ts","../src/server/web-handler.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Reads `.env` files from a CLI-controlled `cwd`. File names are a fixed\n * literal set. Build-time + CLI tool; no HTTP input.\n */\n/**\n * `loadEnv()` — auto-loads `.env` files into `process.env` for server code.\n *\n * Implements the Next.js `loadEnvConfig` algorithm\n * (`referencias/next.js/packages/next-env/index.ts:114-180`) with TheoKit\n * adaptations:\n *\n * - EC-1: 1MB file-size cap (anti-OOM, anti-supply-chain).\n * - EC-2: `_resetEnvCache()` test-only side-door.\n * - EC-8: `dotenv-expand` circular-ref safe (lib-provided).\n * - EC-13: log when `.env` is a symlink (transparency).\n * - D6: real `process.env` wins over `.env`-file values.\n * - NODE_ENV stash: `.env`-set NODE_ENV NEVER overrides the real\n * `process.env.NODE_ENV`. Stashed in `__THEOKIT_USER_NODE_ENV` instead.\n */\n\nimport { lstatSync, readFileSync, realpathSync, statSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport dotenv from 'dotenv'\nimport { expand, type DotenvPopulateInput } from 'dotenv-expand'\n\nimport type { LoadEnvOptions, LoadEnvResult } from './load-env-types.js'\n\n/** EC-1: 1MB cap. Real `.env`s are < 10KB. */\nconst MAX_ENV_FILE_BYTES = 1_048_576\n\nconst cache = new Map<string, LoadEnvResult>()\n\n/** Test-only side-door for EC-2 — clear the module-level cache between vitest test files. */\nexport function _resetEnvCache(): void {\n cache.clear()\n}\n\nfunction envFilesInPriorityOrder(mode: string): string[] {\n // Top of list = highest priority. Will be read in REVERSE so first-in\n // wins via overwrite during merge.\n const files = [`.env.${mode}.local`, `.env.local`, `.env.${mode}`, `.env`]\n // Test mode skips `.env.local` per dotenv convention (avoid leaking dev\n // secrets into the test suite).\n if (mode === 'test') {\n return files.filter((f) => f !== '.env.local')\n }\n return files\n}\n\nfunction readEnvFile(path: string): Record<string, string> | null {\n let stat\n try {\n stat = statSync(path)\n } catch {\n return null // ENOENT / EACCES → skip\n }\n\n // Allow files + FIFOs (1Password/SOPS pipe support).\n if (!stat.isFile() && !stat.isFIFO()) return null\n\n // EC-1 — anti-OOM cap.\n if (stat.size > MAX_ENV_FILE_BYTES) {\n console.warn(\n `[theokit] .env file at ${path} exceeds ${MAX_ENV_FILE_BYTES} bytes — skipping (likely a generated artifact, not a real env file)`,\n )\n return null\n }\n\n // EC-13 — symlink transparency. Don't refuse; just log.\n try {\n const lstat = lstatSync(path)\n if (lstat.isSymbolicLink()) {\n const real = realpathSync(path)\n // eslint-disable-next-line no-console -- intentional transparency log on a build-time tool\n console.info(`[theokit] .env at ${path} is a symlink → ${real}`)\n }\n } catch {\n // lstat failure is non-fatal — fall through to read.\n }\n\n try {\n const content = readFileSync(path, 'utf-8')\n return dotenv.parse(content)\n } catch {\n return null\n }\n}\n\n// eslint-disable-next-line complexity -- canonical env-load algorithm (priority → expand → guards → apply); inlining branches is clearer than extracting micro-helpers\nexport function loadEnv(options: LoadEnvOptions = {}): LoadEnvResult {\n const cwd = options.cwd ?? process.cwd()\n const mode = options.mode ?? process.env.NODE_ENV ?? 'development'\n const cacheKey = `${cwd}:${mode}`\n\n if (!options.forceReload) {\n const cached = cache.get(cacheKey)\n if (cached) return cached\n }\n\n const fileNames = envFilesInPriorityOrder(mode)\n const filePaths = fileNames.map((f) => resolve(cwd, f))\n\n // Read in REVERSE — lower-priority files first, so higher-priority\n // (lower-index) overwrites during merge.\n const merged: Record<string, string> = {}\n const loadedFromFiles: string[] = []\n for (const path of [...filePaths].reverse()) {\n const parsed = readEnvFile(path)\n if (parsed === null) continue\n for (const [k, v] of Object.entries(parsed)) {\n merged[k] = v\n }\n loadedFromFiles.unshift(path) // keep priority order in result\n }\n\n // NODE_ENV stash — `.env`-set NODE_ENV never overrides real process.env.NODE_ENV.\n if (merged.NODE_ENV && process.env.__THEOKIT_USER_NODE_ENV === undefined) {\n process.env.__THEOKIT_USER_NODE_ENV = merged.NODE_ENV\n }\n delete merged.NODE_ENV // never propagate\n\n // EC-8 — dotenv-expand@11 stack-overflows on circular refs (A=${B}, B=${A}).\n // Wrap in try/catch — on overflow, leave the parsed map untouched (literal\n // values survive). Tested via test_loadEnv_circular_expand_no_loop_EC8.\n // Pass a CLONE of process.env (string-only, filtered) so expand can\n // reference real env without mutating it.\n const processEnvClone: DotenvPopulateInput = {}\n for (const [k, v] of Object.entries(process.env)) {\n if (typeof v === 'string') processEnvClone[k] = v\n }\n try {\n expand({ parsed: merged, processEnv: processEnvClone })\n } catch (err) {\n if (err instanceof RangeError) {\n console.warn(\n `[theokit] .env expansion overflow (likely circular reference like A=\\${B}, B=\\${A}). Leaving values as literals.`,\n )\n } else {\n throw err\n }\n }\n\n // Apply: D6 — real process.env wins over file values.\n const loaded: Record<string, string> = {}\n for (const [k, v] of Object.entries(merged)) {\n if (process.env[k] !== undefined) continue // real env wins\n process.env[k] = v\n loaded[k] = v\n }\n\n // Sentinel\n process.env.__THEOKIT_PROCESSED_ENV = 'true'\n\n const result: LoadEnvResult = { loaded, loadedFromFiles }\n cache.set(cacheKey, result)\n return result\n}\n","import superjson from 'superjson'\n\n/**\n * T5.2 — pluggable response/request transformer.\n *\n * `superjson` is the default, preserving Date/Map/Set/BigInt/etc.\n * `json` is the lightweight option (plain JSON.stringify/parse).\n * Users can supply a custom object implementing this contract.\n */\nexport interface TheoTransformer {\n name: string\n serialize: (value: unknown) => string\n deserialize: (raw: string) => unknown\n}\n\nexport const superjsonTransformer: TheoTransformer = {\n name: 'superjson',\n serialize: (v) => JSON.stringify(superjson.serialize(v)),\n deserialize: (raw) => {\n const parsed = JSON.parse(raw) as Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize(parsed)\n },\n}\n\nexport const jsonTransformer: TheoTransformer = {\n name: 'json',\n serialize: (v) => JSON.stringify(v),\n deserialize: (raw) => JSON.parse(raw) as unknown,\n}\n\nconst BUILT_INS: Record<string, TheoTransformer> = {\n superjson: superjsonTransformer,\n json: jsonTransformer,\n}\n\nexport function resolveTransformer(\n selector: 'json' | 'superjson' | TheoTransformer,\n): TheoTransformer {\n if (typeof selector === 'string') {\n // selector is 'json' | 'superjson' literal — both keys exist in\n // BUILT_INS by construction. Type system guarantees a hit; we keep\n // a defensive fallback that the compiler cannot see is unreachable\n // at runtime, just in case someone adds a new literal to the union\n // but forgets to register the built-in.\n const built = BUILT_INS[selector]\n // Defensive: the public union ensures `built` is defined, but if a\n // future contributor extends the union without registering the impl,\n // the cast keeps the failure mode loud.\n if ((built as TheoTransformer | undefined) === undefined) {\n throw new Error(\n `Unknown transformer \"${selector}\". Built-in options: ${Object.keys(BUILT_INS).join(', ')}.`,\n )\n }\n return built\n }\n if (\n typeof selector !== 'object' ||\n typeof selector.serialize !== 'function' ||\n typeof selector.deserialize !== 'function'\n ) {\n throw new Error(\n `Custom transformer must have serialize and deserialize functions. Got: ${JSON.stringify(selector)}`,\n )\n }\n return selector\n}\n","/**\n * T3.2 — Web-Standards middleware runner for the `executeWebRequest` path.\n *\n * The Node request path (`http/execute.ts`) runs middleware via\n * `runMiddlewareAndContext`, which is coupled to Node `req`/`res`. Per G8\n * (Web Standards over Node APIs) the Web path needs a `Request`-shaped runner;\n * this is it. Extracted to a sibling so `web-handler.ts` stays under its LoC\n * budget (G6).\n *\n * Ordering invariant (EC-3): the caller runs the CSRF gate BEFORE invoking this\n * runner, mirroring the Node path (CSRF stage precedes user middleware).\n *\n * NOTE (D4 / EC-12): this is its own middleware contract — `(request, context)`.\n * Full semantic parity with the Node `defineMiddleware` contract is part of the\n * deferred Node→Web pipeline convergence, not this slice.\n */\n\n/** A Web-path middleware: mutate `context`, or return a `Response` to short-circuit. */\nexport type WebMiddleware = (\n request: Request,\n context: Record<string, unknown>,\n // A middleware may mutate `context` and return nothing (void) OR return a\n // `Response` to short-circuit (Express/Koa-style). `void` in this union is\n // intentional — `runWebMiddleware` only inspects `instanceof Response`, so a\n // void return means \"continue to the next middleware / handler\".\n // eslint-disable-next-line @typescript-eslint/no-invalid-void-type\n) => Promise<Response | undefined> | Response | undefined | void\n\n/**\n * Run middleware in order against a shared mutable `context`. The first\n * middleware that returns a `Response` short-circuits the chain (the handler\n * is not reached); its `Response` is returned verbatim so headers like\n * `Set-Cookie` are preserved (EC-11). Returns `undefined` when every\n * middleware passes (the handler should run next).\n */\nexport async function runWebMiddleware(\n request: Request,\n middleware: readonly WebMiddleware[],\n context: Record<string, unknown>,\n): Promise<Response | undefined> {\n for (const mw of middleware) {\n const result = await mw(request, context)\n if (result instanceof Response) return result\n }\n return undefined\n}\n","/**\n * T5a.2 Phase A — Foundation: Web-Standards request handler entry-point.\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase A. Bridges the gap between Web `Request`/`Response` and the\n * existing `defineRoute` config shape (which is consumed today by the Node-\n * shaped `executeRoute`).\n *\n * This is the entry-point T1.2 RED tests expect:\n * `executeWebRequest(request: Request, routeModule: { GET?, POST?, ... }): Promise<Response>`\n *\n * Architecture per ADR-0028 (R3a) — this function accepts a native Web\n * `Request` and returns a native Web `Response`. No `node:*` is required in\n * the implementation (Zod + native Headers/URL/Response cover the surface).\n *\n * **Scope (intentionally narrow):**\n * - Method dispatch (GET/POST/PUT/PATCH/DELETE).\n * - Zod validation for `query` (from URL.searchParams), `body` (from\n * request.json() OR request.text()), `params` (consumer-supplied OR\n * parsed from path).\n * - Handler invocation.\n * - Result → JSON Response (200 default, 204 for void return).\n * - Error → envelope-shaped JSON Response (400 for validation, 500 for\n * handler throws) per G5 boundary translation (serverErrorToEnvelope).\n *\n * **NOT included (deferred to T5a.2 Phase B-G):**\n * - Plugin runner integration (onRequest/preHandler/onResponse hooks).\n * - CSRF / CORS / security headers / rate limiting / cookies / auth.\n * - Middleware chain. SSR rendering. WebSocket upgrade. File upload.\n * - File-system routing scan; consumer provides the route module\n * explicitly (Web Request entry doesn't yet know about scan results).\n *\n * The narrow scope makes this a viable Phase A landing zone — turns the\n * 7 T1.2 RED tests GREEN without prematurely refactoring the full\n * IncomingMessage→Request boundary across server/http/ files.\n */\nimport type { z } from 'zod'\n\nimport { envelopeCodeToStatus } from '../core/contracts/envelope-code-to-status.js'\nimport type { TheoErrorEnvelope } from '../core/contracts/error-envelope.js'\nimport { serverErrorToEnvelope } from '../core/contracts/server-error-to-envelope.js'\nimport { TheoError } from '../core/contracts/theo-error.js'\n\nimport { isZodLike } from './http/execute-stages.js'\nimport { runWebMiddleware, type WebMiddleware } from './http/web-middleware-runner.js'\nimport type {\n WebOnErrorHook,\n WebOnRequestHook,\n WebOnResponseHook,\n WebPluginContext,\n WebPluginErrorContext,\n WebPreHandlerHook,\n} from './plugin-types.js'\nimport { validateCsrfRequest } from './security/csrf.js'\n\nexport type { WebMiddleware }\n\n/**\n * Minimal structural type for a `defineRoute` config. Mirrors\n * `core/contracts/route-config.ts` shape but only the fields this entry\n * point needs at runtime (Zod schemas + handler). Kept structural to\n * avoid a hard dep on the full RouteConfig generic chain.\n */\ninterface WebRouteHandlerConfig {\n query?: z.ZodType\n body?: z.ZodType\n params?: z.ZodType\n /** Optional Zod schema validating a plain-object handler return (D1/D2). */\n response?: z.ZodType\n /** Honored for plain-object returns to match the Node runner (D3). */\n status?: number\n handler: (ctx: {\n query: unknown\n body: unknown\n params: unknown\n request: Request\n /** Mutable per-request context populated by the Web middleware chain (T3.2). */\n context: Record<string, unknown>\n }) => unknown\n}\n\n/**\n * The route module exported by a `server/routes/*.ts` file (after T2.6 G6\n * router lockdown). Method-named exports map to `defineRoute` results.\n */\ntype WebRouteModule = Partial<Record<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', unknown>>\n\n/**\n * Coerce URL.searchParams into a plain `{ key: value }` object so Zod\n * `z.object({...})` schemas work without per-route adapters. Repeated keys\n * become arrays (most browsers serialize multi-select that way).\n */\nfunction searchParamsToObject(params: URLSearchParams): Record<string, string | string[]> {\n const out: Record<string, string | string[]> = {}\n for (const [key, value] of params.entries()) {\n if (!Object.hasOwn(out, key)) {\n out[key] = value\n continue\n }\n const existing = out[key]\n if (Array.isArray(existing)) {\n existing.push(value)\n } else {\n out[key] = [existing, value]\n }\n }\n return out\n}\n\n/**\n * Parse request body based on Content-Type. JSON is the canonical path;\n * empty body returns `undefined` (the handler treats as \"no body\").\n *\n * **Inline-only mode (default):** handles `application/json` and `text/*`.\n * Other content-types return `undefined`. Multipart/form-data requires\n * the opt-in `bodyParser: 'full'` mode (T5a.2 Phase E).\n */\nasync function parseBodyInline(request: Request): Promise<unknown> {\n // GET/HEAD have no body by spec; even if the consumer sets one, ignore it\n // (matches Web Request semantics — `body` is null for GET/HEAD anyway).\n if (request.method === 'GET' || request.method === 'HEAD') return undefined\n const contentType = request.headers.get('content-type') ?? ''\n if (contentType.includes('application/json')) {\n const text = await request.text()\n if (text.length === 0) return undefined\n try {\n return JSON.parse(text)\n } catch {\n // Malformed JSON — return undefined; Zod schema (if any) will fail with\n // a more useful \"required\" message than a raw SyntaxError.\n return undefined\n }\n }\n // text/plain or no body: return raw text or undefined\n if (contentType.startsWith('text/')) {\n const text = await request.text()\n return text.length === 0 ? undefined : text\n }\n return undefined\n}\n\n/**\n * T5a.2 Phase E — \"full\" body parser delegating to `parseWebRequestBody`.\n * Returns a `ParsedWebBody` (`{ json?, fields, files }`) for JSON OR\n * multipart, or `undefined` when the body is empty / unparseable.\n *\n * Handler downstream pattern:\n * `body?.json` (JSON requests)\n * `body?.fields` + `body?.files` (multipart upload requests)\n *\n * Limits enforced by parseWebRequestBody:\n * - declared Content-Length cap (default 10MB × maxFiles + 1MB margin)\n * - per-file size cap (default 10MB)\n * - max files (default 10)\n */\nasync function parseBodyFull(request: Request): Promise<unknown> {\n if (request.method === 'GET' || request.method === 'HEAD') return undefined\n const { parseWebRequestBody } = await import('./body-parser-web.js')\n try {\n const parsed = await parseWebRequestBody(request)\n // If nothing parsed (empty body OR unhandled content-type), return undefined\n // so Zod schemas treat it as missing — same semantics as inline parser.\n if (\n parsed.json === undefined &&\n Object.keys(parsed.fields).length === 0 &&\n parsed.files.length === 0\n ) {\n return undefined\n }\n return parsed\n } catch {\n return undefined\n }\n}\n\n/**\n * Build an envelope-shaped 400 Response for a Zod validation failure. Uses\n * the canonical `TheoErrorEnvelope` shape per G5 D3 (boundary translation).\n */\nfunction validationErrorResponse(zodError: z.ZodError, field: string): Response {\n const envelope: TheoErrorEnvelope = {\n code: 'BAD_REQUEST',\n message: `Validation failed: ${field}`,\n ext: {\n fields: zodError.issues.map((issue) => ({\n path: issue.path.join('.'),\n message: issue.message,\n })),\n },\n }\n return new Response(JSON.stringify(envelope), {\n status: 400,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/**\n * Run a `defineRoute` config against a parsed Web Request. Returns the raw\n * handler result; serialization to Response happens in the caller.\n *\n * Throws if Zod validation fails (caller catches and emits 400).\n */\nasync function runHandler(\n config: WebRouteHandlerConfig,\n request: Request,\n bodyParser: 'inline' | 'full' = 'inline',\n paramsInput: Record<string, string> = {},\n context: Record<string, unknown> = {},\n): Promise<{ ok: true; result: unknown } | { ok: false; response: Response }> {\n const url = new URL(request.url)\n const queryRaw = searchParamsToObject(url.searchParams)\n const bodyRaw =\n bodyParser === 'full' ? await parseBodyFull(request) : await parseBodyInline(request)\n // T3.1 — route params resolved upstream (matchRoute) and threaded via\n // opts.params. Defaults to `{}` so callers that don't supply params keep the\n // prior behavior (a route declaring config.params then fails validation).\n const paramsRaw = paramsInput\n\n // Validate input via Zod schemas when present.\n let query: unknown = queryRaw\n if (config.query !== undefined) {\n const parsed = config.query.safeParse(queryRaw)\n if (!parsed.success)\n return { ok: false, response: validationErrorResponse(parsed.error, 'query') }\n query = parsed.data\n }\n let body: unknown = bodyRaw\n if (config.body !== undefined) {\n const parsed = config.body.safeParse(bodyRaw)\n if (!parsed.success)\n return { ok: false, response: validationErrorResponse(parsed.error, 'body') }\n body = parsed.data\n }\n let params: unknown = paramsRaw\n if (config.params !== undefined) {\n const parsed = config.params.safeParse(paramsRaw)\n if (!parsed.success)\n return { ok: false, response: validationErrorResponse(parsed.error, 'params') }\n params = parsed.data\n }\n\n const result = await config.handler({ query, body, params, request, context })\n return validateResponseOutput(config.response, result) ?? { ok: true, result }\n}\n\n/**\n * Validate a plain-object handler return against `config.response` (D1/D2). A\n * mismatch is a SERVER fault → 500 envelope. `Response`-instance returns and\n * `undefined`/`null` (→ 204) skip validation — parity with the Node runner,\n * which validates only in its plain-object branch. Returns `undefined` when no\n * validation applies (caller forwards the raw result).\n */\nfunction validateResponseOutput(\n response: unknown,\n result: unknown,\n): { ok: true; result: unknown } | { ok: false; response: Response } | undefined {\n const validatable = result !== undefined && result !== null && !(result instanceof Response)\n if (!validatable || !isZodLike(response)) return undefined\n const parsed = response.safeParse(result)\n if (parsed.success) return { ok: true, result: parsed.data }\n const err = new TheoError({\n code: 'INTERNAL_SERVER_ERROR',\n message: 'response validation failed',\n ext: { issues: parsed.error?.issues },\n })\n return { ok: false, response: handlerErrorResponse(err) }\n}\n\n/**\n * Serialize a handler return value into a native Web `Response`. Conventions:\n * - `undefined` / `void` → 204 No Content.\n * - existing `Response` instance → pass through unchanged.\n * - everything else → 200 JSON.\n */\nfunction toResponse(result: unknown, status?: number): Response {\n if (result === undefined) {\n return new Response(null, { status: 204 })\n }\n if (result instanceof Response) {\n return result\n }\n return new Response(JSON.stringify(result), {\n status: status ?? 200,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/**\n * Build an envelope-shaped 500 Response when a handler throws. Uses\n * `serverErrorToEnvelope` so existing ad-hoc Error classes (AuthRequired,\n * FileTooLarge, etc.) get mapped to canonical envelope codes.\n */\nfunction handlerErrorResponse(err: unknown): Response {\n const envelope = serverErrorToEnvelope(err)\n // Map envelope code → HTTP status when possible. Default to 500 for\n // INTERNAL_SERVER_ERROR. Other codes map per HTTP semantics.\n const status = envelopeCodeToStatus(envelope.code)\n return new Response(JSON.stringify(envelope), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// envelopeCodeToStatus extracted to core/contracts/envelope-code-to-status.ts\n// (architecture-remediation T1.2, 2026-06-12)\n\n/**\n * Optional behavior knobs for `executeWebRequest`. Each knob defaults to\n * the safe \"no-op\" stance so existing Phase A consumers (T1.2 fixture\n * tests) keep working unchanged.\n *\n * **`csrfMode`** (T5a.2 Phase B slice 1/6) — when set to `'strict'`, the\n * Web-Standards request gate runs `validateCsrfRequest` BEFORE method\n * dispatch on state-changing methods (POST/PUT/PATCH/DELETE) and emits a\n * `403 FORBIDDEN` envelope when the check fails. Default: `'off'` (no\n * CSRF enforcement) to preserve Phase A backward compat. Production\n * consumers SHOULD pass `csrfMode: 'strict'`.\n *\n * Per the T5a.2 plan v1.0 § Phase B header-only leaves: csrf.ts is the\n * first leaf to be migrated (slice 1/6); 5 more sibling leaves remain\n * (csrf-multi-header, csrf-readiness-endpoint, csp-report, cors, cookies).\n */\nexport interface ExecuteWebRequestOptions {\n csrfMode?: 'off' | 'strict'\n /**\n * T3.1 — route params resolved upstream by `matchRoute` (e.g. `{ id: '42' }`\n * for `/users/:id`). Threaded to the handler's `params` input and validated\n * against `config.params` (Zod) when declared. Defaults to `{}` — callers\n * that don't supply params keep the prior behavior (additive, backward-compat).\n */\n params?: Record<string, string>\n /**\n * T3.2 — Web-Standards middleware chain. Runs in order AFTER the CSRF gate\n * (EC-3) and BEFORE the handler. A middleware returning a `Response`\n * short-circuits (handler not reached); mutating `context` passes data to\n * the handler. Omitted → zero overhead (handler runs directly).\n */\n middleware?: readonly WebMiddleware[]\n /**\n * T5a.2 Phase E — body parser strategy.\n *\n * - `'inline'` (default): handle `application/json` + `text/*` only.\n * Returns the parsed value (object for JSON, string for text). Other\n * content-types (e.g., multipart) return `undefined`.\n * - `'full'`: delegate to `parseWebRequestBody` for multipart support\n * + per-file size caps + max-files cap (Web Standards `request.formData()`\n * under the hood). Returns a `ParsedWebBody` object:\n * `{ json?, fields, files }`. Multipart consumers MUST opt into this\n * mode; JSON-only routes pay zero cost staying on `'inline'`.\n */\n bodyParser?: 'inline' | 'full'\n /**\n * T5a.2 Phase G slice 1/N — plugin lifecycle hooks.\n *\n * Adapters (Node, CF Workers, Bun, Deno) wire `WebPluginContext`-shaped\n * hooks at the executeWebRequest lifecycle. Lifecycle order mirrors the\n * Fastify / Hono convention:\n *\n * 1. CSRF check (when opts.csrfMode === 'strict')\n * 2. onRequest — earliest, before body parsing. Plugins can short-circuit\n * by setting `ctx.response` (handler skipped; subsequent hooks see\n * the short-circuit response).\n * 3. body parse (inline OR full per opts.bodyParser)\n * 4. preHandler — after body parsed, before handler runs. Same\n * short-circuit semantic.\n * 5. handler invocation\n * 6. onResponse — after handler returns OR after a hook short-circuit.\n * `ctx.response` is populated.\n * 7. onError — fires if any of (handler, onRequest, preHandler) throws.\n * `ctx.response` is the envelope-shaped error response built via\n * serverErrorToEnvelope.\n *\n * `responseHeaders` is shared across hooks; the final Response merges\n * them with the handler's Response headers (handler headers win on\n * conflict; hook headers add new ones). Decorations made via\n * `ctx.ctx[key] = value` persist across hooks (request-scoped state).\n *\n * `hooks: undefined` (default) → no plugin lifecycle, Phase A behavior\n * preserved. Production consumers wire via the WebPluginRunner facade\n * (a future Phase G slice).\n */\n hooks?: {\n onRequest?: readonly WebOnRequestHook[]\n preHandler?: readonly WebPreHandlerHook[]\n onResponse?: readonly WebOnResponseHook[]\n onError?: readonly WebOnErrorHook[]\n }\n /**\n * Stable request identifier propagated into hook contexts. Adapters\n * resolve via traceparent / x-request-id / generated UUID (see\n * `extractTraceIdFromRequest` from Phase C slice 1/2). Default:\n * `globalThis.crypto.randomUUID()`.\n */\n requestId?: string\n}\n\n/**\n * Methods that require CSRF enforcement when `csrfMode: 'strict'`. GET\n * and HEAD are read-only per HTTP semantics and bypass CSRF (the threat\n * model is state-changing requests forged via cross-origin POSTs); OPTIONS\n * is the CORS preflight and also bypasses.\n */\nexport const CSRF_PROTECTED_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])\n\n/**\n * Web-Standards entry-point for executing a route module against a native\n * Web `Request`. Returns a native Web `Response`.\n *\n * Method dispatch: looks up the handler keyed by `request.method`\n * (uppercase). Returns 405 if the method isn't exported.\n *\n * @example\n * import * as users from './app/users/route.js'\n * import { executeWebRequest } from 'theokit/server'\n *\n * const response = await executeWebRequest(\n * new Request('http://localhost/api/users', { method: 'GET' }),\n * users,\n * { csrfMode: 'strict' },\n * )\n */\n/**\n * T5a.2 Phase G slice 1/N — merge hook-mutated response headers into the\n * handler's Response. Handler-set headers win on conflict (the handler\n * has the most context about its own response); hook headers add new\n * entries (e.g., CORS, Set-Cookie). Returns a new Response with the\n * merged headers + same body/status as the source.\n *\n * Set-Cookie is multi-value at the Web spec layer — `getSetCookie()` is\n * the only way to retrieve multiple values. The merge appends ALL hook-\n * set Set-Cookie values to the response (multiple Set-Cookie headers is\n * spec-correct and how browsers expect cookie issuance).\n */\nfunction mergeHookHeaders(response: Response, hookHeaders: Headers): Response {\n if ([...hookHeaders].length === 0) return response\n const merged = new Headers(response.headers)\n for (const [k, v] of hookHeaders.entries()) {\n if (k.toLowerCase() === 'set-cookie') continue // handled separately\n if (!merged.has(k)) merged.set(k, v)\n }\n for (const sc of hookHeaders.getSetCookie()) {\n merged.append('Set-Cookie', sc)\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers: merged,\n })\n}\n\n/** Build a 405 envelope Response. */\nfunction methodNotAllowedResponse(method: string): Response {\n const envelope: TheoErrorEnvelope = {\n code: 'METHOD_NOT_ALLOWED',\n message: `Method ${method} not allowed`,\n }\n return new Response(JSON.stringify(envelope), {\n status: 405,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/** Build a 403 CSRF envelope Response. */\nfunction csrfFailedResponse(reason: string): Response {\n const envelope: TheoErrorEnvelope = {\n code: 'FORBIDDEN',\n message: `CSRF check failed: ${reason}`,\n }\n return new Response(JSON.stringify(envelope), {\n status: 403,\n headers: { 'content-type': 'application/json' },\n })\n}\n\nexport async function executeWebRequest(\n request: Request,\n routeModule: WebRouteModule,\n opts: ExecuteWebRequestOptions = {},\n): Promise<Response> {\n const method = request.method.toUpperCase() as keyof WebRouteModule\n const config = routeModule[method] as WebRouteHandlerConfig | undefined\n\n // T5a.2 Phase G slice 1/N — plugin lifecycle hooks.\n // When opts.hooks is undefined, skip the entire hook orchestration to\n // preserve Phase A backward compat (zero overhead for consumers not\n // wiring hooks). In the no-hooks branch, dispatch + CSRF gates run\n // FIRST and 405 short-circuits before the handler runs.\n if (opts.hooks === undefined) {\n if (config === undefined || typeof config.handler !== 'function') {\n return methodNotAllowedResponse(method)\n }\n if (opts.csrfMode === 'strict' && CSRF_PROTECTED_METHODS.has(method)) {\n const csrfCheck = validateCsrfRequest(request)\n if (!csrfCheck.valid) return csrfFailedResponse(csrfCheck.reason)\n }\n try {\n // T3.2 — middleware runs AFTER the CSRF gate (EC-3), BEFORE the handler.\n const context: Record<string, unknown> = {}\n if (opts.middleware?.length) {\n const shortCircuit = await runWebMiddleware(request, opts.middleware, context)\n if (shortCircuit) return shortCircuit\n }\n const outcome = await runHandler(\n config,\n request,\n opts.bodyParser ?? 'inline',\n opts.params ?? {},\n context,\n )\n if (!outcome.ok) return outcome.response\n return toResponse(outcome.result, config.status)\n } catch (err) {\n return handlerErrorResponse(err)\n }\n }\n\n // With hooks: onRequest hooks run BEFORE method dispatch (Hono /\n // Fastify convention) so CORS preflight plugins can intercept OPTIONS\n // requests regardless of route shape. If no hook short-circuits, then\n // 405 fires when the method isn't exported by the route module.\n return runWithHooks(request, config, opts, opts.hooks)\n}\n\n/**\n * Run the request through the full plugin lifecycle. Extracted to keep\n * `executeWebRequest`'s cyclomatic + cognitive complexity under the lint\n * caps (15/20). Pure side-effect surface — same return type as the\n * no-hooks branch.\n */\n/**\n * Pre-handler pipeline: onRequest hooks → CSRF gate → preHandler hooks →\n * method dispatch + handler. Mutates `hookCtx.response` on short-circuit\n * OR on handler completion. Extracted from `runWithHooks` to keep the\n * latter's cyclomatic complexity under the lint cap (15).\n */\nasync function runPreHandlerPipeline(\n hookCtx: WebPluginContext,\n request: Request,\n config: WebRouteHandlerConfig | undefined,\n opts: ExecuteWebRequestOptions,\n hooks: NonNullable<ExecuteWebRequestOptions['hooks']>,\n): Promise<void> {\n const method = request.method.toUpperCase()\n const runList = async (list: readonly WebOnRequestHook[]): Promise<void> => {\n for (const hook of list) {\n if (hookCtx.response !== undefined) return\n await hook(hookCtx)\n }\n }\n // onRequest first (CORS preflight + auth gate intercept before dispatch).\n if (hooks.onRequest) await runList(hooks.onRequest)\n // CSRF gate AFTER onRequest (auth-short-circuit avoids CSRF cost) but\n // BEFORE the handler.\n if (\n hookCtx.response === undefined &&\n opts.csrfMode === 'strict' &&\n CSRF_PROTECTED_METHODS.has(method)\n ) {\n const csrfCheck = validateCsrfRequest(request)\n if (!csrfCheck.valid) hookCtx.response = csrfFailedResponse(csrfCheck.reason)\n }\n if (hookCtx.response === undefined && hooks.preHandler) {\n await runList(hooks.preHandler)\n }\n if (hookCtx.response === undefined) {\n await runHandlerStage(hookCtx, request, config, opts, method)\n }\n}\n\n/**\n * T3.2 — the middleware + handler stage of the hook pipeline. Extracted from\n * `runPreHandlerPipeline` to keep its cyclomatic complexity under the lint cap.\n * Order: 405 check → user middleware (after CSRF + preHandler) → handler.\n */\nasync function runHandlerStage(\n hookCtx: WebPluginContext,\n request: Request,\n config: WebRouteHandlerConfig | undefined,\n opts: ExecuteWebRequestOptions,\n method: string,\n): Promise<void> {\n // 405 if route module doesn't export this method.\n if (config === undefined || typeof config.handler !== 'function') {\n hookCtx.response = methodNotAllowedResponse(method)\n return\n }\n // hookCtx.ctx is the shared per-request context the middleware mutates.\n if (opts.middleware?.length) {\n const shortCircuit = await runWebMiddleware(request, opts.middleware, hookCtx.ctx)\n if (shortCircuit) {\n hookCtx.response = shortCircuit\n return\n }\n }\n const outcome = await runHandler(\n config,\n request,\n opts.bodyParser ?? 'inline',\n opts.params ?? {},\n hookCtx.ctx,\n )\n hookCtx.response = outcome.ok ? toResponse(outcome.result, config.status) : outcome.response\n}\n\nasync function runWithHooks(\n request: Request,\n config: WebRouteHandlerConfig | undefined,\n opts: ExecuteWebRequestOptions,\n hooks: NonNullable<ExecuteWebRequestOptions['hooks']>,\n): Promise<Response> {\n const hookCtx: WebPluginContext = {\n request,\n responseHeaders: new Headers(),\n ctx: {},\n requestId: opts.requestId ?? globalThis.crypto.randomUUID(),\n }\n try {\n await runPreHandlerPipeline(hookCtx, request, config, opts, hooks)\n if (hooks.onResponse) {\n for (const hook of hooks.onResponse) {\n await hook(hookCtx)\n }\n }\n // runPreHandlerPipeline guarantees hookCtx.response is set (via either\n // a hook short-circuit OR handler outcome OR 405). TS doesn't infer this\n // post-mutation; the assertion is safe per the function's contract.\n const finalResponse =\n hookCtx.response ??\n new Response(\n JSON.stringify({ code: 'INTERNAL_SERVER_ERROR', message: 'No response built' }),\n {\n status: 500,\n headers: { 'content-type': 'application/json' },\n },\n )\n return mergeHookHeaders(finalResponse, hookCtx.responseHeaders)\n } catch (err) {\n return runErrorHooks(err, hookCtx, hooks.onError)\n }\n}\n\n/**\n * Run onError hooks against an envelope-shaped error response. EC-9 —\n * each hook throw is swallowed to avoid error-in-error-handler recursion.\n * Returns the merged final Response.\n */\nasync function runErrorHooks(\n err: unknown,\n hookCtx: WebPluginContext,\n onError: readonly WebOnErrorHook[] | undefined,\n): Promise<Response> {\n const errorResponse = handlerErrorResponse(err)\n if (onError !== undefined) {\n const errorCtx: WebPluginErrorContext = {\n ...hookCtx,\n response: errorResponse,\n error: err,\n }\n for (const hook of onError) {\n try {\n await hook(errorCtx)\n } catch {\n // EC-9: error in error handler — swallow to avoid recursion.\n }\n }\n }\n return mergeHookHeaders(errorResponse, hookCtx.responseHeaders)\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/define/define-route.ts","../src/server/define/define-action.ts","../src/server/define/define-middleware.ts","../src/server/define/define-agent-tool.ts","../src/server/define/define-websocket.ts","../src/server/define/define-channel.ts","../src/server/define/define-plugin.ts"],"sourcesContent":["import type { z } from 'zod'\n\n// T2.2 (architecture-cleanup) — RouteConfig type moved to core/contracts/\n// (canonical home per ADR-0001 v3). Re-export preserves the public path\n// `import { type RouteConfig } from 'theokit/server'`.\nexport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\n/**\n * Define a typed HTTP route.\n * Identity function — provides type inference for route handlers.\n */\nexport function defineRoute<\n TQuery extends z.ZodType = z.ZodUndefined,\n TBody extends z.ZodType = z.ZodUndefined,\n TParams extends z.ZodType = z.ZodUndefined,\n TCtx = unknown,\n TResponse = unknown,\n>(\n config: RouteConfig<TQuery, TBody, TParams, TCtx, TResponse>,\n): RouteConfig<TQuery, TBody, TParams, TCtx, TResponse> {\n return config\n}\n","import type { z } from 'zod'\n\n/**\n * Action wire-protocol accept mode per plan g3-server-actions-and-useaction\n * v1.2 ADR D1. Default behavior (when omitted) is `'json'`. `'form'` opts the\n * action into FormData multipart parsing for progressive-enhancement forms;\n * the runtime in `server/http/action-execute.ts` will coerce FormData entries\n * against the `input` schema via `formDataToObject` (Astro pattern).\n */\nexport type ActionAccept = 'form' | 'json'\n\nexport interface ActionConfig<TInput extends z.ZodType, TCtx = unknown> {\n /**\n * Zod input schema. Required: every action declares its input contract via\n * Zod (architecture rule: zod-is-SSOT). The shape becomes the handler's\n * typed `input` parameter via `z.infer<TInput>`.\n */\n input: TInput\n /**\n * Wire-protocol accept mode. Defaults to `'json'` when omitted. Setting\n * `'form'` switches the runtime to FormData multipart parsing — the input\n * schema MUST be `z.object(...)` so field-by-field coercion can drive\n * boolean string / number / array coercion (Astro pattern).\n */\n accept?: ActionAccept\n /**\n * Opt OUT of CSRF enforcement for this action. Default (omitted) keeps the\n * multi-header CSRF gate active. Set `false` for endpoints intentionally\n * callable without the `X-Theo-Action` header (e.g. public webhooks). The\n * runtime in `server/http/action-execute.ts` reads this flag.\n */\n csrf?: false\n handler: (ctx: { input: z.infer<TInput>; ctx: TCtx }) => unknown\n}\n\n/**\n * Define a typed server action.\n *\n * Identity function — provides type inference for action handlers. The\n * runtime that consumes the config (validation + invocation + serialization)\n * lives in `server/http/action-execute.ts`.\n *\n * Per plan g3-server-actions-and-useaction v1.2 § Phase 1 / T1.2: the new\n * `accept?: 'form' | 'json'` field is the only contract change vs the\n * pre-G3 identity. Existing callsites (`defineAction({input, handler})`)\n * continue to compile — `accept` is opt-in.\n */\nexport function defineAction<TInput extends z.ZodType, TCtx = unknown>(\n config: ActionConfig<TInput, TCtx>,\n): ActionConfig<TInput, TCtx> {\n return config\n}\n","export type MiddlewareHandler = (\n request: Request,\n next: (request: Request) => Promise<Response>,\n) => Response | Promise<Response>\n\n/**\n * Define a middleware handler.\n * Identity function — provides type annotation for middleware.\n */\nexport function defineMiddleware(handler: MiddlewareHandler): MiddlewareHandler {\n return handler\n}\n","import { z } from 'zod'\n\n/**\n * Item #4 — `defineAgentTool`\n *\n * Sugar over the `@theokit/sdk` `CustomTool` contract. Takes a Zod schema +\n * handler and produces a structurally-compatible `CustomTool` that\n * `Agent.create({ tools: [...] })` accepts.\n *\n * Uses Zod v4's native `z.toJSONSchema()` to convert the input schema to\n * JSON Schema for LLM providers.\n *\n * Handler error propagation:\n * `defineAgentTool` parses the input via the Zod schema BEFORE calling the\n * user handler. Invalid input throws a `ZodError`, which the SDK's tool-\n * dispatcher treats as a tool failure and surfaces to the model as a tool\n * error (the SDK owns the wire; ADR D3).\n */\n\n/**\n * Local mirror of the SDK's `CustomTool` interface. We don't `import type`\n * from `@theokit/sdk` because the SDK is an optional peer (consumers who\n * never call `defineAgentTool` shouldn't need it installed). The shape is\n * the wire contract; any structurally-matching object is accepted by\n * `Agent.create({ tools })`.\n *\n * @public\n */\nexport interface CustomTool {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n handler: (input: Record<string, unknown>) => string | Promise<string>\n}\n\n/**\n * Spec accepted by {@link defineAgentTool}. `inputSchema` is a Zod 3 schema\n * rooted in `z.object(...)`. The `handler` argument type is inferred via\n * `z.infer<T>`.\n *\n * @public\n */\nexport interface DefineAgentToolSpec<T extends z.ZodType> {\n /** Tool name surfaced to the LLM. Must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$`. */\n name: string\n /** Description surfaced to the LLM. Required — drives tool-selection accuracy. */\n description: string\n /** Zod schema describing the input. Must be `z.object(...)` at the root. */\n inputSchema: T\n /** Handler invoked with the parsed input. */\n handler: (input: z.infer<T>) => string | Promise<string>\n}\n\nconst TOOL_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/\n\nfunction isZodObject(schema: z.ZodType): boolean {\n // Refinements (`.refine`), transforms (`.transform`), and defaults wrap the\n // underlying schema — walk the chain until we hit a ZodObject (or give up).\n // Supports both zod 4 (`instanceof z.ZodObject`, `def.type === 'object'`,\n // wrappers via `def.innerType` / pipe via `def.in`) and zod 3\n // (`_def.typeName === 'ZodObject'`, wrappers via `_def.schema`/`_def.innerType`).\n let current: unknown = schema\n for (let depth = 0; depth < 10; depth++) {\n if (current instanceof z.ZodObject) return true\n const z4 = (current as { def?: { type?: string; innerType?: unknown; in?: unknown } }).def\n if (z4?.type === 'object') return true\n const z3 = (current as { _def?: { typeName?: string; schema?: unknown; innerType?: unknown } })\n ._def\n if (z3?.typeName === 'ZodObject') return true\n const next = z4?.innerType ?? z4?.in ?? z3?.schema ?? z3?.innerType\n if (next !== undefined) {\n current = next\n continue\n }\n return false\n }\n return false\n}\n\n/**\n * Build a {@link CustomTool} from a Zod 3 schema + handler.\n *\n * Behavior:\n * - Validates `name` matches the LLM tool-name regex.\n * - Requires `inputSchema` to be a `ZodObject` (Anthropic + SDK contract).\n * - Warns (not throws) if `description` is empty — empty descriptions\n * degrade LLM tool selection.\n * - Converts the Zod schema to JSON Schema 7 inline (no `$ref`s — LLMs handle\n * inline schemas more reliably).\n * - Strips the top-level `$schema` field (Anthropic rejects schemas with\n * `$schema` at root in some provider modes).\n * - Wraps the handler to parse the input via the Zod schema BEFORE invoking\n * the user code — bad LLM-supplied input throws `ZodError`, which the SDK\n * converts to `tool_result(isError)`.\n *\n * @public\n */\nexport function defineAgentTool<T extends z.ZodType>(spec: DefineAgentToolSpec<T>): CustomTool {\n if (!TOOL_NAME_REGEX.test(spec.name)) {\n throw new Error(\n `defineAgentTool: name must match ${TOOL_NAME_REGEX.source}. Got: ${JSON.stringify(spec.name)}`,\n )\n }\n if (!isZodObject(spec.inputSchema)) {\n throw new Error('defineAgentTool: inputSchema must be a ZodObject (z.object({...}))')\n }\n if (spec.description.length === 0) {\n console.warn(\n `defineAgentTool(${JSON.stringify(spec.name)}): empty description degrades LLM tool selection — provide a one-sentence summary.`,\n )\n }\n\n // Zod v4 native JSON Schema conversion — replaces zod-to-json-schema dep.\n // Strip $schema (Anthropic + some providers reject it).\n const { $schema: _$schema, ...inputSchema } = z.toJSONSchema(spec.inputSchema) as Record<\n string,\n unknown\n > & {\n $schema?: unknown\n }\n\n return {\n name: spec.name,\n description: spec.description,\n inputSchema,\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const parsed = spec.inputSchema.parse(input)\n return await spec.handler(parsed)\n },\n }\n}\n","import type { IncomingMessage } from 'node:http'\n\nexport interface WebSocketLike {\n send(data: string | Buffer): void\n close(code?: number, reason?: string): void\n}\n\nexport interface WebSocketHandler {\n onOpen?: (ws: WebSocketLike, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, data: string | Buffer) => void\n onClose?: (ws: WebSocketLike, code: number, reason: Buffer) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Define a WebSocket endpoint handler.\n * Identity function — provides type inference for WebSocket handlers.\n */\nexport function defineWebSocket(handler: WebSocketHandler): WebSocketHandler {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 3/3 — Web-Standards WebSocket endpoint handler.\n *\n * Mirror of `WebSocketHandler` for the Web `Request` shape. `onOpen`\n * receives `request: Request` instead of `req: IncomingMessage`. The\n * rest of the lifecycle (onMessage, onClose, onError) is shape-agnostic\n * (`WebSocketLike` is already Web-standards-compatible per the existing\n * design — `send(string | Buffer)` works on both Node `ws` and Web\n * `WebSocket` instances; CF Workers / Bun / Deno coerce as needed at\n * the adapter boundary).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F (closes Phase F).\n *\n * **Architectural note — WebSocket upgrade semantics differ across runtimes:**\n * - Node + `ws`: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * `req` is `IncomingMessage`. Use `WebSocketHandler`.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request). Use `WebSocketHandlerWeb`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Cross-runtime WebSocket endpoints ship BOTH `WebSocketHandler` +\n * `WebSocketHandlerWeb` exports; the runtime adapter picks the matching\n * one. This is the canonical Hono / Nitric pattern.\n */\nexport interface WebSocketHandlerWeb {\n onOpen?: (ws: WebSocketLike, request: Request) => void\n onMessage?: (ws: WebSocketLike, data: string | Uint8Array) => void\n onClose?: (ws: WebSocketLike, code: number, reason: string) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Web-Standards `defineWebSocket` sibling. Identity function — provides\n * type inference for Web WebSocket handlers.\n *\n * **Type difference note vs Node path:**\n * - `onMessage` data is `string | Uint8Array` instead of `string | Buffer`\n * (Web standards have no `Buffer`; Node's Buffer is a Uint8Array\n * subclass so the Node path's Buffer values flow through unchanged\n * when adapters wrap them).\n * - `onClose` reason is `string` instead of `Buffer` (Web `CloseEvent`\n * exposes the reason as a UTF-8 string natively).\n */\nexport function defineWebSocketWeb(handler: WebSocketHandlerWeb): WebSocketHandlerWeb {\n return handler\n}\n","import type { IncomingMessage } from 'node:http'\n\nimport type { WebSocketLike } from './define-websocket.js'\n\nexport interface ChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Define a channel handler for WebSocket rooms.\n * Identity function — provides type inference for channel handlers.\n */\nexport function defineChannel<TMessage = unknown>(\n handler: ChannelHandler<TMessage>,\n): ChannelHandler<TMessage> {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 2/3 — Web-Standards channel handler.\n *\n * Mirror of `ChannelHandler<TMessage>` for the Web `Request` shape.\n * `onSubscribe` receives `request: Request` instead of `req: IncomingMessage`\n * — the rest of the surface (onMessage, onUnsubscribe) is shape-agnostic\n * (WebSocketLike is already Web-standards-compatible per `define-websocket.ts`).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F.\n *\n * **Architectural note:** WebSocket upgrade semantics differ across\n * runtimes:\n * - Node: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * hands you `req: IncomingMessage` at the upgrade handshake.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request) — hands you `request: Request`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Channel handlers targeting CF/Bun/Deno use `WebChannelHandler`; legacy\n * Node consumers stay on `ChannelHandler`. Cross-runtime channels ship\n * both shapes.\n */\nexport interface WebChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, request: Request) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Web-Standards `defineChannel` sibling. Identity function — provides\n * type inference for Web channel handlers.\n */\nexport function defineWebChannel<TMessage = unknown>(\n handler: WebChannelHandler<TMessage>,\n): WebChannelHandler<TMessage> {\n return handler\n}\n","import type { TheoPlugin } from '../plugin-types.js'\n\n/**\n * Identity function for defining a Theo plugin.\n *\n * **Note:** Prefer `definePlugin` (shorter, canonical name per ADR-0008 D6).\n * Both functions are identical — `defineTheoPlugin` is kept as an alias for\n * existing in-tree consumers without forcing a migration sweep.\n */\nexport function defineTheoPlugin(plugin: TheoPlugin): TheoPlugin {\n return plugin\n}\n"],"mappings":";AAaO,SAAS,YAOd,QACsD;AACtD,SAAO;AACT;;;ACwBO,SAAS,aACd,QAC4B;AAC5B,SAAO;AACT;;;AC1CO,SAAS,iBAAiB,SAA+C;AAC9E,SAAO;AACT;;;ACXA,SAAS,SAAS;AAqDlB,IAAM,kBAAkB;AAExB,SAAS,YAAY,QAA4B;AAM/C,MAAI,UAAmB;AACvB,WAAS,QAAQ,GAAG,QAAQ,IAAI,SAAS;AACvC,QAAI,mBAAmB,EAAE,UAAW,QAAO;AAC3C,UAAM,KAAM,QAA2E;AACvF,QAAI,IAAI,SAAS,SAAU,QAAO;AAClC,UAAM,KAAM,QACT;AACH,QAAI,IAAI,aAAa,YAAa,QAAO;AACzC,UAAM,OAAO,IAAI,aAAa,IAAI,MAAM,IAAI,UAAU,IAAI;AAC1D,QAAI,SAAS,QAAW;AACtB,gBAAU;AACV;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAoBO,SAAS,gBAAqC,MAA0C;AAC7F,MAAI,CAAC,gBAAgB,KAAK,KAAK,IAAI,GAAG;AACpC,UAAM,IAAI;AAAA,MACR,oCAAoC,gBAAgB,MAAM,UAAU,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,IAC/F;AAAA,EACF;AACA,MAAI,CAAC,YAAY,KAAK,WAAW,GAAG;AAClC,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,MAAI,KAAK,YAAY,WAAW,GAAG;AACjC,YAAQ;AAAA,MACN,mBAAmB,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,IAC9C;AAAA,EACF;AAIA,QAAM,EAAE,SAAS,UAAU,GAAG,YAAY,IAAI,EAAE,aAAa,KAAK,WAAW;AAO7E,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB;AAAA,IACA,SAAS,OAAO,UAAoD;AAClE,YAAM,SAAS,KAAK,YAAY,MAAM,KAAK;AAC3C,aAAO,MAAM,KAAK,QAAQ,MAAM;AAAA,IAClC;AAAA,EACF;AACF;;;AChHO,SAAS,gBAAgB,SAA6C;AAC3E,SAAO;AACT;AA+CO,SAAS,mBAAmB,SAAmD;AACpF,SAAO;AACT;;;ACvDO,SAAS,cACd,SAC0B;AAC1B,SAAO;AACT;AAoCO,SAAS,iBACd,SAC6B;AAC7B,SAAO;AACT;;;ACjDO,SAAS,iBAAiB,QAAgC;AAC/D,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server/transformer.ts","../src/server/agent/approve-agent.ts","../src/server/agent/mount-agent.ts","../src/server/define/ui-message-stream-response.ts","../src/server/http/node-web-adapter.ts"],"sourcesContent":["import superjson from 'superjson'\n\n/**\n * T5.2 — pluggable response/request transformer.\n *\n * `superjson` is the default, preserving Date/Map/Set/BigInt/etc.\n * `json` is the lightweight option (plain JSON.stringify/parse).\n * Users can supply a custom object implementing this contract.\n */\nexport interface TheoTransformer {\n name: string\n serialize: (value: unknown) => string\n deserialize: (raw: string) => unknown\n}\n\nexport const superjsonTransformer: TheoTransformer = {\n name: 'superjson',\n serialize: (v) => JSON.stringify(superjson.serialize(v)),\n deserialize: (raw) => {\n const parsed = JSON.parse(raw) as Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize(parsed)\n },\n}\n\nexport const jsonTransformer: TheoTransformer = {\n name: 'json',\n serialize: (v) => JSON.stringify(v),\n deserialize: (raw) => JSON.parse(raw) as unknown,\n}\n\nconst BUILT_INS: Record<string, TheoTransformer> = {\n superjson: superjsonTransformer,\n json: jsonTransformer,\n}\n\nexport function resolveTransformer(\n selector: 'json' | 'superjson' | TheoTransformer,\n): TheoTransformer {\n if (typeof selector === 'string') {\n // selector is 'json' | 'superjson' literal — both keys exist in\n // BUILT_INS by construction. Type system guarantees a hit; we keep\n // a defensive fallback that the compiler cannot see is unreachable\n // at runtime, just in case someone adds a new literal to the union\n // but forgets to register the built-in.\n const built = BUILT_INS[selector]\n // Defensive: the public union ensures `built` is defined, but if a\n // future contributor extends the union without registering the impl,\n // the cast keeps the failure mode loud.\n if ((built as TheoTransformer | undefined) === undefined) {\n throw new Error(\n `Unknown transformer \"${selector}\". Built-in options: ${Object.keys(BUILT_INS).join(', ')}.`,\n )\n }\n return built\n }\n if (\n typeof selector !== 'object' ||\n typeof selector.serialize !== 'function' ||\n typeof selector.deserialize !== 'function'\n ) {\n throw new Error(\n `Custom transformer must have serialize and deserialize functions. Got: ${JSON.stringify(selector)}`,\n )\n }\n return selector\n}\n","/**\n * M4 (theokit-ai-first) — the HITL approve endpoint: `POST /api/agents/<name>/approve/<approvalId>`.\n *\n * The counterpart to `mountAgent`'s HITL pause. While a gated tool holds the SDK run paused (the\n * awaited `pre_tool_call` hook), the client POSTs here with `{ approved }`; this resolves the\n * pending approval in the shared registry, which un-pauses the run (allow) or vetoes the tool (deny).\n *\n * Web-Standard `Request` → `Response`, one wiring point shared by dev (vite middleware) and prod\n * (built server) so the two never drift (EC-4 parity with `mountAgent`). The registry is INJECTED —\n * dev/prod pass the process singleton (`getApprovalRegistry`), tests pass a fresh instance.\n */\nimport { validateCsrfRequest, type CsrfMode } from '../security/csrf.js'\n\nimport type { ApprovalRegistry } from './approval-registry.js'\n\n/** The path segment separating the agent name from the approval id. */\nconst APPROVE_SEGMENT = '/approve/'\n\n/**\n * Extract the `<approvalId>` from a `/api/agents/<name>/approve/<approvalId>` path.\n * Returns `null` when the path has no `/approve/` segment or an empty / nested id.\n */\nexport function parseApprovalId(urlPath: string): string | null {\n const at = urlPath.indexOf(APPROVE_SEGMENT)\n if (at === -1) return null\n const id = urlPath.slice(at + APPROVE_SEGMENT.length)\n return id.length > 0 && !id.includes('/') ? id : null\n}\n\n/** True when `urlPath` targets a HITL approve endpoint (used by dev/prod routing to branch early). */\nexport function isApprovalPath(urlPath: string): boolean {\n return urlPath.includes(APPROVE_SEGMENT)\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/** Extract `{ approved: boolean }` from an untrusted body; `null` when the shape is wrong. */\nfunction parseApprovalBody(body: unknown): { approved: boolean } | null {\n if (typeof body !== 'object' || body === null) return null\n const b = body as Record<string, unknown>\n return typeof b.approved === 'boolean' ? { approved: b.approved } : null\n}\n\n/**\n * Resolve a pending HITL approval. CSRF-guarded like `mountAgent` (the custom `X-Theo-Action`\n * header + Origin match) — a cross-origin POST must not approve a paused tool. Returns:\n * 403 CSRF_FAILED — strict CSRF check failed\n * 400 BAD_REQUEST — no `/approve/<id>` in the path, or body lacks a boolean `approved`\n * 404 NOT_PENDING — the id is unknown or already settled (idempotent double-submit)\n * 200 { resolved:true } — the approval was settled by this call\n */\nexport async function handleAgentApproval(\n request: Request,\n urlPath: string,\n registry: ApprovalRegistry,\n csrfMode: CsrfMode = 'strict',\n): Promise<Response> {\n if (csrfMode !== 'off') {\n const csrf = validateCsrfRequest(request)\n if (!csrf.valid && csrfMode === 'strict') {\n return jsonError(403, 'CSRF_FAILED', `CSRF check failed: ${csrf.reason}`)\n }\n }\n\n const approvalId = parseApprovalId(urlPath)\n if (approvalId === null) {\n return jsonError(400, 'BAD_REQUEST', 'Approval path must be /api/agents/<name>/approve/<id>.')\n }\n\n let body: unknown = null\n try {\n body = await request.json()\n } catch {\n /* invalid/empty JSON → handled below as a 400 */\n }\n const parsed = parseApprovalBody(body)\n if (parsed === null) {\n return jsonError(400, 'BAD_REQUEST', 'Request body must contain a boolean `approved`.')\n }\n\n const resolved = registry.resolve(approvalId, parsed.approved)\n if (!resolved) {\n return jsonError(404, 'NOT_PENDING', `No pending approval for id '${approvalId}'.`)\n }\n return new Response(JSON.stringify({ resolved: true }), {\n status: 200,\n headers: { 'content-type': 'application/json' },\n })\n}\n","/**\n * M2 (theokit-ai-first) — mount a scanned `agents/<name>.ts` module as an SSE endpoint.\n *\n * The SINGLE wiring point shared by dev (vite middleware) and prod (built server), so the\n * two never drift (EC-4). Web-Standard `Request` → `Response`: parse the chat body, compile\n * the module (`compileAgentModule`, converges both surfaces), stream via the M0/M1 canonical\n * protocol (`streamAgentUIMessages` → `uiMessageStreamResponse`).\n *\n * Request body — accepts the `@ai-sdk/react` `useChat` shape (`{ id, messages: UIMessage[] }`,\n * the typed-client path) AND a simple `{ message, sessionId? }` shape (M0/M1-style clients).\n */\nimport {\n compileAgentModule,\n streamAgentUIMessages,\n type HumanInTheLoopOptions,\n} from '@theokit/agents'\n\nimport { uiMessageStreamResponse } from '../define/ui-message-stream-response.js'\nimport { validateCsrfRequest, type CsrfMode } from '../security/csrf.js'\n\nimport { getApprovalRegistry } from './approval-registry.js'\n\n/** The message + session extracted from a chat request, or `null` when the body is invalid. */\nexport interface AgentRequestInput {\n message: string\n sessionId: string\n}\n\n/** Extract the text of a `{ type: 'text', text: string }` part from an untrusted value. */\nfunction partText(part: unknown): string {\n if (typeof part !== 'object' || part === null) return ''\n const p = part as Record<string, unknown>\n return p.type === 'text' && typeof p.text === 'string' ? p.text : ''\n}\n\nfunction jsonError(status: number, code: string, message: string): Response {\n return new Response(JSON.stringify({ error: { code, message } }), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n}\n\n/**\n * Extract `{ message, sessionId }` from a chat request body. Returns `null` when neither the\n * ai-sdk `messages` shape nor the simple `message` shape yields non-empty user text.\n */\nexport function parseAgentRequestBody(body: unknown): AgentRequestInput | null {\n if (typeof body !== 'object' || body === null) return null\n const b = body as Record<string, unknown>\n\n // ai-sdk useChat shape: { id, messages: UIMessage[] } — take the last message's text parts.\n if (Array.isArray(b.messages) && b.messages.length > 0) {\n const last = b.messages[b.messages.length - 1] as Record<string, unknown>\n const parts = Array.isArray(last.parts) ? last.parts : []\n const text = parts.map(partText).join('')\n if (text.length === 0) return null\n const sessionId = typeof b.id === 'string' && b.id.length > 0 ? b.id : crypto.randomUUID()\n return { message: text, sessionId }\n }\n\n // Simple shape: { message, sessionId? }.\n if (typeof b.message === 'string' && b.message.length > 0) {\n const sessionId =\n typeof b.sessionId === 'string' && b.sessionId.length > 0 ? b.sessionId : crypto.randomUUID()\n return { message: b.message, sessionId }\n }\n\n return null\n}\n\n/**\n * Mount a loaded agent module as a `Response`. `apiKey` is resolved by the caller\n * (`resolveProvider`). `source` labels a fail-fast `AgentDefinitionError` (the file path).\n */\nexport async function mountAgent(\n mod: unknown,\n request: Request,\n apiKey: string,\n source = 'agent module',\n csrfMode: CsrfMode = 'strict',\n): Promise<Response> {\n // Enforce CSRF BEFORE any work — an agent run spends real LLM tokens, so a cross-origin\n // POST must be rejected before it reaches the SDK (parity with actions/routes). The custom\n // `X-Theo-Action` header + Origin match is the same defense `executeRoute`/`executeAction`\n // apply; the `useAgent` client sends the header. `off` skips; `warn` never blocks.\n if (csrfMode !== 'off') {\n const csrf = validateCsrfRequest(request)\n if (!csrf.valid && csrfMode === 'strict') {\n return jsonError(403, 'CSRF_FAILED', `CSRF check failed: ${csrf.reason}`)\n }\n }\n\n const compiled = compileAgentModule(mod, source)\n\n let body: unknown = null\n try {\n body = await request.json()\n } catch {\n /* invalid/empty JSON → handled below as a 400 */\n }\n\n const input = parseAgentRequestBody(body)\n if (input === null) {\n return jsonError(400, 'BAD_REQUEST', 'Request must contain a non-empty message or messages[].')\n }\n\n // When the agent has @HumanInTheLoop-gated tools (M4), wire the pause: the plugin's `awaitApproval`\n // registers a pending approval in the shared registry (the Promise that PAUSES the run); the\n // approve route (`handleAgentApproval`) resolves it. No gated tools ⇒ the M2 stream path unchanged.\n const gated = compiled.hitl\n const registry = getApprovalRegistry()\n const hitl =\n gated && gated.size > 0\n ? {\n gated,\n awaitApproval: (approvalId: string, opts: HumanInTheLoopOptions) =>\n registry.register(approvalId, {\n timeoutMs: opts.timeout ?? 300_000,\n onTimeout: opts.onTimeout ?? 'abort',\n }),\n }\n : undefined\n\n return uiMessageStreamResponse(\n streamAgentUIMessages(compiled, apiKey, { ...input, hitl, signal: request.signal }),\n )\n}\n","import type { UIMessageChunk } from 'ai'\n\n/**\n * M0 (theokit-ai-first) — serialize a stream of ai-sdk `UIMessageChunk`s into a\n * Web-Standards `Response` on the UIMessageStream wire so `@ai-sdk/react`'s\n * `useChat` consumes it WITHOUT a custom adapter.\n *\n * Wire contract (must match ai-sdk's consumer transport exactly):\n * - `content-type: text/event-stream`\n * - `x-vercel-ai-ui-message-stream: v1` — the version marker `useChat` checks\n * - each chunk framed as `data: ${JSON.stringify(chunk)}\\n\\n`\n * - a terminal `data: [DONE]\\n\\n` after the last chunk (ignored by the parser)\n *\n * Web Standards only — `Response` + `ReadableStream` (G8, no node:http). The\n * headers commit before the stream starts.\n *\n * Fail-clear (error-handling.md): if the source iterable throws mid-stream, the\n * `[DONE]` terminal is still flushed and the stream is closed — never left\n * hanging. (The translator upstream already closes gracefully; this is defense\n * in depth for any other chunk source.)\n */\nconst UI_MESSAGE_STREAM_HEADERS = {\n 'content-type': 'text/event-stream',\n 'x-vercel-ai-ui-message-stream': 'v1',\n} as const\n\nconst DONE_FRAME = 'data: [DONE]\\n\\n'\n\nfunction encode(text: string): Uint8Array {\n return new TextEncoder().encode(text)\n}\n\nexport function uiMessageStreamResponse(chunks: AsyncIterable<UIMessageChunk>): Response {\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n try {\n for await (const chunk of chunks) {\n controller.enqueue(encode(`data: ${JSON.stringify(chunk)}\\n\\n`))\n }\n } catch {\n // The source iterable aborted mid-stream. The upstream translator owns\n // error semantics (it surfaces failures as chunks + closes gracefully);\n // this transport's sole guarantee is a terminated stream — fall through\n // to the DONE terminal rather than re-throw and error an open stream.\n } finally {\n controller.enqueue(encode(DONE_FRAME))\n controller.close()\n }\n },\n })\n return new Response(stream, { headers: UI_MESSAGE_STREAM_HEADERS })\n}\n","/**\n * T5a.2 Phase G slice 5/N — Node adapter shim for the Web request handler.\n *\n * Bridges Node's `IncomingMessage` + `ServerResponse` shape to the\n * Web-Standards `executeWebRequest` (Phase A → G slices 1-4). Per\n * ADR-0028 R3a, the Node adapter is the ONLY place IncomingMessage ↔\n * Request conversion happens — every other layer of `server/` flows\n * through Web `Request`/`Response`.\n *\n * **Two conversions:**\n *\n * 1. `incomingMessageToWebRequest(req)` — Node → Web. Reads\n * `req.method`, `req.url`, `req.headers`, and (for POST/PUT/etc.)\n * drains the Node Readable body into a Web `ReadableStream`. The\n * request URL is resolved to absolute form using `req.headers.host`\n * (Web Request guarantees absolute URL).\n *\n * 2. `writeWebResponseToServerResponse(response, res)` — Web → Node.\n * Sets status code + status text, copies headers (including all\n * `Set-Cookie` values via `getSetCookie()`), then drains the Web\n * `ReadableStream` body into the Node ServerResponse.\n *\n * Plus the convenience composer `executeWebRequestFromNode(req, res,\n * routeModule, opts?)` that wires both ends — exactly what api-middleware\n * (and the prod CLI start path) need to migrate from the legacy\n * `executeRoute` to `executeWebRequest` without touching call sites.\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase G slice 5/N (closes the executor bridge surface).\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport { Readable } from 'node:stream'\n\nimport { executeWebRequest, type ExecuteWebRequestOptions } from '../web-handler.js'\n\n/**\n * Build a Web `Request` from a Node `IncomingMessage`. The Web Request\n * spec requires an absolute URL; we synthesize one from\n * `req.headers.host` (or fall back to `localhost` for test doubles).\n *\n * For methods with a body (POST/PUT/PATCH/DELETE), the Node Readable\n * stream is wrapped as a Web ReadableStream via `Readable.toWeb()` so\n * downstream consumers can call `request.json()` / `request.formData()`\n * / `request.text()` natively.\n *\n * EC-1: Node sometimes provides headers as `string | string[]`. Web\n * `Headers` collapses to single-comma-joined strings — we do the join\n * manually for repeated headers because `Headers.append` would create\n * multi-value entries which behave differently on `.get()`.\n */\nexport function incomingMessageToWebRequest(req: IncomingMessage): Request {\n const host = pickHeaderString(req.headers.host) ?? 'localhost'\n const url = `http://${host}${req.url ?? '/'}`\n\n const headers = new Headers()\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined) continue\n if (Array.isArray(value)) {\n headers.set(key, value.join(', '))\n } else {\n headers.set(key, value)\n }\n }\n\n const method = (req.method ?? 'GET').toUpperCase()\n const hasBody = method !== 'GET' && method !== 'HEAD'\n\n if (!hasBody) {\n return new Request(url, { method, headers })\n }\n\n // Drain Node's Readable into a Web ReadableStream. `Readable.toWeb` is\n // available in Node 18+ (theokit's engines.node floor is 22+, so safe).\n const webStream = Readable.toWeb(req) as ReadableStream\n return new Request(url, {\n method,\n headers,\n body: webStream,\n // EC-2: Node 18+ requires `duplex: 'half'` when body is a stream.\n // The `RequestInit` type omits it (Web spec gap); cast accordingly.\n ...({ duplex: 'half' } as { duplex: 'half' }),\n })\n}\n\n/**\n * Write a Web `Response` into a Node `ServerResponse`. Mirrors the Node\n * `res.writeHead` + `res.end` pattern.\n *\n * Set-Cookie is the only multi-value header the Web spec exposes via\n * `getSetCookie()`. We append each entry individually so Node emits\n * separate `Set-Cookie:` lines per the HTTP spec.\n *\n * If the Response body is a `ReadableStream`, it's piped chunk-by-chunk\n * to `res`. Empty body (null) → just close.\n */\nexport async function writeWebResponseToServerResponse(\n response: Response,\n res: ServerResponse,\n): Promise<void> {\n // Status + headers FIRST (writeHead locks them).\n // EC-3: Set-Cookie needs special handling (writeHead's plain object\n // shape conflicts with multi-value headers; we set them via setHeader\n // BEFORE writeHead so the array form is preserved).\n const setCookies = response.headers.getSetCookie()\n if (setCookies.length > 0) {\n res.setHeader('Set-Cookie', setCookies)\n }\n const otherHeaders: Record<string, string> = {}\n for (const [key, value] of response.headers.entries()) {\n if (key.toLowerCase() === 'set-cookie') continue\n otherHeaders[key] = value\n }\n res.writeHead(response.status, response.statusText, otherHeaders)\n\n // Body — drain ReadableStream OR just end() for null body.\n if (response.body === null) {\n res.end()\n return\n }\n const reader = response.body.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n // Node's res.write accepts Uint8Array natively (no conversion needed).\n res.write(value)\n }\n res.end()\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Convenience composer — full request lifecycle Node → Web → Node.\n *\n * Use case: existing api-middleware (and the prod CLI start path)\n * receive Node `(req, res)` from `http.createServer`. To migrate to the\n * Web-Standards executor without rewriting every call site, wrap with\n * this composer:\n *\n * import * as users from './app/users/route.js'\n * await executeWebRequestFromNode(req, res, users, { csrfMode: 'strict' })\n *\n * The Web request is built, dispatched through executeWebRequest, and\n * the Response is drained back into `res`. Caller does NOT need to call\n * `res.end()` afterwards — this composer handles it.\n */\nexport async function executeWebRequestFromNode(\n req: IncomingMessage,\n res: ServerResponse,\n routeModule: Parameters<typeof executeWebRequest>[1],\n opts?: ExecuteWebRequestOptions,\n): Promise<void> {\n const webRequest = incomingMessageToWebRequest(req)\n const webResponse = await executeWebRequest(webRequest, routeModule, opts)\n await writeWebResponseToServerResponse(webResponse, res)\n}\n\n/** Pick the first usable string from Node's `string | string[] | undefined` headers. */\nfunction pickHeaderString(value: string | string[] | undefined): string | undefined {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n for (const v of value) if (typeof v === 'string' && v.length > 0) return v\n }\n return undefined\n}\n"],"mappings":"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","names":["jsonError"]}