@lamplitisles/dsh-nanocodex 0.1.0-beta.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 (276) hide show
  1. package/LICENSE +65 -0
  2. package/NOTICE +2 -0
  3. package/README.md +182 -0
  4. package/THIRD_PARTY_NOTICES.md +29 -0
  5. package/cordis.patch.yml +52 -0
  6. package/dist/index.d.ts +435 -0
  7. package/dist/index.js +3405 -0
  8. package/dist/standard-preset.d.ts +7 -0
  9. package/dist/standard-preset.js +25 -0
  10. package/engine-release.json +14 -0
  11. package/package.json +119 -0
  12. package/presets/standard/agent.cordis.yml +6 -0
  13. package/presets/standard/preset.yml +2 -0
  14. package/vendor/nanocodex/README.md +1344 -0
  15. package/vendor/nanocodex/actions/events.d.mts +10 -0
  16. package/vendor/nanocodex/actions/events.mjs +163 -0
  17. package/vendor/nanocodex/actions/index.d.mts +13 -0
  18. package/vendor/nanocodex/actions/index.mjs +35 -0
  19. package/vendor/nanocodex/actions/session.d.mts +66 -0
  20. package/vendor/nanocodex/actions/session.mjs +59 -0
  21. package/vendor/nanocodex/actions/turn.d.mts +59 -0
  22. package/vendor/nanocodex/actions/turn.mjs +37 -0
  23. package/vendor/nanocodex/actions/voice.d.mts +22 -0
  24. package/vendor/nanocodex/actions/voice.mjs +50 -0
  25. package/vendor/nanocodex/browser/Agent.d.mts +55 -0
  26. package/vendor/nanocodex/browser/Agent.mjs +11 -0
  27. package/vendor/nanocodex/browser/ChatGptSubscription.d.mts +7 -0
  28. package/vendor/nanocodex/browser/ChatGptSubscription.mjs +19 -0
  29. package/vendor/nanocodex/browser/InlineAgent.mjs +266 -0
  30. package/vendor/nanocodex/browser/Transport.d.mts +74 -0
  31. package/vendor/nanocodex/browser/Transport.mjs +61 -0
  32. package/vendor/nanocodex/browser/Voice.d.mts +71 -0
  33. package/vendor/nanocodex/browser/Voice.mjs +291 -0
  34. package/vendor/nanocodex/browser/VoiceSession.mjs +688 -0
  35. package/vendor/nanocodex/browser/WorkerAgent.d.mts +65 -0
  36. package/vendor/nanocodex/browser/WorkerAgent.mjs +1472 -0
  37. package/vendor/nanocodex/browser/agent.worker.mjs +3 -0
  38. package/vendor/nanocodex/browser/config.d.mts +36 -0
  39. package/vendor/nanocodex/browser/config.mjs +439 -0
  40. package/vendor/nanocodex/browser/engine.mjs +13 -0
  41. package/vendor/nanocodex/browser/harness.mjs +55 -0
  42. package/vendor/nanocodex/browser/host.d.mts +83 -0
  43. package/vendor/nanocodex/browser/host.mjs +555 -0
  44. package/vendor/nanocodex/browser/hostManagedWebSocket.d.mts +14 -0
  45. package/vendor/nanocodex/browser/hostManagedWebSocket.mjs +110 -0
  46. package/vendor/nanocodex/browser/index.d.mts +92 -0
  47. package/vendor/nanocodex/browser/index.mjs +23 -0
  48. package/vendor/nanocodex/browser/indexeddb-durability-store.mjs +197 -0
  49. package/vendor/nanocodex/browser/workspace.d.mts +16 -0
  50. package/vendor/nanocodex/browser/workspace.mjs +107 -0
  51. package/vendor/nanocodex/cloud/Client.d.mts +83 -0
  52. package/vendor/nanocodex/cloud/Client.mjs +231 -0
  53. package/vendor/nanocodex/cloud/Decorator.d.mts +31 -0
  54. package/vendor/nanocodex/cloud/Decorator.mjs +37 -0
  55. package/vendor/nanocodex/cloud/Dialog.d.mts +113 -0
  56. package/vendor/nanocodex/cloud/Dialog.mjs +366 -0
  57. package/vendor/nanocodex/cloud/Errors.d.mts +22 -0
  58. package/vendor/nanocodex/cloud/Errors.mjs +39 -0
  59. package/vendor/nanocodex/cloud/Principal.d.mts +26 -0
  60. package/vendor/nanocodex/cloud/Principal.mjs +88 -0
  61. package/vendor/nanocodex/cloud/RemoteProvider.mjs +88 -0
  62. package/vendor/nanocodex/cloud/Transport.d.mts +47 -0
  63. package/vendor/nanocodex/cloud/Transport.mjs +454 -0
  64. package/vendor/nanocodex/cloud/actions/account.d.mts +9 -0
  65. package/vendor/nanocodex/cloud/actions/account.mjs +19 -0
  66. package/vendor/nanocodex/cloud/actions/agent.d.mts +18 -0
  67. package/vendor/nanocodex/cloud/actions/agent.mjs +428 -0
  68. package/vendor/nanocodex/cloud/actions/connection.d.mts +133 -0
  69. package/vendor/nanocodex/cloud/actions/connection.mjs +580 -0
  70. package/vendor/nanocodex/cloud/actions/grant.d.mts +10 -0
  71. package/vendor/nanocodex/cloud/actions/grant.mjs +12 -0
  72. package/vendor/nanocodex/cloud/actions/index.d.mts +7 -0
  73. package/vendor/nanocodex/cloud/actions/index.mjs +7 -0
  74. package/vendor/nanocodex/cloud/actions/machineUsd.d.mts +23 -0
  75. package/vendor/nanocodex/cloud/actions/machineUsd.mjs +37 -0
  76. package/vendor/nanocodex/cloud/actions/model.d.mts +12 -0
  77. package/vendor/nanocodex/cloud/actions/model.mjs +50 -0
  78. package/vendor/nanocodex/cloud/actions/mpp.d.mts +28 -0
  79. package/vendor/nanocodex/cloud/actions/mpp.mjs +39 -0
  80. package/vendor/nanocodex/cloud/index.d.mts +30 -0
  81. package/vendor/nanocodex/cloud/index.mjs +9 -0
  82. package/vendor/nanocodex/cloud/internal.mjs +533 -0
  83. package/vendor/nanocodex/cloud/mercator.mjs +108 -0
  84. package/vendor/nanocodex/cloud/server/HostPrincipal.d.mts +34 -0
  85. package/vendor/nanocodex/cloud/server/HostPrincipal.mjs +202 -0
  86. package/vendor/nanocodex/cloud/server/index.d.mts +1 -0
  87. package/vendor/nanocodex/cloud/server/index.mjs +1 -0
  88. package/vendor/nanocodex/cloud/types.d.mts +211 -0
  89. package/vendor/nanocodex/cloudflare/Agent.d.mts +133 -0
  90. package/vendor/nanocodex/cloudflare/Agent.mjs +811 -0
  91. package/vendor/nanocodex/cloudflare/egress-subject.mjs +19 -0
  92. package/vendor/nanocodex/cloudflare/egress.d.mts +41 -0
  93. package/vendor/nanocodex/cloudflare/egress.mjs +119 -0
  94. package/vendor/nanocodex/cloudflare/event-socket.mjs +316 -0
  95. package/vendor/nanocodex/cloudflare/index.d.mts +7 -0
  96. package/vendor/nanocodex/cloudflare/index.mjs +6 -0
  97. package/vendor/nanocodex/host/Agent.d.mts +55 -0
  98. package/vendor/nanocodex/host/Agent.mjs +1 -0
  99. package/vendor/nanocodex/host/index.d.mts +82 -0
  100. package/vendor/nanocodex/host/index.mjs +10 -0
  101. package/vendor/nanocodex/index.d.mts +81 -0
  102. package/vendor/nanocodex/index.mjs +12 -0
  103. package/vendor/nanocodex/internal.mjs +1275 -0
  104. package/vendor/nanocodex/managed/Agent.d.mts +380 -0
  105. package/vendor/nanocodex/managed/Agent.mjs +1694 -0
  106. package/vendor/nanocodex/managed/ManagedError.d.mts +9 -0
  107. package/vendor/nanocodex/managed/ManagedError.mjs +8 -0
  108. package/vendor/nanocodex/managed/README.md +241 -0
  109. package/vendor/nanocodex/managed/Voice.mjs +202 -0
  110. package/vendor/nanocodex/managed/index.d.mts +20 -0
  111. package/vendor/nanocodex/managed/index.mjs +2 -0
  112. package/vendor/nanocodex/managed/internal.mjs +119 -0
  113. package/vendor/nanocodex/node/Agent.d.mts +50 -0
  114. package/vendor/nanocodex/node/Agent.mjs +203 -0
  115. package/vendor/nanocodex/node/ChatGptSubscription.d.mts +9 -0
  116. package/vendor/nanocodex/node/ChatGptSubscription.mjs +17 -0
  117. package/vendor/nanocodex/node/Transport.d.mts +44 -0
  118. package/vendor/nanocodex/node/Transport.mjs +46 -0
  119. package/vendor/nanocodex/node/host.mjs +731 -0
  120. package/vendor/nanocodex/node/index.d.mts +73 -0
  121. package/vendor/nanocodex/node/index.mjs +17 -0
  122. package/vendor/nanocodex/node/workspace.d.mts +10 -0
  123. package/vendor/nanocodex/node/workspace.mjs +198 -0
  124. package/vendor/nanocodex/package.json +200 -0
  125. package/vendor/nanocodex/pkg-node/nanocodex.d.ts +675 -0
  126. package/vendor/nanocodex/pkg-node/nanocodex.js +2628 -0
  127. package/vendor/nanocodex/pkg-node/nanocodex_bg.wasm.d.ts +105 -0
  128. package/vendor/nanocodex/pkg-node/package.json +1 -0
  129. package/vendor/nanocodex/pkg-web/.nanocodex-bindgen-stamp +6 -0
  130. package/vendor/nanocodex/pkg-web/nanocodex-build.json +1 -0
  131. package/vendor/nanocodex/pkg-web/nanocodex.d.ts +805 -0
  132. package/vendor/nanocodex/pkg-web/nanocodex.js +2714 -0
  133. package/vendor/nanocodex/pkg-web/nanocodex_bg.js +2615 -0
  134. package/vendor/nanocodex/pkg-web/nanocodex_bg.wasm +0 -0
  135. package/vendor/nanocodex/pkg-web/nanocodex_bg.wasm.d.ts +105 -0
  136. package/vendor/nanocodex/pkg-web/nanocodex_worker.js +9 -0
  137. package/vendor/nanocodex/pkg-web/package.json +1 -0
  138. package/vendor/nanocodex/runtime/chatgpt-subscription.mjs +212 -0
  139. package/vendor/nanocodex/runtime/cloudflare-durability-store.d.mts +26 -0
  140. package/vendor/nanocodex/runtime/cloudflare-durability-store.mjs +168 -0
  141. package/vendor/nanocodex/runtime/code-evaluator.worker.mjs +137 -0
  142. package/vendor/nanocodex/runtime/code-runtime.mjs +1 -0
  143. package/vendor/nanocodex/runtime/durability-store.d.mts +85 -0
  144. package/vendor/nanocodex/runtime/durability-store.mjs +631 -0
  145. package/vendor/nanocodex/runtime/durability.mjs +153 -0
  146. package/vendor/nanocodex/runtime/managed-transport.mjs +460 -0
  147. package/vendor/nanocodex/runtime/mcp-runtime.mjs +534 -0
  148. package/vendor/nanocodex/runtime/postgres-durability-store.d.mts +64 -0
  149. package/vendor/nanocodex/runtime/postgres-durability-store.mjs +532 -0
  150. package/vendor/nanocodex/runtime/quickjs-evaluator.d.mts +17 -0
  151. package/vendor/nanocodex/runtime/quickjs-evaluator.mjs +236 -0
  152. package/vendor/nanocodex/runtime/responses-transport.mjs +22 -0
  153. package/vendor/nanocodex/runtime/subagents.d.mts +107 -0
  154. package/vendor/nanocodex/runtime/subagents.mjs +54 -0
  155. package/vendor/nanocodex/runtime/subscription-store.d.mts +8 -0
  156. package/vendor/nanocodex/runtime/subscription-store.mjs +42 -0
  157. package/vendor/nanocodex/runtime/tempo-provider.d.mts +125 -0
  158. package/vendor/nanocodex/runtime/tempo-provider.mjs +264 -0
  159. package/vendor/nanocodex/runtime/tool-configuration.mjs +1 -0
  160. package/vendor/nanocodex/runtime/tool-router.mjs +1 -0
  161. package/vendor/nanocodex/runtime/utf8.mjs +1 -0
  162. package/vendor/nanocodex/runtime/worker-evaluator.mjs +162 -0
  163. package/vendor/nanocodex/runtime/workspace.d.mts +1 -0
  164. package/vendor/nanocodex/runtime/workspace.mjs +1 -0
  165. package/vendor/nanocodex/tools/Tools.d.mts +56 -0
  166. package/vendor/nanocodex/tools/Tools.mjs +136 -0
  167. package/vendor/nanocodex/tools/artifact.d.mts +1 -0
  168. package/vendor/nanocodex/tools/artifact.mjs +1 -0
  169. package/vendor/nanocodex/tools/attachment.mjs +1 -0
  170. package/vendor/nanocodex/tools/bash.d.mts +1 -0
  171. package/vendor/nanocodex/tools/bash.mjs +1 -0
  172. package/vendor/nanocodex/tools/browser/accountInfo.mjs +795 -0
  173. package/vendor/nanocodex/tools/browser/browserBuffer.mjs +18 -0
  174. package/vendor/nanocodex/tools/browser/browserCompiler.mjs +155 -0
  175. package/vendor/nanocodex/tools/browser/browserEgress.mjs +161 -0
  176. package/vendor/nanocodex/tools/browser/browserPython.mjs +133 -0
  177. package/vendor/nanocodex/tools/browser/browserShell.mjs +1075 -0
  178. package/vendor/nanocodex/tools/browser/browserSprintf.mjs +4 -0
  179. package/vendor/nanocodex/tools/browser/browserSsh.mjs +201 -0
  180. package/vendor/nanocodex/tools/browser/browserZlib.mjs +136 -0
  181. package/vendor/nanocodex/tools/browser/compiler.worker.mjs +160 -0
  182. package/vendor/nanocodex/tools/browser/devTunnelsSshBrowser.mjs +13 -0
  183. package/vendor/nanocodex/tools/browser/index.d.mts +209 -0
  184. package/vendor/nanocodex/tools/browser/index.mjs +174 -0
  185. package/vendor/nanocodex/tools/browser/opfsGit.mjs +248 -0
  186. package/vendor/nanocodex/tools/browser/python.worker.mjs +114 -0
  187. package/vendor/nanocodex/tools/browser/threadGit.mjs +197 -0
  188. package/vendor/nanocodex/tools/browser/unsupportedNodeRsa.mjs +5 -0
  189. package/vendor/nanocodex/tools/browser/workspace.mjs +83 -0
  190. package/vendor/nanocodex/tools/dataset.d.mts +1 -0
  191. package/vendor/nanocodex/tools/dataset.mjs +1 -0
  192. package/vendor/nanocodex/tools/datasetContract.mjs +1 -0
  193. package/vendor/nanocodex/tools/datasetEngine.mjs +1 -0
  194. package/vendor/nanocodex/tools/hostedCatalog.d.mts +1 -0
  195. package/vendor/nanocodex/tools/hostedCatalog.mjs +1 -0
  196. package/vendor/nanocodex/tools/index.d.mts +49 -0
  197. package/vendor/nanocodex/tools/index.mjs +19 -0
  198. package/vendor/nanocodex/tools/namedTool.mjs +1 -0
  199. package/vendor/nanocodex/tools/repository-workspace.d.mts +1 -0
  200. package/vendor/nanocodex/tools/repository-workspace.mjs +1 -0
  201. package/vendor/nanocodex/tools/ssh.d.mts +1 -0
  202. package/vendor/nanocodex/tools/ssh.mjs +1 -0
  203. package/vendor/nanocodex/tools/standard.mjs +1 -0
  204. package/vendor/nanocodex/tools/standardDescriptions.mjs +1 -0
  205. package/vendor/nanocodex/types.d.mts +663 -0
  206. package/vendor/nanocodex/wasm.d.mts +4 -0
  207. package/vendor/nanocodex/worker/ChatGptSubscription.d.mts +9 -0
  208. package/vendor/nanocodex/worker/ChatGptSubscription.mjs +29 -0
  209. package/vendor/nanocodex/worker/index.d.mts +18 -0
  210. package/vendor/nanocodex/worker/index.mjs +5 -0
  211. package/vendor/nanocodex-tools/README.md +65 -0
  212. package/vendor/nanocodex-tools/dist/hosted/app-tool-catalog.d.ts +7 -0
  213. package/vendor/nanocodex-tools/dist/hosted/app-tool-catalog.js +14 -0
  214. package/vendor/nanocodex-tools/dist/hosted/broker-core.d.ts +172 -0
  215. package/vendor/nanocodex-tools/dist/hosted/broker-core.js +1278 -0
  216. package/vendor/nanocodex-tools/dist/hosted/index.d.ts +3 -0
  217. package/vendor/nanocodex-tools/dist/hosted/index.js +3 -0
  218. package/vendor/nanocodex-tools/dist/hosted/protocol.d.ts +120 -0
  219. package/vendor/nanocodex-tools/dist/hosted/protocol.js +415 -0
  220. package/vendor/nanocodex-tools/dist/index.d.ts +19 -0
  221. package/vendor/nanocodex-tools/dist/index.js +14 -0
  222. package/vendor/nanocodex-tools/dist/memory.d.ts +204 -0
  223. package/vendor/nanocodex-tools/dist/memory.js +411 -0
  224. package/vendor/nanocodex-tools/dist/namespace.d.ts +87 -0
  225. package/vendor/nanocodex-tools/dist/namespace.js +338 -0
  226. package/vendor/nanocodex-tools/dist/repository-archive.d.ts +4 -0
  227. package/vendor/nanocodex-tools/dist/repository-archive.js +104 -0
  228. package/vendor/nanocodex-tools/dist/runtime.d.ts +30 -0
  229. package/vendor/nanocodex-tools/dist/runtime.js +37 -0
  230. package/vendor/nanocodex-tools/dist/session.d.ts +167 -0
  231. package/vendor/nanocodex-tools/dist/session.js +286 -0
  232. package/vendor/nanocodex-tools/dist/shell.d.ts +51 -0
  233. package/vendor/nanocodex-tools/dist/shell.js +553 -0
  234. package/vendor/nanocodex-tools/dist/ssh.d.ts +29 -0
  235. package/vendor/nanocodex-tools/dist/ssh.js +66 -0
  236. package/vendor/nanocodex-tools/dist/workspace.d.ts +45 -0
  237. package/vendor/nanocodex-tools/dist/workspace.js +237 -0
  238. package/vendor/nanocodex-tools/package.json +122 -0
  239. package/vendor/nanocodex-tools/runtime/code-runtime.mjs +817 -0
  240. package/vendor/nanocodex-tools/runtime/tool-configuration.mjs +50 -0
  241. package/vendor/nanocodex-tools/runtime/tool-router.mjs +730 -0
  242. package/vendor/nanocodex-tools/runtime/utf8.d.mts +2 -0
  243. package/vendor/nanocodex-tools/runtime/utf8.mjs +25 -0
  244. package/vendor/nanocodex-tools/tools/artifact.d.mts +69 -0
  245. package/vendor/nanocodex-tools/tools/artifact.mjs +270 -0
  246. package/vendor/nanocodex-tools/tools/attachment.mjs +603 -0
  247. package/vendor/nanocodex-tools/tools/bash.d.mts +90 -0
  248. package/vendor/nanocodex-tools/tools/bash.mjs +742 -0
  249. package/vendor/nanocodex-tools/tools/dataset.d.mts +9 -0
  250. package/vendor/nanocodex-tools/tools/dataset.mjs +47 -0
  251. package/vendor/nanocodex-tools/tools/datasetContract.mjs +54 -0
  252. package/vendor/nanocodex-tools/tools/datasetEngine.mjs +1167 -0
  253. package/vendor/nanocodex-tools/tools/execution-contract.d.mts +5 -0
  254. package/vendor/nanocodex-tools/tools/execution-contract.mjs +63 -0
  255. package/vendor/nanocodex-tools/tools/hostedCatalog.d.mts +20 -0
  256. package/vendor/nanocodex-tools/tools/hostedCatalog.mjs +67 -0
  257. package/vendor/nanocodex-tools/tools/hostedMachine.d.mts +10 -0
  258. package/vendor/nanocodex-tools/tools/hostedMachine.mjs +56 -0
  259. package/vendor/nanocodex-tools/tools/just-bash-browser.d.mts +1 -0
  260. package/vendor/nanocodex-tools/tools/just-bash-browser.mjs +1 -0
  261. package/vendor/nanocodex-tools/tools/namedTool.d.mts +3 -0
  262. package/vendor/nanocodex-tools/tools/namedTool.mjs +3 -0
  263. package/vendor/nanocodex-tools/tools/nodeProcess.d.mts +10 -0
  264. package/vendor/nanocodex-tools/tools/nodeProcess.mjs +314 -0
  265. package/vendor/nanocodex-tools/tools/processOutput.mjs +56 -0
  266. package/vendor/nanocodex-tools/tools/repository-workspace.d.mts +55 -0
  267. package/vendor/nanocodex-tools/tools/repository-workspace.mjs +397 -0
  268. package/vendor/nanocodex-tools/tools/ssh.d.mts +56 -0
  269. package/vendor/nanocodex-tools/tools/ssh.mjs +503 -0
  270. package/vendor/nanocodex-tools/tools/standard.mjs +458 -0
  271. package/vendor/nanocodex-tools/tools/standardDescriptions.mjs +3 -0
  272. package/vendor/nanocodex-tools/tools/types.d.mts +83 -0
  273. package/vendor/nanocodex-tools/tools/workspace.d.mts +25 -0
  274. package/vendor/nanocodex-tools/tools/workspace.mjs +282 -0
  275. package/vendor/nanocodex-tools/tools/x.d.mts +30 -0
  276. package/vendor/nanocodex-tools/tools/x.mjs +91 -0
