@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,1275 @@
1
+ const agentStates = new WeakMap();
2
+ const turnStates = new WeakMap();
3
+ const resultStates = new WeakMap();
4
+ const resultFinalizer = typeof FinalizationRegistry === "function"
5
+ ? new FinalizationRegistry((raw) => {
6
+ try { raw.free(); } catch (error) { reportError(error); }
7
+ })
8
+ : undefined;
9
+ const hostSessions = new Map();
10
+ const cloudflareHostReservations = new WeakMap();
11
+ const activeAgentSessions = new Map();
12
+ const pendingCloudflareAgentSessions = new Map();
13
+ const cloudflareAgentSessions = new WeakSet();
14
+ const hostConnections = new Map();
15
+ const definitionHosts = new Map();
16
+ const pendingCompactionInstructions = new Set();
17
+ let nextHostConnection = 1;
18
+ let nextDefinitionHost = 1;
19
+ let nextAgentUid = 1;
20
+
21
+ export const CLOUDFLARE_SESSION_RESERVATION = Symbol("nanocodex.cloudflare.sessionReservation");
22
+
23
+ export function defineRuntime(definition) {
24
+ if (!definition || typeof definition.create !== "function") {
25
+ throw new TypeError("a Nanocodex runtime must define create(options)");
26
+ }
27
+ return Object.freeze({
28
+ key: definition.key ?? "custom",
29
+ name: definition.name ?? "Nanocodex Agent",
30
+ type: definition.type ?? "custom",
31
+ create: definition.create,
32
+ dispose: definition.dispose || ((agent) => agent.free()),
33
+ subscribe: definition.subscribe,
34
+ adopt: definition.adopt,
35
+ release: definition.release,
36
+ decorate: definition.decorate,
37
+ reserveSessions: definition.reserveSessions !== false,
38
+ });
39
+ }
40
+
41
+ export async function createAgentClient(runtime, options = {}, requestedReservation) {
42
+ if (!runtime || typeof runtime.create !== "function") {
43
+ throw new TypeError("createAgent requires a Nanocodex runtime");
44
+ }
45
+ const reserveSession = runtime.reserveSessions !== false;
46
+ const reservation = requestedReservation ?? (
47
+ !reserveSession || options.sessionId === undefined
48
+ ? undefined
49
+ : reserveAgentSession(options.sessionId)
50
+ );
51
+ let raw;
52
+ try {
53
+ raw = await runtime.create(options);
54
+ } catch (error) {
55
+ releaseAgentSession(reservation);
56
+ throw error;
57
+ }
58
+ return createAgent(raw, runtime, reservation, reserveSession);
59
+ }
60
+
61
+ /** Internal adapter seam: observes completion of the owned Agent release path. */
62
+ export function observeAgentRelease(agent, listener) {
63
+ if (typeof listener !== "function") throw new TypeError("Agent release observer must be a function");
64
+ const state = knownAgentState(agent);
65
+ if (state.released) {
66
+ listener({ graceful: state.shutdownPromise !== undefined });
67
+ return () => {};
68
+ }
69
+ state.releaseObservers.add(listener);
70
+ return () => state.releaseObservers.delete(listener);
71
+ }
72
+
73
+ /** Creates the stable UUIDv7 identity reserved before a WASM Agent is constructed. */
74
+ export function createSessionId() {
75
+ if (typeof globalThis.crypto?.getRandomValues !== "function") {
76
+ throw new Error("Nanocodex Agent creation requires crypto.getRandomValues()");
77
+ }
78
+ const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
79
+ let timestamp = Date.now();
80
+ for (let index = 5; index >= 0; index -= 1) {
81
+ bytes[index] = timestamp % 256;
82
+ timestamp = Math.floor(timestamp / 256);
83
+ }
84
+ bytes[6] = (bytes[6] & 0x0f) | 0x70;
85
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
86
+ const encoded = [...bytes].map((byte) => byte.toString(16).padStart(2, "0"));
87
+ 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("")}`;
88
+ }
89
+
90
+ export function prompt(agent, options) {
91
+ const state = agentState(agent);
92
+ const input = actionInput(options);
93
+ const operationId = options?.id;
94
+ const cancelOnAdmission = options?.cancelOnAdmission === true;
95
+ const supplementaryContext = options?.supplementaryContext;
96
+ if (supplementaryContext !== undefined && typeof supplementaryContext !== "string") {
97
+ throw new TypeError("supplementaryContext must be a string");
98
+ }
99
+ const raw = typeof input === "string"
100
+ ? state.raw.prompt(input, operationId, cancelOnAdmission, supplementaryContext)
101
+ : state.raw.promptContent(JSON.stringify(input), operationId, cancelOnAdmission, supplementaryContext);
102
+ return createTurn(raw, agent);
103
+ }
104
+
105
+ /** Internal live-input seam: atomically steers the active turn or starts one. */
106
+ export async function routePrompt(agent, options) {
107
+ const state = agentState(agent);
108
+ const input = actionInput(options);
109
+ if (typeof input !== "string") {
110
+ throw new TypeError("live routed input must be text");
111
+ }
112
+ const raw = await state.raw.routePrompt(input);
113
+ return raw === undefined ? undefined : createTurn(raw, agent);
114
+ }
115
+
116
+ export function getTurnResult(turn) {
117
+ const state = turnState(turn);
118
+ if (!state.result) {
119
+ try {
120
+ state.result = Promise.resolve(state.raw.result()).then(createTurnResult);
121
+ } catch (error) {
122
+ state.result = Promise.reject(error);
123
+ }
124
+ }
125
+ return state.result;
126
+ }
127
+
128
+ export function awaitTurnAcceptance(turn) {
129
+ const state = turnState(turn);
130
+ if (!state.acceptance) {
131
+ try {
132
+ state.acceptance = typeof state.raw.accepted === "function"
133
+ ? Promise.resolve(state.raw.accepted())
134
+ : Promise.resolve(undefined);
135
+ } catch (error) {
136
+ state.acceptance = Promise.reject(error);
137
+ }
138
+ }
139
+ return state.acceptance;
140
+ }
141
+
142
+ export function getTurnSnapshot(result) {
143
+ return resultState(result).snapshot();
144
+ }
145
+
146
+ export function getTurnUsage(result) {
147
+ return resultState(result).usage();
148
+ }
149
+
150
+ /** Internal Worker seam: preserves the Rust-owned encoding until it reaches its consumer. */
151
+ export function getEncodedTurnSnapshot(result) {
152
+ return encodedTurnResultValue(resultState(result), "snapshot");
153
+ }
154
+
155
+ /** Internal Worker seam: preserves the Rust-owned encoding until it reaches its consumer. */
156
+ export function getEncodedTurnUsage(result) {
157
+ return encodedTurnResultValue(resultState(result), "usage");
158
+ }
159
+
160
+ export function steer(turn, options) {
161
+ const state = turnState(turn);
162
+ const input = actionInput(options);
163
+ return typeof input === "string"
164
+ ? state.raw.steer(input)
165
+ : state.raw.steerContent(JSON.stringify(input));
166
+ }
167
+
168
+ export function cancel(turn) {
169
+ return turnState(turn).raw.cancel();
170
+ }
171
+
172
+ export async function fork(agent, options) {
173
+ const state = agentState(agent);
174
+ const at = options?.at;
175
+ const raw = at === undefined
176
+ ? await state.raw.fork()
177
+ : await state.raw.forkFrom(resultState(at).raw);
178
+ return createAgent(raw, state.runtime);
179
+ }
180
+
181
+ export async function spawn(agent) {
182
+ const state = agentState(agent);
183
+ return createAgent(await state.raw.spawn(), state.runtime);
184
+ }
185
+
186
+ export async function spawnSubagent(agent, options) {
187
+ return JSON.parse(await agentState(agent).raw.spawnSubagent(JSON.stringify(options)));
188
+ }
189
+
190
+ export async function spawnSubagents(agent, options) {
191
+ return JSON.parse(await agentState(agent).raw.spawnSubagents(JSON.stringify(options)));
192
+ }
193
+
194
+ export async function waitSubagents(agent, options) {
195
+ return JSON.parse(await agentState(agent).raw.waitSubagents(JSON.stringify(options)));
196
+ }
197
+
198
+ export async function listSubagents(agent, options) {
199
+ return JSON.parse(await agentState(agent).raw.listSubagents(JSON.stringify(options ?? {})));
200
+ }
201
+
202
+ export async function sendSubagentMessage(agent, options) {
203
+ return JSON.parse(await agentState(agent).raw.sendSubagentMessage(JSON.stringify(options)));
204
+ }
205
+
206
+ export async function interruptSubagent(agent, agentId) {
207
+ return JSON.parse(await agentState(agent).raw.interruptSubagent(JSON.stringify({ agentId })));
208
+ }
209
+
210
+ export async function closeSubagent(agent, agentId) {
211
+ return JSON.parse(await agentState(agent).raw.closeSubagent(JSON.stringify({ agentId })));
212
+ }
213
+
214
+ export function setThinking(agent, thinking) {
215
+ return agentState(agent).raw.setThinking(thinking);
216
+ }
217
+
218
+ export function setModel(agent, model) {
219
+ return agentState(agent).raw.setModel(model);
220
+ }
221
+
222
+ export function setFastMode(agent, enabled) {
223
+ return agentState(agent).raw.setFastMode(enabled);
224
+ }
225
+
226
+ export function compact(agent) {
227
+ const raw = agentState(agent).raw;
228
+ if (typeof raw.compactOutcome === "function") {
229
+ return raw.compactOutcome().then((encoded) => JSON.parse(encoded));
230
+ }
231
+ return raw.compact();
232
+ }
233
+
234
+ export async function snapshot(agent) {
235
+ const encoded = await agentState(agent).raw.snapshot();
236
+ if (typeof encoded !== "string") {
237
+ throw new TypeError("Nanocodex snapshot must be a JSON string");
238
+ }
239
+ return freezeJson(JSON.parse(encoded));
240
+ }
241
+
242
+ export async function context(agent) {
243
+ return parseSessionContext(await agentState(agent).raw.context());
244
+ }
245
+
246
+ export async function appendDeveloperMessage(agent, text) {
247
+ if (typeof text !== "string" || !text.trim()) {
248
+ throw new TypeError("non-empty string");
249
+ }
250
+ return parseSessionContext(await agentState(agent).raw.appendDeveloperMessage(text));
251
+ }
252
+
253
+ export async function startRealtimeConversation(agent) {
254
+ return parseSessionContext(await agentState(agent).raw.startRealtimeConversation());
255
+ }
256
+
257
+ export async function endRealtimeConversation(agent) {
258
+ return parseSessionContext(await agentState(agent).raw.endRealtimeConversation());
259
+ }
260
+
261
+ export async function realtimeDelegation(agent, input, transcript = []) {
262
+ return agentState(agent).raw.realtimeDelegation(input, JSON.stringify(transcript));
263
+ }
264
+
265
+ export async function realtimeTailDelegation(agent, transcript) {
266
+ return agentState(agent).raw.realtimeTailDelegation(JSON.stringify(transcript));
267
+ }
268
+
269
+ /** Internal browser seam over the Rust-owned voice controller. */
270
+ export function createBrowserVoice(agent, voice) {
271
+ return agentState(agent).raw.browserVoice(voice);
272
+ }
273
+
274
+ export async function shutdown(agent) {
275
+ const state = knownAgentState(agent);
276
+ if (state.shutdownPromise) return state.shutdownPromise;
277
+ if (state.disposed) throw new Error("the Nanocodex agent has been disposed");
278
+ if (typeof state.raw.shutdown !== "function") {
279
+ throw new Error("this Nanocodex runtime does not expose graceful shutdown");
280
+ }
281
+ state.disposed = true;
282
+ state.shutdownPromise = joinAgentShutdown(state);
283
+ return state.shutdownPromise;
284
+ }
285
+
286
+ function parseSessionContext(context) {
287
+ return JSON.parse(context);
288
+ }
289
+
290
+ export function subscribeAgentEvents(agent, listener, options = {}, onRelease) {
291
+ const state = agentState(agent);
292
+ if (typeof state.runtime.subscribe !== "function") {
293
+ throw new Error("this Nanocodex runtime does not expose agent events");
294
+ }
295
+ if (typeof listener !== "function") {
296
+ throw new TypeError("watchAgentEvents requires a listener");
297
+ }
298
+ const unsubscribe = state.runtime.subscribe((event, encodedLength, encodedEvent, agentId) => {
299
+ if (options.includeAllSessions || !event?.request_id || event.request_id === agent.sessionId) {
300
+ listener(event, encodedLength, encodedEvent, agentId);
301
+ }
302
+ });
303
+ let active = true;
304
+ const subscription = {
305
+ close(notify) {
306
+ if (!active) return;
307
+ active = false;
308
+ state.subscriptions.delete(subscription);
309
+ const errors = [];
310
+ runCleanup(errors, () => unsubscribe?.());
311
+ if (notify) runCleanup(errors, () => onRelease?.());
312
+ throwCleanupErrors(errors);
313
+ },
314
+ };
315
+ state.subscriptions.add(subscription);
316
+ return () => subscription.close(false);
317
+ }
318
+
319
+ export function toWasmConfig(options = {}) {
320
+ const apiKey = options.apiKey;
321
+ if (typeof apiKey !== "string" || !apiKey.trim()) {
322
+ throw new TypeError("apiKey must be a non-empty string");
323
+ }
324
+ const config = { api_key: apiKey };
325
+ copy(config, "model", options.model);
326
+ copy(config, "thinking", options.thinking);
327
+ copy(config, "reasoning_mode", options.reasoningMode);
328
+ copy(config, "fast_mode", options.fastMode);
329
+ copy(config, "websocket_warmup", options.websocketWarmup);
330
+ copy(config, "host_http", options.hostHttp);
331
+ copy(config, "websocket_url", options.websocketUrl);
332
+ copy(config, "api_base_url", options.apiBaseUrl);
333
+ copy(config, "instructions", options.instructions);
334
+ copy(config, "additional_instructions", options.additionalInstructions);
335
+ copy(config, "companion_compaction_instruction", options.companionCompactionInstruction);
336
+ if (options.resolveCompactionInstruction !== undefined) {
337
+ config.dynamic_compaction_instruction = true;
338
+ }
339
+ if (options.historySeed !== undefined) {
340
+ const seed = options.historySeed;
341
+ if (!seed || typeof seed !== "object" || Array.isArray(seed)
342
+ || !Array.isArray(seed.history)) {
343
+ throw new TypeError("historySeed must contain a history array");
344
+ }
345
+ config.history_seed = { history: seed.history };
346
+ copy(config.history_seed, "continuity_summary", seed.continuitySummary);
347
+ }
348
+ copy(config, "session_id", options.sessionId);
349
+ copy(config, "workspace", options.workspace);
350
+ if (options.executionEnvironment !== undefined) {
351
+ const environment = options.executionEnvironment;
352
+ if (!environment || typeof environment !== "object" || Array.isArray(environment)) {
353
+ throw new TypeError("executionEnvironment must be an object");
354
+ }
355
+ config.execution_environment = {
356
+ current_date: environment.currentDate,
357
+ timezone: environment.timezone,
358
+ };
359
+ copy(
360
+ config.execution_environment,
361
+ "project_instructions",
362
+ environment.projectInstructions,
363
+ );
364
+ }
365
+ copy(config, "resume", options.resume);
366
+ copy(config, "durability_id", options.durabilityId);
367
+ copy(config, "durability_host_id", options.durabilityHostId);
368
+ copy(config, "terminal_receipt_retention", options.terminalReceiptRetention);
369
+ copy(config, "subagents", options.subagents);
370
+ copy(config, "host_definition_id", options.hostDefinitionId);
371
+ return config;
372
+ }
373
+
374
+ export function createEventChannel() {
375
+ const listeners = new Set();
376
+ const sources = new Set();
377
+ return Object.freeze({
378
+ emit(eventJson, encodedBytes, agentId) {
379
+ if (!listeners.size) return;
380
+ const event = freezeJson(typeof eventJson === "string" ? JSON.parse(eventJson) : eventJson);
381
+ const encodedLength = Number.isSafeInteger(encodedBytes) && encodedBytes >= 0
382
+ ? encodedBytes
383
+ : undefined;
384
+ for (const listener of listeners) listener(event, encodedLength, eventJson, agentId);
385
+ },
386
+ subscribe(listener) {
387
+ const activate = listeners.size === 0;
388
+ listeners.add(listener);
389
+ if (activate) {
390
+ for (const source of sources) source.setEventForwarding?.(true);
391
+ }
392
+ let active = true;
393
+ return () => {
394
+ if (!active) return;
395
+ active = false;
396
+ listeners.delete(listener);
397
+ if (listeners.size === 0) {
398
+ for (const source of sources) source.setEventForwarding?.(false);
399
+ }
400
+ };
401
+ },
402
+ addSource(source) {
403
+ sources.add(source);
404
+ if (listeners.size) source.setEventForwarding?.(true);
405
+ },
406
+ removeSource(source) {
407
+ if (!sources.delete(source)) return;
408
+ source.setEventForwarding?.(false);
409
+ },
410
+ });
411
+ }
412
+
413
+ export function activateHost(host) {
414
+ if (!host || typeof host.connect !== "function") {
415
+ throw new TypeError("a Nanocodex host must define connect()");
416
+ }
417
+ installHostBridge();
418
+ }
419
+
420
+ export function installHostBridge() {
421
+ globalThis.nanocodexHost = hostBridge;
422
+ }
423
+
424
+ export function loadDurabilityRuntime() {
425
+ return import("./runtime/durability.mjs");
426
+ }
427
+
428
+ export function reportError(error) {
429
+ try {
430
+ if (typeof globalThis.reportError === "function") globalThis.reportError(error);
431
+ else globalThis.console?.error?.(error);
432
+ } catch {}
433
+ }
434
+
435
+ export function bindHostSession(host, sessionId, reservation) {
436
+ const existing = hostSessions.get(sessionId);
437
+ const replacementOwner = cloudflareSessionOwner(reservation, sessionId);
438
+ if (existing && existing !== host) {
439
+ if (replacementOwner === undefined
440
+ || cloudflareHostReservations.get(existing)?.ownerId !== replacementOwner) {
441
+ throw new Error(`Nanocodex session ID is already active: ${sessionId}`);
442
+ }
443
+ }
444
+ hostSessions.set(sessionId, host);
445
+ if (replacementOwner !== undefined) {
446
+ reservation.host = host;
447
+ }
448
+ }
449
+
450
+ export function releaseHostSession(host, sessionId) {
451
+ if (hostSessions.get(sessionId) !== host) return;
452
+ hostSessions.delete(sessionId);
453
+ }
454
+
455
+ export function registerDefinitionHost(host, cloudflareReservation) {
456
+ const id = nextDefinitionHost++;
457
+ definitionHosts.set(id, host);
458
+ if (cloudflareReservation !== undefined) {
459
+ if (!cloudflareAgentSessions.has(cloudflareReservation)
460
+ || cloudflareReservation.released) {
461
+ definitionHosts.delete(id);
462
+ throw new Error("Cloudflare Agent session reservation is no longer active");
463
+ }
464
+ cloudflareHostReservations.set(host, cloudflareReservation);
465
+ }
466
+ return id;
467
+ }
468
+
469
+ export function releaseDefinitionHost(id) {
470
+ for (const pending of [...pendingCompactionInstructions]) {
471
+ if (pending.definitionHostId === id) pending.cancel();
472
+ }
473
+ definitionHosts.delete(id);
474
+ }
475
+
476
+ const hostBridge = Object.freeze({
477
+ connect(endpoint, apiKey, accountId, fedramp, sessionId, threadId, turnState) {
478
+ const host = requiredSessionHost(threadId);
479
+ let pending;
480
+ try {
481
+ pending = host.connect(endpoint, apiKey, sessionId, {
482
+ accountId: accountId ?? undefined,
483
+ fedramp,
484
+ threadId,
485
+ turnState: turnState ?? undefined,
486
+ });
487
+ } catch (error) {
488
+ return Promise.reject(JSON.stringify(connectFailure(error)));
489
+ }
490
+ const result = Promise.resolve(pending).then((wire) => {
491
+ let parsed;
492
+ try {
493
+ parsed = JSON.parse(wire);
494
+ } catch (error) {
495
+ throw JSON.stringify(connectFailure(error));
496
+ }
497
+ const handle = nextHostConnection++;
498
+ hostConnections.set(handle, { host, handle: parsed.handle });
499
+ hostSessions.set(threadId, host);
500
+ return JSON.stringify({ ...parsed, handle });
501
+ }, (error) => {
502
+ throw JSON.stringify(connectFailure(error));
503
+ });
504
+ if (typeof pending?.cancel === "function") {
505
+ result.cancel = () => pending.cancel();
506
+ }
507
+ return result;
508
+ },
509
+ async httpOpen(endpoint, apiKey, accountId, fedramp, sessionId, threadId, turnState, body) {
510
+ const host = requiredSessionHost(threadId);
511
+ let result;
512
+ try {
513
+ result = JSON.parse(await host.httpOpen(endpoint, apiKey, sessionId, body, {
514
+ accountId: accountId ?? undefined,
515
+ fedramp,
516
+ threadId,
517
+ turnState: turnState ?? undefined,
518
+ }));
519
+ } catch (error) {
520
+ throw JSON.stringify(connectFailure(error));
521
+ }
522
+ const handle = nextHostConnection++;
523
+ hostConnections.set(handle, { host, handle: result.handle });
524
+ hostSessions.set(threadId, host);
525
+ return JSON.stringify({ ...result, handle });
526
+ },
527
+ httpHeaders(handle) {
528
+ const connection = hostConnections.get(handle);
529
+ if (!connection) {
530
+ return Promise.reject(JSON.stringify({
531
+ kind: "transport",
532
+ detail: "unknown HTTPS handle",
533
+ reconnectable: false,
534
+ }));
535
+ }
536
+ return connection.host.httpHeaders(connection.handle)
537
+ .catch((error) => {
538
+ // Header rejection closes the host-owned handle before Rust can build
539
+ // its HostConnection wrapper; do not retain the outer bridge entry.
540
+ hostConnections.delete(handle);
541
+ throw JSON.stringify(httpFailure(error));
542
+ });
543
+ },
544
+ send(handle, message) {
545
+ const connection = hostConnections.get(handle);
546
+ return connection
547
+ ? connection.host.send(connection.handle, message)
548
+ : Promise.resolve(JSON.stringify({ ok: false, reconnectable: true, error: "unknown WebSocket handle" }));
549
+ },
550
+ next(handle, timeoutMs) {
551
+ const connection = hostConnections.get(handle);
552
+ return connection
553
+ ? connection.host.next(connection.handle, timeoutMs)
554
+ : Promise.resolve(JSON.stringify({ kind: "closed", detail: "for an unknown WebSocket handle" }));
555
+ },
556
+ close(handle) {
557
+ const connection = hostConnections.get(handle);
558
+ if (!connection) return;
559
+ hostConnections.delete(handle);
560
+ connection.host.close(connection.handle);
561
+ },
562
+ sleep(sessionId, milliseconds) {
563
+ const host = requiredSessionHost(sessionId);
564
+ if (typeof host.sleep !== "function") {
565
+ throw new TypeError("the selected Nanocodex host must define sleep(milliseconds)");
566
+ }
567
+ return host.sleep(milliseconds);
568
+ },
569
+ bindSubagentSession(
570
+ hostDefinitionId,
571
+ rootSessionId,
572
+ sessionId,
573
+ contextJson,
574
+ hostContextRef,
575
+ ) {
576
+ let host;
577
+ if (contextJson === undefined) {
578
+ contextJson = sessionId;
579
+ sessionId = rootSessionId;
580
+ rootSessionId = hostDefinitionId;
581
+ host = requiredSessionHost(rootSessionId);
582
+ } else {
583
+ host = requiredDefinitionHost(hostDefinitionId);
584
+ }
585
+ if (!cloudflareHostMayBindSubagent(host)) return;
586
+ const existing = hostSessions.get(sessionId);
587
+ if (existing && existing !== host) {
588
+ const ownerId = cloudflareHostReservations.get(host)?.ownerId;
589
+ if (ownerId === undefined
590
+ || cloudflareHostReservations.get(existing)?.ownerId !== ownerId) {
591
+ throw new Error(`Nanocodex subagent session ID is already active: ${sessionId}`);
592
+ }
593
+ }
594
+ host.bindSubagentSession(sessionId, JSON.parse(contextJson), hostContextRef);
595
+ hostSessions.set(sessionId, host);
596
+ },
597
+ releaseSubagentSession(hostDefinitionId, rootSessionId, sessionId) {
598
+ let host;
599
+ if (sessionId !== undefined) {
600
+ host = definitionHosts.get(hostDefinitionId);
601
+ } else if (rootSessionId !== undefined) {
602
+ sessionId = rootSessionId;
603
+ host = hostSessions.get(hostDefinitionId);
604
+ } else {
605
+ sessionId = hostDefinitionId;
606
+ host = hostSessions.get(sessionId);
607
+ }
608
+ if (!host || hostSessions.get(sessionId) !== host) return;
609
+ host.releaseSession(sessionId);
610
+ if (hostSessions.get(sessionId) === host) hostSessions.delete(sessionId);
611
+ },
612
+ executeCode(source, sessionId, callId, model) {
613
+ return requiredSessionHost(sessionId).executeCode(source, sessionId, callId, model);
614
+ },
615
+ waitCode(input, sessionId, callId) {
616
+ return requiredSessionHost(sessionId).waitCode(input, sessionId, callId);
617
+ },
618
+ nextCodeUpdate(sessionId, callId) {
619
+ return requiredSessionHost(sessionId).nextCodeUpdate(sessionId, callId);
620
+ },
621
+ executeTool(name, input, sessionId, callId, model) {
622
+ return requiredSessionHost(sessionId).executeTool(name, input, sessionId, callId, model);
623
+ },
624
+ beginCodeTurn(sessionId) {
625
+ hostSessions.get(sessionId)?.beginCodeTurn?.(sessionId);
626
+ },
627
+ cancelCodeTurn(sessionId) {
628
+ hostSessions.get(sessionId)?.cancelCodeTurn?.(sessionId);
629
+ },
630
+ cancelCode(sessionId) {
631
+ hostSessions.get(sessionId)?.cancelCode?.(sessionId);
632
+ },
633
+ readWorkspaceFile(path, sessionId) {
634
+ return requiredSessionHost(sessionId).readWorkspaceFile(path);
635
+ },
636
+ async listWorkspace(path, sessionId) {
637
+ return JSON.stringify(await requiredSessionHost(sessionId).listWorkspace(path));
638
+ },
639
+ writeWorkspaceFile(path, contents, sessionId) {
640
+ return requiredSessionHost(sessionId).writeWorkspaceFile(path, contents);
641
+ },
642
+ removeWorkspaceFile(path, sessionId) {
643
+ return requiredSessionHost(sessionId).removeWorkspaceFile(path);
644
+ },
645
+ async subscriptionLoad(subscriptionId) {
646
+ return (await loadSubscriptionRuntime()).load(subscriptionId);
647
+ },
648
+ async subscriptionCompareAndSwap(subscriptionId, expectedRevision, payload) {
649
+ return (await loadSubscriptionRuntime()).compareAndSwap(
650
+ subscriptionId,
651
+ expectedRevision,
652
+ payload,
653
+ );
654
+ },
655
+ async subscriptionRequest(subscriptionId, request) {
656
+ return (await loadSubscriptionRuntime()).request(subscriptionId, request);
657
+ },
658
+ toolMode(definitionHostId, sessionId) {
659
+ return requiredDefinitionHost(definitionHostId).toolMode(sessionId);
660
+ },
661
+ toolDefinitions(definitionHostId, sessionId) {
662
+ // ModelRun builds its stable tool prefix inside the WASM constructor,
663
+ // before the returned session can be adopted. The private definition host
664
+ // keeps that lookup instance-scoped for roots and Rust-spawned children.
665
+ return requiredDefinitionHost(definitionHostId).toolDefinitions(sessionId);
666
+ },
667
+ resolveCompactionInstruction(definitionHostId, contextJson) {
668
+ const host = requiredDefinitionHost(definitionHostId);
669
+ const context = JSON.parse(contextJson);
670
+ const controller = new AbortController();
671
+ const pending = {
672
+ definitionHostId,
673
+ active: true,
674
+ cancel() {
675
+ if (!pending.active) return;
676
+ pending.active = false;
677
+ pendingCompactionInstructions.delete(pending);
678
+ controller.abort(new Error("compaction instruction resolution was cancelled"));
679
+ },
680
+ };
681
+ pendingCompactionInstructions.add(pending);
682
+ let result;
683
+ try {
684
+ if (typeof host.resolveCompactionInstruction !== "function") {
685
+ throw new Error("the Nanocodex host does not provide compaction instruction resolution");
686
+ }
687
+ result = Promise.resolve(host.resolveCompactionInstruction(context, controller.signal))
688
+ .then((instruction) => {
689
+ if (typeof instruction !== "string" || !instruction.trim()) {
690
+ throw new TypeError("compaction instruction resolver must return a non-empty string");
691
+ }
692
+ return instruction;
693
+ })
694
+ .finally(() => {
695
+ pending.active = false;
696
+ pendingCompactionInstructions.delete(pending);
697
+ });
698
+ } catch (error) {
699
+ pending.cancel();
700
+ result = Promise.reject(error);
701
+ }
702
+ result.cancel = pending.cancel;
703
+ // A dropped WASM JsFuture still owns this promise. Keep cancellation
704
+ // rejections observed when the host's resolver is abort-aware.
705
+ result.catch(() => {});
706
+ return result;
707
+ },
708
+ async durabilityAcquire(routeId, stateId, ownerId) {
709
+ return (await loadDurabilityRuntime()).acquire(routeId, stateId, ownerId);
710
+ },
711
+ async durabilityReplace(
712
+ routeId,
713
+ stateId,
714
+ ownerId,
715
+ fence,
716
+ expectedRevision,
717
+ payload,
718
+ ) {
719
+ return (await loadDurabilityRuntime()).replace(
720
+ routeId,
721
+ stateId,
722
+ ownerId,
723
+ fence,
724
+ expectedRevision,
725
+ payload,
726
+ );
727
+ },
728
+ emitEvent(sessionId, eventJson, encodedBytes, encodedAgentId) {
729
+ requiredSessionHost(sessionId).emitEvent(
730
+ eventJson,
731
+ encodedBytes,
732
+ parseSubagentAgentId(encodedAgentId),
733
+ );
734
+ },
735
+ });
736
+
737
+ /** Decodes the string ABI without changing JavaScript's numeric AgentId contract. */
738
+ export function parseSubagentAgentId(encoded) {
739
+ if (encoded === undefined) return undefined;
740
+ if (typeof encoded !== "string" || !/^[1-9][0-9]*$/.test(encoded)) {
741
+ throw new TypeError("subagent agent ID must be a canonical positive decimal string");
742
+ }
743
+ const agentId = Number(encoded);
744
+ if (!Number.isSafeInteger(agentId)) {
745
+ throw new RangeError("subagent agent ID exceeds JavaScript's safe integer range");
746
+ }
747
+ return agentId;
748
+ }
749
+
750
+ export function loadSubscriptionRuntime() {
751
+ return import("./runtime/chatgpt-subscription.mjs");
752
+ }
753
+
754
+ function createAgent(
755
+ raw,
756
+ runtime,
757
+ requestedReservation,
758
+ reserveSession = runtime.reserveSessions !== false,
759
+ ) {
760
+ let reservation = requestedReservation;
761
+ if (!raw || typeof raw.prompt !== "function") {
762
+ releaseAgentSession(reservation);
763
+ throw new TypeError("the runtime returned an invalid Nanocodex agent handle");
764
+ }
765
+ try {
766
+ if (reserveSession) {
767
+ reservation ??= reserveAgentSession(raw.sessionId);
768
+ adoptAgentSession(reservation, raw.sessionId);
769
+ }
770
+ } catch (error) {
771
+ const errors = [error];
772
+ runCleanup(errors, () => runtime.dispose(raw));
773
+ runCleanup(errors, () => releaseAgentSession(reservation));
774
+ throwCleanupErrors(errors);
775
+ }
776
+ const state = {
777
+ raw,
778
+ runtime,
779
+ reservation,
780
+ releaseObservers: new Set(),
781
+ disposed: false,
782
+ released: false,
783
+ shutdownPromise: undefined,
784
+ subscriptions: new Set(),
785
+ agentId: typeof raw.agentId === "string" ? raw.agentId : raw.sessionId,
786
+ sessionId: raw.sessionId,
787
+ uid: `agent-${nextAgentUid++}`,
788
+ };
789
+ try {
790
+ runtime.adopt?.(raw);
791
+ } catch (error) {
792
+ const errors = [error];
793
+ runCleanup(errors, () => runtime.dispose(raw));
794
+ runCleanup(errors, () => releaseAgentSession(reservation));
795
+ throwCleanupErrors(errors);
796
+ }
797
+ const agent = agentView(state, {});
798
+ try {
799
+ return runtime.decorate ? runtime.decorate(agent, raw) : agent;
800
+ } catch (error) {
801
+ const errors = [error];
802
+ runCleanup(errors, () => releaseAgentState(state));
803
+ throwCleanupErrors(errors);
804
+ }
805
+ }
806
+
807
+ function agentView(state, extensions) {
808
+ let agent;
809
+ let reservedKeys;
810
+ const base = {
811
+ uid: state.uid,
812
+ key: state.runtime.key,
813
+ name: state.runtime.name,
814
+ type: state.runtime.type,
815
+ get agentId() { return state.agentId; },
816
+ get sessionId() { return state.sessionId; },
817
+ extend(fn) {
818
+ if (typeof fn !== "function") throw new TypeError("agent.extend requires a decorator function");
819
+ const value = fn(agent);
820
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
821
+ throw new TypeError("an agent decorator must return an object");
822
+ }
823
+ const extension = { ...value };
824
+ for (const key of reservedKeys) delete extension[key];
825
+ return agentView(state, deepMerge(extensions, extension));
826
+ },
827
+ dispose() {
828
+ if (state.shutdownPromise) return;
829
+ releaseAgentState(state);
830
+ },
831
+ };
832
+ reservedKeys = Object.keys(base);
833
+ agent = Object.assign(base, extensions);
834
+ agentStates.set(agent, state);
835
+ return agent;
836
+ }
837
+
838
+ function requiredSessionHost(sessionId) {
839
+ const host = hostSessions.get(sessionId);
840
+ if (!host || !cloudflareHostMayBindSubagent(host)) {
841
+ throw new Error(`no Nanocodex host is active for session: ${sessionId}`);
842
+ }
843
+ return host;
844
+ }
845
+
846
+ function requiredDefinitionHost(id) {
847
+ const host = definitionHosts.get(id);
848
+ if (!host) throw new Error(`no Nanocodex definition host is active: ${id}`);
849
+ return host;
850
+ }
851
+
852
+ function releaseAgentState(state) {
853
+ if (state.released) return;
854
+ state.disposed = true;
855
+ state.released = true;
856
+ const errors = [];
857
+ for (const subscription of [...state.subscriptions]) {
858
+ runCleanup(errors, () => subscription.close(true));
859
+ }
860
+ runCleanup(errors, () => state.runtime.release?.(state.raw));
861
+ runCleanup(errors, () => state.runtime.dispose(state.raw));
862
+ runCleanup(errors, () => releaseAgentSession(state.reservation));
863
+ for (const observer of [...state.releaseObservers]) {
864
+ runCleanup(errors, () => observer({ graceful: state.shutdownPromise !== undefined }));
865
+ }
866
+ state.releaseObservers.clear();
867
+ throwCleanupErrors(errors);
868
+ }
869
+
870
+ /** Internal adapter seam: reserves a stable identity before starting its runtime. */
871
+ export function reserveAgentSession(sessionId) {
872
+ if (typeof sessionId !== "string" || !sessionId) {
873
+ throw new TypeError("sessionId must be a non-empty string");
874
+ }
875
+ if (activeAgentSessions.has(sessionId) || pendingCloudflareAgentSessions.has(sessionId)) {
876
+ throw new Error(`Nanocodex session ID is already active: ${sessionId}`);
877
+ }
878
+ const reservation = { sessionId, adopted: false, released: false };
879
+ activeAgentSessions.set(sessionId, reservation);
880
+ return reservation;
881
+ }
882
+
883
+ /** Internal Cloudflare seam: prepares, but does not activate, a reconstructed DO owner. */
884
+ export function prepareCloudflareAgentSession(sessionId, ownerId) {
885
+ if (typeof sessionId !== "string" || !sessionId) {
886
+ throw new TypeError("sessionId must be a non-empty string");
887
+ }
888
+ if (typeof ownerId !== "string" || !ownerId) {
889
+ throw new TypeError("Cloudflare Durable Object owner ID must be a non-empty string");
890
+ }
891
+ const existing = activeAgentSessions.get(sessionId);
892
+ if (pendingCloudflareAgentSessions.has(sessionId)
893
+ || (existing !== undefined
894
+ && (!cloudflareAgentSessions.has(existing)
895
+ || existing.ownerId !== ownerId
896
+ || !existing.committed))) {
897
+ throw new Error(`Nanocodex session ID is already active: ${sessionId}`);
898
+ }
899
+ const reservation = {
900
+ sessionId,
901
+ ownerId,
902
+ adopted: false,
903
+ committed: false,
904
+ predecessor: undefined,
905
+ predecessorHost: undefined,
906
+ host: undefined,
907
+ released: false,
908
+ };
909
+ cloudflareAgentSessions.add(reservation);
910
+ pendingCloudflareAgentSessions.set(sessionId, reservation);
911
+ return reservation;
912
+ }
913
+
914
+ /** @internal Whether this exact Cloudflare generation may publish child descriptors. */
915
+ export function mayBindCloudflareSubagentSession(reservation) {
916
+ return cloudflareAgentSessions.has(reservation)
917
+ && !reservation.released
918
+ && (pendingCloudflareAgentSessions.get(reservation.sessionId) === reservation
919
+ || activeAgentSessions.get(reservation.sessionId) === reservation);
920
+ }
921
+
922
+ /** @internal Whether this committed current generation may delete child descriptors. */
923
+ export function mayReleaseCloudflareSubagentSession(reservation) {
924
+ return cloudflareAgentSessions.has(reservation)
925
+ && !reservation.released
926
+ && reservation.committed
927
+ && activeAgentSessions.get(reservation.sessionId) === reservation;
928
+ }
929
+
930
+ function cloudflareHostMayBindSubagent(host) {
931
+ const reservation = cloudflareHostReservations.get(host);
932
+ return reservation === undefined || mayBindCloudflareSubagentSession(reservation);
933
+ }
934
+
935
+ /** Internal Cloudflare seam: activates a prepared owner after raw construction acquires its durable fence. */
936
+ export function activateCloudflareAgentSession(reservation) {
937
+ if (!cloudflareAgentSessions.has(reservation) || reservation.released) {
938
+ throw new Error("Cloudflare Agent session reservation is no longer active");
939
+ }
940
+ if (activeAgentSessions.get(reservation.sessionId) === reservation) return;
941
+ if (pendingCloudflareAgentSessions.get(reservation.sessionId) !== reservation) {
942
+ throw new Error("Cloudflare Agent session reservation is no longer pending");
943
+ }
944
+ const existing = activeAgentSessions.get(reservation.sessionId);
945
+ if (existing !== undefined
946
+ && (!cloudflareAgentSessions.has(existing)
947
+ || existing.ownerId !== reservation.ownerId
948
+ || !existing.committed)) {
949
+ throw new Error(`Nanocodex session ID is already active: ${reservation.sessionId}`);
950
+ }
951
+ reservation.predecessor = existing;
952
+ reservation.predecessorHost = hostSessions.get(reservation.sessionId);
953
+ activeAgentSessions.set(reservation.sessionId, reservation);
954
+ pendingCloudflareAgentSessions.delete(reservation.sessionId);
955
+ }
956
+
957
+ /** Internal Cloudflare seam: publishes a reconstructed owner after adapter setup succeeds. */
958
+ export function commitCloudflareAgentSession(reservation) {
959
+ if (!cloudflareAgentSessions.has(reservation)
960
+ || reservation.released
961
+ || !reservation.adopted
962
+ || activeAgentSessions.get(reservation.sessionId) !== reservation) {
963
+ throw new Error("Cloudflare Agent session reservation is not ready to commit");
964
+ }
965
+ reservation.committed = true;
966
+ reservation.predecessor = undefined;
967
+ reservation.predecessorHost = undefined;
968
+ }
969
+
970
+ function adoptAgentSession(reservation, sessionId) {
971
+ if (reservation.released || activeAgentSessions.get(reservation.sessionId) !== reservation) {
972
+ throw new Error(`Nanocodex session reservation is no longer active: ${sessionId}`);
973
+ }
974
+ if (reservation.sessionId !== sessionId) {
975
+ throw new Error(
976
+ `Nanocodex runtime changed reserved session ID ${reservation.sessionId} to ${sessionId}`,
977
+ );
978
+ }
979
+ if (reservation.adopted) {
980
+ throw new Error(`Nanocodex session reservation was already adopted: ${sessionId}`);
981
+ }
982
+ reservation.adopted = true;
983
+ }
984
+
985
+ /** Internal adapter seam: rolls back a runtime reservation that was not adopted. */
986
+ export function releaseAgentSession(reservation) {
987
+ if (!reservation || reservation.released) return;
988
+ reservation.released = true;
989
+ if (pendingCloudflareAgentSessions.get(reservation.sessionId) === reservation) {
990
+ pendingCloudflareAgentSessions.delete(reservation.sessionId);
991
+ }
992
+ if (activeAgentSessions.get(reservation.sessionId) === reservation) {
993
+ if (cloudflareAgentSessions.has(reservation)
994
+ && !reservation.committed
995
+ && reservation.predecessor !== undefined
996
+ && !reservation.predecessor.released) {
997
+ activeAgentSessions.set(reservation.sessionId, reservation.predecessor);
998
+ if (reservation.predecessorHost !== undefined) {
999
+ hostSessions.set(reservation.sessionId, reservation.predecessorHost);
1000
+ }
1001
+ } else {
1002
+ activeAgentSessions.delete(reservation.sessionId);
1003
+ if (hostSessions.get(reservation.sessionId) === reservation.host) {
1004
+ hostSessions.delete(reservation.sessionId);
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ function cloudflareSessionOwner(reservation, sessionId) {
1011
+ if (!cloudflareAgentSessions.has(reservation)
1012
+ || reservation.released
1013
+ || reservation.sessionId !== sessionId
1014
+ || activeAgentSessions.get(sessionId) !== reservation) {
1015
+ return undefined;
1016
+ }
1017
+ return reservation.ownerId;
1018
+ }
1019
+
1020
+ async function joinAgentShutdown(state) {
1021
+ await Promise.resolve();
1022
+ let shutdownFailed = false;
1023
+ let shutdownError;
1024
+ try {
1025
+ await state.raw.shutdown();
1026
+ } catch (error) {
1027
+ shutdownFailed = true;
1028
+ shutdownError = error;
1029
+ }
1030
+
1031
+ let cleanupFailed = false;
1032
+ let cleanupError;
1033
+ try {
1034
+ releaseAgentState(state);
1035
+ } catch (error) {
1036
+ cleanupFailed = true;
1037
+ cleanupError = error;
1038
+ }
1039
+
1040
+ if (shutdownFailed && cleanupFailed) {
1041
+ const cleanupErrors = cleanupError instanceof AggregateError
1042
+ ? cleanupError.errors
1043
+ : [cleanupError];
1044
+ throw new AggregateError(
1045
+ [shutdownError, ...cleanupErrors],
1046
+ "Nanocodex driver shutdown and resource release both failed",
1047
+ );
1048
+ }
1049
+ if (shutdownFailed) throw shutdownError;
1050
+ if (cleanupFailed) throw cleanupError;
1051
+ }
1052
+
1053
+ function connectFailure(error) {
1054
+ if (typeof error === "string") {
1055
+ try {
1056
+ const encoded = JSON.parse(error);
1057
+ if (encoded?.kind === "handshake_rejected" || encoded?.kind === "transport") {
1058
+ return encoded;
1059
+ }
1060
+ } catch {}
1061
+ }
1062
+ const status = Number(error?.status);
1063
+ if (Number.isInteger(status) && status >= 100 && status <= 599) {
1064
+ const retryAfter = Number(error?.retryAfter);
1065
+ return {
1066
+ kind: "handshake_rejected",
1067
+ status,
1068
+ body: typeof error?.body === "string" ? error.body : errorDetail(error),
1069
+ ...(Number.isFinite(retryAfter) && retryAfter >= 0 ? { retry_after: retryAfter } : {}),
1070
+ };
1071
+ }
1072
+ return {
1073
+ kind: "transport",
1074
+ detail: errorDetail(error),
1075
+ reconnectable: true,
1076
+ };
1077
+ }
1078
+
1079
+ function httpFailure(error) {
1080
+ if (typeof error === "string") {
1081
+ try {
1082
+ const encoded = JSON.parse(error);
1083
+ if (encoded?.kind === "http_rejected" || encoded?.kind === "transport") {
1084
+ return encoded;
1085
+ }
1086
+ } catch {}
1087
+ }
1088
+ const status = Number(error?.status);
1089
+ if (Number.isInteger(status) && status >= 100 && status <= 599) {
1090
+ const retryAfter = Number(error?.retryAfter);
1091
+ return {
1092
+ kind: "http_rejected",
1093
+ status,
1094
+ body: typeof error?.body === "string" ? error.body : errorDetail(error),
1095
+ ...(Number.isFinite(retryAfter) && retryAfter >= 0 ? { retry_after: retryAfter } : {}),
1096
+ };
1097
+ }
1098
+ return {
1099
+ kind: "transport",
1100
+ detail: errorDetail(error),
1101
+ reconnectable: error?.reconnectable === true,
1102
+ };
1103
+ }
1104
+
1105
+ function errorDetail(error) {
1106
+ return error && (error.stack || error.message) || String(error);
1107
+ }
1108
+
1109
+ function createTurn(raw, agent) {
1110
+ if (!raw || typeof raw.result !== "function") {
1111
+ throw new TypeError("the runtime returned an invalid Nanocodex turn handle");
1112
+ }
1113
+ const state = { raw, agent, acceptance: undefined, result: undefined, disposed: false };
1114
+ const turn = {
1115
+ get agent() { return state.agent; },
1116
+ accepted: () => awaitTurnAcceptance(turn),
1117
+ result: () => getTurnResult(turn),
1118
+ steer: (input) => steer(turn, input),
1119
+ cancel: () => cancel(turn),
1120
+ dispose() {
1121
+ if (state.disposed) return;
1122
+ state.disposed = true;
1123
+ state.raw.free();
1124
+ },
1125
+ };
1126
+ turnStates.set(turn, state);
1127
+ return Object.freeze(turn);
1128
+ }
1129
+
1130
+ function createTurnResult(raw) {
1131
+ if (
1132
+ !raw
1133
+ || typeof raw.finalMessage !== "string"
1134
+ || typeof raw.snapshot !== "function"
1135
+ || typeof raw.usage !== "function"
1136
+ || typeof raw.free !== "function"
1137
+ ) {
1138
+ raw?.free?.();
1139
+ throw new TypeError("the runtime returned an invalid Nanocodex turn result");
1140
+ }
1141
+ const state = {
1142
+ disposed: false,
1143
+ raw,
1144
+ snapshotPromise: undefined,
1145
+ usagePromise: undefined,
1146
+ snapshot() {
1147
+ if (state.disposed) return Promise.reject(new Error("the Nanocodex turn result has been disposed"));
1148
+ state.snapshotPromise ||= materializeTurnResultValue(state, "snapshot");
1149
+ return state.snapshotPromise;
1150
+ },
1151
+ usage() {
1152
+ if (state.disposed) return Promise.reject(new Error("the Nanocodex turn result has been disposed"));
1153
+ state.usagePromise ||= materializeTurnResultValue(state, "usage");
1154
+ return state.usagePromise;
1155
+ },
1156
+ };
1157
+ const result = {
1158
+ finalMessage: raw.finalMessage,
1159
+ snapshot: () => state.snapshot(),
1160
+ usage: () => state.usage(),
1161
+ dispose() {
1162
+ if (state.disposed) return;
1163
+ state.disposed = true;
1164
+ resultFinalizer?.unregister(result);
1165
+ state.raw.free();
1166
+ },
1167
+ };
1168
+ resultStates.set(result, state);
1169
+ resultFinalizer?.register(result, raw, result);
1170
+ return Object.freeze(result);
1171
+ }
1172
+
1173
+ function materializeTurnResultValue(state, method) {
1174
+ let encoded;
1175
+ try {
1176
+ encoded = state.raw[method]();
1177
+ } catch (error) {
1178
+ return Promise.reject(error);
1179
+ }
1180
+ return Promise.resolve(encoded).then((value) => {
1181
+ if (typeof value !== "string") {
1182
+ throw new TypeError(`the runtime returned an invalid encoded turn ${method}`);
1183
+ }
1184
+ return freezeJson(JSON.parse(value));
1185
+ });
1186
+ }
1187
+
1188
+ async function encodedTurnResultValue(state, method) {
1189
+ const encoded = await state.raw[method]();
1190
+ if (typeof encoded !== "string") {
1191
+ throw new TypeError(`the runtime returned an invalid encoded turn ${method}`);
1192
+ }
1193
+ return encoded;
1194
+ }
1195
+
1196
+ function agentState(agent) {
1197
+ const state = knownAgentState(agent);
1198
+ if (state.disposed) throw new Error("the Nanocodex agent has been disposed");
1199
+ return state;
1200
+ }
1201
+
1202
+ function knownAgentState(agent) {
1203
+ const state = agentStates.get(agent);
1204
+ if (!state) throw new TypeError("expected a Nanocodex agent");
1205
+ return state;
1206
+ }
1207
+
1208
+ function turnState(turn) {
1209
+ const state = turnStates.get(turn);
1210
+ if (!state) throw new TypeError("expected a Nanocodex turn");
1211
+ if (state.disposed) throw new Error("the Nanocodex turn has been disposed");
1212
+ return state;
1213
+ }
1214
+
1215
+ function resultState(result) {
1216
+ const state = resultStates.get(result);
1217
+ if (!state) throw new TypeError("expected a completed Nanocodex turn result");
1218
+ if (state.disposed) throw new Error("the Nanocodex turn result has been disposed");
1219
+ return state;
1220
+ }
1221
+
1222
+ function actionInput(options) {
1223
+ const input = options?.input;
1224
+ if (typeof input !== "string" && !Array.isArray(input)) {
1225
+ throw new TypeError("turn input must be a string or ordered content array");
1226
+ }
1227
+ return input;
1228
+ }
1229
+
1230
+ function deepMerge(left, right) {
1231
+ const merged = { ...left };
1232
+ for (const [key, value] of Object.entries(right)) {
1233
+ merged[key] = isObject(merged[key]) && isObject(value)
1234
+ ? deepMerge(merged[key], value)
1235
+ : value;
1236
+ }
1237
+ return merged;
1238
+ }
1239
+
1240
+ function isObject(value) {
1241
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1242
+ }
1243
+
1244
+ function copy(target, key, value) {
1245
+ if (value !== undefined) target[key] = value;
1246
+ }
1247
+
1248
+ function runCleanup(errors, cleanup) {
1249
+ try {
1250
+ cleanup();
1251
+ } catch (error) {
1252
+ errors.push(error);
1253
+ }
1254
+ }
1255
+
1256
+ function throwCleanupErrors(errors) {
1257
+ if (errors.length === 1) throw errors[0];
1258
+ if (errors.length > 1) {
1259
+ throw new AggregateError(errors, "multiple Nanocodex resources failed to release");
1260
+ }
1261
+ }
1262
+
1263
+ export function freezeJson(value) {
1264
+ if (!value || typeof value !== "object") return value;
1265
+ const pending = [value];
1266
+ while (pending.length) {
1267
+ const current = pending.pop();
1268
+ if (Object.isFrozen(current)) continue;
1269
+ for (const child of Object.values(current)) {
1270
+ if (child && typeof child === "object" && !Object.isFrozen(child)) pending.push(child);
1271
+ }
1272
+ Object.freeze(current);
1273
+ }
1274
+ return value;
1275
+ }