@@ -0,0 +1,811 @@
1
+ import * as HostAgent from "../host/Agent.mjs";
2
+ import {
3
+ CLOUDFLARE_SESSION_RESERVATION,
4
+ commitCloudflareAgentSession,
5
+ installHostBridge,
6
+ loadDurabilityRuntime,
7
+ mayBindCloudflareSubagentSession,
8
+ mayReleaseCloudflareSubagentSession,
9
+ observeAgentRelease,
10
+ prepareCloudflareAgentSession,
11
+ releaseAgentSession,
12
+ routePrompt,
13
+ } from "../internal.mjs";
14
+ import { pruneDurableReceipts as pruneWasmDurableReceipts, managedBootstrapPlan } from "../pkg-web/nanocodex.js";
15
+ import * as Transport from "../browser/Transport.mjs";
16
+ import { initializeBrowserEngine } from "../browser/engine.mjs";
17
+ import { createCloudflareDurabilityStore } from "../runtime/cloudflare-durability-store.mjs";
18
+ import {
19
+ createMemoryDurabilityStore,
20
+ durabilityRevision,
21
+ exportDurabilityState as exportPortableState,
22
+ exportDurabilityStatePage as exportPortableStatePage,
23
+ importDurabilityState as importPortableState,
24
+ } from "../runtime/durability-store.mjs";
25
+ import { cloudflareEgress } from "./egress.mjs";
26
+ import { scopeCloudflareEgress } from "./egress-subject.mjs";
27
+ import {
28
+ clearCloudflareEventSocket,
29
+ createCloudflareEventSocket,
30
+ } from "./event-socket.mjs";
31
+
32
+ const STARTUP_TIMEOUT_MS = 10_000;
33
+ const INTERNAL_RUNTIME = Symbol.for("nanocodex.cloudflare.internalRuntime");
34
+ const INTERNAL_CONFIGURATION = Symbol.for("nanocodex.cloudflare.internalConfiguration");
35
+ const EPHEMERAL_APPLICATION_OPTIONS = new Set([
36
+ "additionalInstructions",
37
+ "fastMode",
38
+ "instructions",
39
+ "model",
40
+ "reasoningMode",
41
+ "resume",
42
+ "sessionId",
43
+ "thinking",
44
+ "tools",
45
+ "workspace",
46
+ ]);
47
+ const APPLICATION_OPTIONS = new Set([
48
+ "additionalInstructions",
49
+ "durabilityId",
50
+ "eventPersistence",
51
+ "instructions",
52
+ "terminalReceiptRetention",
53
+ "tools",
54
+ ]);
55
+ const lifecycles = new WeakMap();
56
+
57
+ /** @internal Binds the package-owned module to the public Cloudflare namespace. */
58
+ export function bindAgent(module, hostAgent = HostAgent) {
59
+ return Object.freeze({
60
+ bootstrapPlan: async (input) => {
61
+ await initializeBrowserEngine({ module });
62
+ return JSON.parse(managedBootstrapPlan(input));
63
+ },
64
+ pruneDurableReceipts: (owner, options) => pruneDurableReceipts(module, owner, options),
65
+ create: (owner, options) => create(module, owner, options, hostAgent),
66
+ createEphemeral: (owner, options) => createEphemeral(module, owner, options),
67
+ destroy,
68
+ exportDurabilityState,
69
+ importDurabilityState: (owner, archive) => importDurabilityState(owner, archive, module),
70
+ route,
71
+ });
72
+ }
73
+
74
+ /** Atomically steers an active Cloudflare Agent turn or starts a new turn. */
75
+ export function route(agent, options) {
76
+ return routePrompt(agent, options);
77
+ }
78
+
79
+ /** Removes the package-owned durable history for one Cloudflare Agent. */
80
+ export function destroy(owner) {
81
+ const context = resolveContext(owner);
82
+ const lifecycle = lifecycles.get(context);
83
+ if (lifecycle?.creating) {
84
+ throw new Error("Cloudflare Agent creation must settle before destroy");
85
+ }
86
+ if (lifecycle?.active !== undefined) {
87
+ throw new Error("Cloudflare Agent shutdown must complete before destroy");
88
+ }
89
+ const storage = context.storage;
90
+ createCloudflareDurabilityStore(storage);
91
+ initializeAgentStorage(storage);
92
+ const stateId = storedStateId(storage) ?? legacyStateId(storage);
93
+ storage.transactionSync(() => {
94
+ if (stateId !== undefined) {
95
+ const retained = storage.sql.exec(
96
+ "SELECT fence FROM nanocodex_durable_owners WHERE state_id = ?",
97
+ stateId,
98
+ ).toArray();
99
+ const fence = durabilityRevision(
100
+ BigInt(durabilityRevision(retained[0]?.fence ?? "0")) + 1n,
101
+ );
102
+ storage.sql.exec(
103
+ `INSERT INTO nanocodex_durable_owners (state_id, owner_id, fence) VALUES (?, ?, ?)
104
+ ON CONFLICT (state_id) DO UPDATE SET owner_id = excluded.owner_id, fence = excluded.fence`,
105
+ stateId,
106
+ `destroy:${globalThis.crypto.randomUUID()}`,
107
+ fence,
108
+ );
109
+ storage.sql.exec(
110
+ "DELETE FROM nanocodex_durable_chunk_heads WHERE state_id = ?",
111
+ stateId,
112
+ );
113
+ storage.sql.exec(
114
+ "DELETE FROM nanocodex_durable_state_chunks WHERE state_id = ?",
115
+ stateId,
116
+ );
117
+ storage.sql.exec(
118
+ "DELETE FROM nanocodex_durable_states WHERE state_id = ?",
119
+ stateId,
120
+ );
121
+ }
122
+ storage.sql.exec("DELETE FROM nanocodex_cloudflare_subagents");
123
+ clearCloudflareEventSocket(context);
124
+ });
125
+ }
126
+
127
+ /** Fences and exports this inactive Cloudflare Agent's provider-neutral state. */
128
+ export async function exportDurabilityState(owner, request) {
129
+ const context = reserveInactiveLifecycle(owner, "exporting durability state");
130
+ try {
131
+ const storage = context.storage;
132
+ const durability = createCloudflareDurabilityStore(storage);
133
+ initializeAgentStorage(storage);
134
+ const stateId = storedStateId(storage) ?? legacyStateId(storage);
135
+ if (stateId === undefined) {
136
+ throw new Error("Cloudflare Agent has no durability state to export");
137
+ }
138
+ return request === undefined
139
+ ? await exportPortableState(durability, stateId)
140
+ : await exportPortableStatePage(durability, stateId, request);
141
+ } finally {
142
+ lifecycleFor(context).creating = false;
143
+ }
144
+ }
145
+
146
+ /** Imports provider-neutral state into a pristine Cloudflare Agent owner. */
147
+ export async function importDurabilityState(owner, archive, module) {
148
+ const context = reserveInactiveLifecycle(owner, "importing durability state");
149
+ try {
150
+ const storage = context.storage;
151
+ const durability = createCloudflareDurabilityStore(storage);
152
+ initializeAgentStorage(storage);
153
+ const validationStateId = typeof archive?.stateId === "string" && archive.stateId
154
+ ? archive.stateId
155
+ : "nanocodex-invalid-import";
156
+ const validationStore = createMemoryDurabilityStore(validationStateId);
157
+ const validated = await importPortableState(validationStore, archive);
158
+ if (module !== undefined) {
159
+ const routeHost = {};
160
+ const route = (await loadDurabilityRuntime()).own(
161
+ routeHost,
162
+ validationStore,
163
+ validationStateId,
164
+ );
165
+ try {
166
+ installHostBridge();
167
+ await initializeBrowserEngine({ module });
168
+ // Opening the Rust durability session validates the complete canonical
169
+ // state. Pruning happens only in this throwaway memory copy.
170
+ await pruneWasmDurableReceipts(route.id, validationStateId, 4_096);
171
+ } finally {
172
+ route.abandon();
173
+ }
174
+ }
175
+ const retainedSessionId = storedSessionId(storage);
176
+ const retainedStateId = storedStateId(storage);
177
+ if (retainedSessionId !== undefined || retainedStateId !== undefined) {
178
+ if (retainedSessionId !== undefined
179
+ && retainedStateId === archive?.stateId
180
+ && archive?.format === "nanocodex-durability-state-v1") {
181
+ const retained = await durability.load(retainedStateId);
182
+ if (retained.revision === validated.revision
183
+ && retained.payload === validated.payload) {
184
+ return retained;
185
+ }
186
+ }
187
+ throw new Error("Cloudflare Agent durability import requires a pristine Durable Object");
188
+ }
189
+ const imported = await importPortableState(durability, archive);
190
+ const sessionId = uuidV7();
191
+ try {
192
+ storage.transactionSync(() => {
193
+ storage.sql.exec(
194
+ "INSERT INTO nanocodex_cloudflare_agent (singleton, session_id) VALUES (1, ?)",
195
+ sessionId,
196
+ );
197
+ storage.sql.exec(
198
+ "INSERT INTO nanocodex_cloudflare_durability (singleton, state_id) VALUES (1, ?)",
199
+ archive.stateId,
200
+ );
201
+ });
202
+ } catch (error) {
203
+ try {
204
+ storage.transactionSync(() => {
205
+ storage.sql.exec(
206
+ "DELETE FROM nanocodex_durable_chunk_heads WHERE state_id = ?",
207
+ archive.stateId,
208
+ );
209
+ storage.sql.exec(
210
+ "DELETE FROM nanocodex_durable_state_chunks WHERE state_id = ?",
211
+ archive.stateId,
212
+ );
213
+ storage.sql.exec(
214
+ "DELETE FROM nanocodex_durable_states WHERE state_id = ?",
215
+ archive.stateId,
216
+ );
217
+ storage.sql.exec(
218
+ "DELETE FROM nanocodex_durable_owners WHERE state_id = ?",
219
+ archive.stateId,
220
+ );
221
+ });
222
+ } catch (rollbackError) {
223
+ throw new AggregateError(
224
+ [error, rollbackError],
225
+ "Cloudflare Agent durability import metadata and rollback both failed",
226
+ );
227
+ }
228
+ throw error;
229
+ }
230
+ return imported;
231
+ } finally {
232
+ lifecycleFor(context).creating = false;
233
+ }
234
+ }
235
+
236
+ function reserveInactiveLifecycle(owner, operation) {
237
+ const context = resolveContext(owner);
238
+ const lifecycle = lifecycleFor(context);
239
+ if (lifecycle.creating) {
240
+ throw new Error("Cloudflare Agent lifecycle operation is already in progress");
241
+ }
242
+ if (lifecycle.active !== undefined) {
243
+ throw new Error(`Cloudflare Agent shutdown must complete before ${operation}`);
244
+ }
245
+ lifecycle.creating = true;
246
+ return context;
247
+ }
248
+
249
+ /** Prunes old terminal receipts before constructing the full Agent runtime. */
250
+ export async function pruneDurableReceipts(module, owner, options = {}) {
251
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
252
+ throw new TypeError("Cloudflare durability receipt-pruning options must be an object");
253
+ }
254
+ const terminalReceiptRetention = options.terminalReceiptRetention ?? 512;
255
+ if (!Number.isSafeInteger(terminalReceiptRetention)
256
+ || terminalReceiptRetention < 0
257
+ || terminalReceiptRetention > 4_096) {
258
+ throw new TypeError("terminalReceiptRetention must be an integer from 0 through 4096");
259
+ }
260
+ const context = resolveContext(owner);
261
+ const lifecycle = lifecycleFor(context);
262
+ if (lifecycle.creating) {
263
+ throw new Error("Cloudflare Agent lifecycle operation is already in progress");
264
+ }
265
+ if (lifecycle.active !== undefined) {
266
+ throw new Error("Cloudflare Agent shutdown must complete before pruning durability receipts");
267
+ }
268
+ lifecycle.creating = true;
269
+ try {
270
+ const storage = context.storage;
271
+ const durability = createCloudflareDurabilityStore(storage);
272
+ initializeAgentStorage(storage);
273
+ const stateId = storedStateId(storage) ?? legacyStateId(storage);
274
+ if (stateId === undefined) return;
275
+ const routeHost = {};
276
+ const route = (await loadDurabilityRuntime()).own(
277
+ routeHost,
278
+ durability,
279
+ stateId,
280
+ );
281
+ try {
282
+ installHostBridge();
283
+ await initializeBrowserEngine({ module });
284
+ await pruneWasmDurableReceipts(route.id, stateId, terminalReceiptRetention);
285
+ } finally {
286
+ route.abandon();
287
+ }
288
+ } finally {
289
+ lifecycle.creating = false;
290
+ }
291
+ }
292
+
293
+ /** @internal Creates one Agent with an explicitly supplied package module. */
294
+ export async function create(module, owner, options = {}, hostAgent = HostAgent) {
295
+ const resolved = resolveOwner(owner);
296
+ const lifecycle = lifecycleFor(resolved.context);
297
+ if (lifecycle.creating) {
298
+ throw new Error("Cloudflare Agent creation is already in progress for this Durable Object");
299
+ }
300
+ if (lifecycle.active !== undefined) {
301
+ throw new Error("Cloudflare Agent shutdown must complete before create");
302
+ }
303
+ lifecycle.creating = true;
304
+ try {
305
+ return await createOwned(module, resolved, options, hostAgent, lifecycle);
306
+ } finally {
307
+ lifecycle.creating = false;
308
+ }
309
+ }
310
+
311
+ async function createOwned(module, resolved, options, hostAgent, lifecycle) {
312
+ const { context, egress, subject } = resolved;
313
+ const configured = applicationOptions(options);
314
+ const {
315
+ durabilityId,
316
+ eventPersistence = "durable",
317
+ [INTERNAL_RUNTIME]: internalRuntime,
318
+ [INTERNAL_CONFIGURATION]: internalConfiguration,
319
+ ...agentOptions
320
+ } = configured;
321
+ if (internalRuntime !== undefined
322
+ && (!internalRuntime || typeof internalRuntime !== "object" || Array.isArray(internalRuntime))) {
323
+ throw new TypeError("Cloudflare Agent internal runtime options must be an object");
324
+ }
325
+ if (internalRuntime?.subagentLifecycle !== undefined
326
+ && typeof internalRuntime.subagentLifecycle !== "function") {
327
+ throw new TypeError("Cloudflare Agent subagent lifecycle hook must be a function");
328
+ }
329
+ if (internalRuntime?.waitForPreconnect !== undefined
330
+ && typeof internalRuntime.waitForPreconnect !== "boolean") {
331
+ throw new TypeError("Cloudflare Agent internal waitForPreconnect must be a boolean");
332
+ }
333
+ validateInternalConfiguration(internalConfiguration);
334
+ const eventSocket = eventPersistence === "durable"
335
+ ? createCloudflareEventSocket(context)
336
+ : undefined;
337
+ if (eventPersistence === "caller") clearCloudflareEventSocket(context);
338
+ const durability = createCloudflareDurabilityStore(context.storage);
339
+ const { sessionId, stateId } = durableIdentity(context.storage, durabilityId);
340
+ const endpoint = cloudflareEgress({
341
+ binding: scopeCloudflareEgress(egress, subject),
342
+ });
343
+ const startup = deferred();
344
+ const transport = Transport.hostManaged({
345
+ ...endpoint,
346
+ websocketPreconnect: true,
347
+ async createWebSocket(url, id, request) {
348
+ try {
349
+ const opened = await endpoint.createWebSocket(url, id, request);
350
+ if (request.authorization === "preconnect") startup.resolve();
351
+ return opened;
352
+ } catch (error) {
353
+ if (request.authorization === "preconnect") startup.reject(error);
354
+ throw error;
355
+ }
356
+ },
357
+ });
358
+
359
+ const sessionReservation = prepareCloudflareAgentSession(sessionId, subject);
360
+ const subagentSessions = cloudflareSubagentSessions(
361
+ context.storage,
362
+ sessionReservation,
363
+ internalRuntime?.subagentLifecycle,
364
+ );
365
+ let agent;
366
+ let watcher;
367
+ let unwatch;
368
+ try {
369
+ agent = await hostAgent.create({
370
+ ...agentOptions,
371
+ ...(internalConfiguration === undefined ? {} : {
372
+ model: internalConfiguration.model,
373
+ thinking: internalConfiguration.thinking,
374
+ reasoningMode: internalConfiguration.reasoning_mode,
375
+ fastMode: internalConfiguration.fast_mode,
376
+ }),
377
+ module,
378
+ toolMode: internalRuntime?.toolMode ?? "direct",
379
+ codeEvaluator: internalRuntime?.codeEvaluator,
380
+ [Symbol.for("nanocodex.browser.internalRuntime")]: {
381
+ toolProviders: internalRuntime?.toolProviders,
382
+ subagentMaxConcurrency: internalRuntime?.subagentMaxConcurrency,
383
+ subagentSessions,
384
+ [CLOUDFLARE_SESSION_RESERVATION]: sessionReservation,
385
+ },
386
+ transport,
387
+ sessionId,
388
+ durability,
389
+ durabilityId: stateId,
390
+ });
391
+ // Managed voice needs the durable session before the separate Responses
392
+ // relay is ready. Its preconnection remains owned by the host and a later
393
+ // text turn consumes it through the same credential-checked transport.
394
+ if (internalRuntime?.waitForPreconnect !== false) {
395
+ await withTimeout(
396
+ startup.promise,
397
+ STARTUP_TIMEOUT_MS,
398
+ "Cloudflare Agent EGRESS startup validation timed out",
399
+ );
400
+ }
401
+
402
+ if (eventSocket !== undefined) {
403
+ watcher = agent.events.watch();
404
+ unwatch = watcher.onEvent((event) => {
405
+ try {
406
+ eventSocket.publish(event);
407
+ } catch (error) {
408
+ unwatch?.();
409
+ eventSocket.fail(error);
410
+ console.error("Nanocodex Cloudflare event projection failed", error);
411
+ }
412
+ });
413
+ }
414
+ const exposed = agent.extend((owned) => ({
415
+ events: {
416
+ connect: (request) => eventSocket?.connect(request) ?? Response.json(
417
+ { error: "event_persistence_caller_owned" },
418
+ { status: 409 },
419
+ ),
420
+ },
421
+ turn: {
422
+ ...owned.turn,
423
+ route: (options) => routePrompt(owned, options),
424
+ },
425
+ }));
426
+ const active = {};
427
+ lifecycle.active = active;
428
+ observeAgentRelease(exposed, () => {
429
+ if (lifecycle.active === active) lifecycle.active = undefined;
430
+ });
431
+ commitCloudflareAgentSession(sessionReservation);
432
+ return exposed;
433
+ } catch (error) {
434
+ const cleanupErrors = [];
435
+ try { unwatch?.(); } catch (cleanupError) { cleanupErrors.push(cleanupError); }
436
+ try { watcher?.off(); } catch (cleanupError) { cleanupErrors.push(cleanupError); }
437
+ if (agent) {
438
+ try { await agent.session.shutdown(); } catch (cleanupError) { cleanupErrors.push(cleanupError); }
439
+ }
440
+ releaseAgentSession(sessionReservation);
441
+ if (cleanupErrors.length > 0) {
442
+ const cause = new AggregateError(
443
+ [error, ...cleanupErrors],
444
+ "Cloudflare Agent creation and resource rollback both failed",
445
+ );
446
+ throw Object.assign(
447
+ new Error(
448
+ `Cloudflare Agent creation failed and rollback requires reopen: ${errorMessage(error)}`,
449
+ { cause },
450
+ ),
451
+ { code: "reopen_required" },
452
+ );
453
+ }
454
+ throw error;
455
+ }
456
+ }
457
+
458
+ function lifecycleFor(context) {
459
+ let lifecycle = lifecycles.get(context);
460
+ if (lifecycle === undefined) {
461
+ lifecycle = { active: undefined, creating: false };
462
+ lifecycles.set(context, lifecycle);
463
+ }
464
+ return lifecycle;
465
+ }
466
+
467
+ function errorMessage(error) {
468
+ return error instanceof Error ? error.message : String(error);
469
+ }
470
+
471
+ /** @internal Creates one non-durable Agent in the current Cloudflare isolate. */
472
+ export async function createEphemeral(module, owner, options = {}) {
473
+ const { egress, subject } = resolveOwner(owner);
474
+ const agentOptions = ephemeralApplicationOptions(options);
475
+ const endpoint = cloudflareEgress({
476
+ binding: scopeCloudflareEgress(egress, subject),
477
+ });
478
+ const startup = deferred();
479
+ const transport = Transport.hostManaged({
480
+ ...endpoint,
481
+ websocketPreconnect: true,
482
+ async createWebSocket(url, id, request) {
483
+ try {
484
+ const opened = await endpoint.createWebSocket(url, id, request);
485
+ if (request.authorization === "preconnect") startup.resolve();
486
+ return opened;
487
+ } catch (error) {
488
+ if (request.authorization === "preconnect") startup.reject(error);
489
+ throw error;
490
+ }
491
+ },
492
+ });
493
+
494
+ let agent;
495
+ try {
496
+ agent = await HostAgent.create({
497
+ ...agentOptions,
498
+ module,
499
+ toolMode: "direct",
500
+ transport,
501
+ });
502
+ await withTimeout(
503
+ startup.promise,
504
+ STARTUP_TIMEOUT_MS,
505
+ "Cloudflare ephemeral Agent EGRESS startup validation timed out",
506
+ );
507
+ return agent;
508
+ } catch (error) {
509
+ if (agent) await agent.session.shutdown().catch(() => {});
510
+ throw error;
511
+ }
512
+ }
513
+
514
+ function resolveOwner(owner) {
515
+ const context = resolveContext(owner);
516
+ const egress = owner.env?.NANOCODEX;
517
+ if (!egress || typeof egress.fetch !== "function") {
518
+ throw new TypeError(
519
+ "Cloudflare Agent.create requires the private owner.env.NANOCODEX Service Binding",
520
+ );
521
+ }
522
+ const subject = context.id?.toString?.();
523
+ if (typeof subject !== "string" || !subject) {
524
+ throw new TypeError("Cloudflare Agent.create requires owner.ctx.id");
525
+ }
526
+ return { context, egress, subject };
527
+ }
528
+
529
+ function resolveContext(owner) {
530
+ if (!owner || (typeof owner !== "object" && typeof owner !== "function")) {
531
+ throw new TypeError("Cloudflare Agent.create requires a Durable Object instance");
532
+ }
533
+ const context = owner.ctx;
534
+ if (!context || typeof context !== "object") {
535
+ throw new TypeError("Cloudflare Agent.create requires owner.ctx");
536
+ }
537
+ return context;
538
+ }
539
+
540
+ function applicationOptions(options) {
541
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
542
+ throw new TypeError("Cloudflare Agent.create options must be an object");
543
+ }
544
+ for (const name of Object.keys(options)) {
545
+ if (!APPLICATION_OPTIONS.has(name)) {
546
+ throw new TypeError(
547
+ `Cloudflare Agent.create does not accept ${name}; only durabilityId, eventPersistence, instructions, additionalInstructions, terminalReceiptRetention, and tools are configurable`,
548
+ );
549
+ }
550
+ }
551
+ if (options.eventPersistence !== undefined
552
+ && options.eventPersistence !== "durable"
553
+ && options.eventPersistence !== "caller") {
554
+ throw new TypeError(
555
+ "Cloudflare Agent.create eventPersistence must be durable or caller",
556
+ );
557
+ }
558
+ if (options.terminalReceiptRetention !== undefined
559
+ && (!Number.isSafeInteger(options.terminalReceiptRetention)
560
+ || options.terminalReceiptRetention < 0
561
+ || options.terminalReceiptRetention > 4_096)) {
562
+ throw new TypeError(
563
+ "Cloudflare Agent.create terminalReceiptRetention must be an integer from 0 through 4096",
564
+ );
565
+ }
566
+ return options;
567
+ }
568
+
569
+ function validateInternalConfiguration(configuration) {
570
+ if (configuration === undefined) return;
571
+ if (!configuration || typeof configuration !== "object" || Array.isArray(configuration)
572
+ || Reflect.ownKeys(configuration).some((key) => ![
573
+ "model",
574
+ "thinking",
575
+ "reasoning_mode",
576
+ "fast_mode",
577
+ ].includes(key))
578
+ || !["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-6-astra"]
579
+ .includes(configuration.model)
580
+ || !["none", "low", "medium", "high", "xhigh", "max"].includes(configuration.thinking)
581
+ || !["standard", "pro"].includes(configuration.reasoning_mode)
582
+ || typeof configuration.fast_mode !== "boolean"
583
+ || (configuration.model === "gpt-6-astra" && configuration.thinking === "none")) {
584
+ throw new TypeError("Cloudflare Agent internal configuration is invalid");
585
+ }
586
+ }
587
+
588
+ function ephemeralApplicationOptions(options) {
589
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
590
+ throw new TypeError("Cloudflare Agent.createEphemeral options must be an object");
591
+ }
592
+ for (const name of Object.keys(options)) {
593
+ if (!EPHEMERAL_APPLICATION_OPTIONS.has(name)) {
594
+ throw new TypeError(
595
+ `Cloudflare Agent.createEphemeral does not accept ${name}; transport and runtime policy are owned by the adapter`,
596
+ );
597
+ }
598
+ }
599
+ return options;
600
+ }
601
+
602
+ function durableIdentity(storage, configuredStateId) {
603
+ initializeAgentStorage(storage);
604
+ if (configuredStateId !== undefined
605
+ && (typeof configuredStateId !== "string" || !configuredStateId.trim())) {
606
+ throw new TypeError("Cloudflare Agent durabilityId must be a non-empty string");
607
+ }
608
+ const previousSessionId = storedSessionId(storage);
609
+ const previousStateId = storedStateId(storage);
610
+ if (previousStateId !== undefined
611
+ && configuredStateId !== undefined
612
+ && previousStateId !== configuredStateId) {
613
+ throw new Error("Cloudflare Agent durabilityId does not match the retained state identity");
614
+ }
615
+ const generated = previousSessionId ?? uuidV7();
616
+ const generatedStateId = previousStateId
617
+ ?? configuredStateId
618
+ ?? (previousSessionId === undefined ? generated : `cloudflare:${previousSessionId}`);
619
+ storage.transactionSync(() => {
620
+ storage.sql.exec(
621
+ "INSERT OR IGNORE INTO nanocodex_cloudflare_agent (singleton, session_id) VALUES (1, ?)",
622
+ generated,
623
+ );
624
+ storage.sql.exec(
625
+ "INSERT OR IGNORE INTO nanocodex_cloudflare_durability (singleton, state_id) VALUES (1, ?)",
626
+ generatedStateId,
627
+ );
628
+ });
629
+ const sessionId = storedSessionId(storage);
630
+ const stateId = storedStateId(storage);
631
+ if (typeof sessionId !== "string" || !sessionId) {
632
+ throw new Error("Cloudflare Agent failed to persist its runtime session ID");
633
+ }
634
+ if (typeof stateId !== "string" || !stateId) {
635
+ throw new Error("Cloudflare Agent failed to persist its durability state ID");
636
+ }
637
+ return { sessionId, stateId };
638
+ }
639
+
640
+ function initializeAgentStorage(storage) {
641
+ storage.sql.exec(`
642
+ CREATE TABLE IF NOT EXISTS nanocodex_cloudflare_agent (
643
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
644
+ session_id TEXT NOT NULL UNIQUE
645
+ )
646
+ `);
647
+ storage.sql.exec(`
648
+ CREATE TABLE IF NOT EXISTS nanocodex_cloudflare_durability (
649
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
650
+ state_id TEXT NOT NULL UNIQUE
651
+ )
652
+ `);
653
+ storage.sql.exec(`
654
+ CREATE TABLE IF NOT EXISTS nanocodex_cloudflare_subagents (
655
+ session_id TEXT PRIMARY KEY,
656
+ agent_id TEXT NOT NULL UNIQUE,
657
+ descriptor_json TEXT NOT NULL,
658
+ host_context_ref TEXT
659
+ )
660
+ `);
661
+ const subagentColumns = storage.sql.exec(
662
+ "PRAGMA table_info('nanocodex_cloudflare_subagents')",
663
+ ).toArray();
664
+ if (!subagentColumns.some(({ name }) => name === "host_context_ref")) {
665
+ storage.sql.exec(
666
+ "ALTER TABLE nanocodex_cloudflare_subagents ADD COLUMN host_context_ref TEXT",
667
+ );
668
+ }
669
+ }
670
+
671
+ function cloudflareSubagentSessions(storage, reservation, lifecycle) {
672
+ const restoredHostContextRefs = new Map();
673
+ return Object.freeze({
674
+ restore() {
675
+ const restored = storage.sql.exec(
676
+ "SELECT descriptor_json, host_context_ref FROM nanocodex_cloudflare_subagents",
677
+ ).toArray().map(({ descriptor_json, host_context_ref }) => {
678
+ const descriptor = Object.freeze(JSON.parse(descriptor_json));
679
+ restoredHostContextRefs.set(
680
+ descriptor.sessionId,
681
+ host_context_ref === null ? undefined : host_context_ref,
682
+ );
683
+ return descriptor;
684
+ });
685
+ return Object.freeze(restored);
686
+ },
687
+ hostContextRef(sessionId) {
688
+ return restoredHostContextRefs.get(sessionId);
689
+ },
690
+ bind(sessionId, descriptor, hostContextRef) {
691
+ if (!mayBindCloudflareSubagentSession(reservation)) return;
692
+ if (hostContextRef !== undefined
693
+ && (typeof hostContextRef !== "string" || hostContextRef.length === 0)) {
694
+ throw new TypeError("subagent host context ref must be a non-empty string when supplied");
695
+ }
696
+ const type = restoredHostContextRefs.has(sessionId) ? "reconstruct" : "bind";
697
+ storage.transactionSync(() => {
698
+ storage.sql.exec(
699
+ `INSERT INTO nanocodex_cloudflare_subagents
700
+ (session_id, agent_id, descriptor_json, host_context_ref) VALUES (?, ?, ?, ?)
701
+ ON CONFLICT (session_id) DO UPDATE SET
702
+ agent_id = excluded.agent_id,
703
+ descriptor_json = excluded.descriptor_json,
704
+ host_context_ref = excluded.host_context_ref`,
705
+ sessionId,
706
+ descriptor.agentId,
707
+ JSON.stringify(descriptor),
708
+ hostContextRef ?? null,
709
+ );
710
+ notifySubagentLifecycle(lifecycle, {
711
+ type,
712
+ rootSessionId: reservation.sessionId,
713
+ sessionId,
714
+ descriptor,
715
+ hostContextRef,
716
+ });
717
+ });
718
+ restoredHostContextRefs.delete(sessionId);
719
+ },
720
+ release(sessionId, hostContextRef) {
721
+ if (!mayReleaseCloudflareSubagentSession(reservation)) return;
722
+ storage.transactionSync(() => {
723
+ const retained = storage.sql.exec(
724
+ `SELECT 1 AS retained FROM nanocodex_cloudflare_subagents
725
+ WHERE session_id = ? AND host_context_ref IS ?`,
726
+ sessionId,
727
+ hostContextRef ?? null,
728
+ ).toArray();
729
+ if (retained.length === 0) return;
730
+ notifySubagentLifecycle(lifecycle, {
731
+ type: "release",
732
+ rootSessionId: reservation.sessionId,
733
+ sessionId,
734
+ hostContextRef,
735
+ });
736
+ storage.sql.exec(
737
+ `DELETE FROM nanocodex_cloudflare_subagents
738
+ WHERE session_id = ? AND host_context_ref IS ?`,
739
+ sessionId,
740
+ hostContextRef ?? null,
741
+ );
742
+ });
743
+ },
744
+ });
745
+ }
746
+
747
+ function notifySubagentLifecycle(lifecycle, event) {
748
+ if (lifecycle === undefined) return;
749
+ lifecycle(Object.freeze(event));
750
+ }
751
+
752
+ function storedSessionId(storage) {
753
+ return storage.sql.exec(
754
+ "SELECT session_id FROM nanocodex_cloudflare_agent WHERE singleton = 1",
755
+ ).toArray()[0]?.session_id;
756
+ }
757
+
758
+ function storedStateId(storage) {
759
+ return storage.sql.exec(
760
+ "SELECT state_id FROM nanocodex_cloudflare_durability WHERE singleton = 1",
761
+ ).toArray()[0]?.state_id;
762
+ }
763
+
764
+ function legacyStateId(storage) {
765
+ const sessionId = storedSessionId(storage);
766
+ return sessionId === undefined ? undefined : `cloudflare:${sessionId}`;
767
+ }
768
+
769
+ function uuidV7() {
770
+ if (typeof globalThis.crypto?.getRandomValues !== "function") {
771
+ throw new Error("Cloudflare Agent requires crypto.getRandomValues()");
772
+ }
773
+ const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
774
+ let timestamp = Date.now();
775
+ for (let index = 5; index >= 0; index -= 1) {
776
+ bytes[index] = timestamp % 256;
777
+ timestamp = Math.floor(timestamp / 256);
778
+ }
779
+ bytes[6] = (bytes[6] & 0x0f) | 0x70;
780
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
781
+ const encoded = [...bytes].map((byte) => byte.toString(16).padStart(2, "0"));
782
+ return `${encoded.slice(0, 4).join("")}-${encoded.slice(4, 6).join("")}-${encoded.slice(6, 8).join("")}-${encoded.slice(8, 10).join("")}-${encoded.slice(10).join("")}`;
783
+ }
784
+
785
+ function deferred() {
786
+ let resolve;
787
+ let reject;
788
+ const promise = new Promise((onResolve, onReject) => {
789
+ resolve = onResolve;
790
+ reject = onReject;
791
+ });
792
+ // Preconnect may fail before HostAgent.create returns and installs the
793
+ // startup waiter. Mark the original promise handled without changing what
794
+ // the later await observes.
795
+ void promise.catch(() => {});
796
+ return { promise, resolve, reject };
797
+ }
798
+
799
+ async function withTimeout(promise, timeoutMs, message) {
800
+ let timer;
801
+ try {
802
+ await Promise.race([
803
+ promise,
804
+ new Promise((_, reject) => {
805
+ timer = setTimeout(() => reject(new Error(message)), timeoutMs);
806
+ }),
807
+ ]);
808
+ } finally {
809
+ clearTimeout(timer);
810
+ }
811
+ }