@tangle-network/agent-runtime 0.105.0 → 0.106.1

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 (218) hide show
  1. package/README.md +2 -2
  2. package/dist/activation-CRjVfOiy.js +203 -0
  3. package/dist/activation-CRjVfOiy.js.map +1 -0
  4. package/dist/activation-DyWB0K6E.d.ts +98 -0
  5. package/dist/agent.d.ts +216 -234
  6. package/dist/agent.js +615 -547
  7. package/dist/agent.js.map +1 -1
  8. package/dist/analyst-loop-DGdtVENg.js +517 -0
  9. package/dist/analyst-loop-DGdtVENg.js.map +1 -0
  10. package/dist/analyst-loop.d.ts +10 -43
  11. package/dist/analyst-loop.js +2 -11
  12. package/dist/backends-CiOCyRHb.js +743 -0
  13. package/dist/backends-CiOCyRHb.js.map +1 -0
  14. package/dist/candidate-execution/index.d.ts +4 -192
  15. package/dist/candidate-execution/index.js +5 -66
  16. package/dist/candidate-execution-DqMbv1rU.js +488 -0
  17. package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
  18. package/dist/coder-yhVWbdWc.js +40 -0
  19. package/dist/coder-yhVWbdWc.js.map +1 -0
  20. package/dist/conversation-BpLQZGPH.js +1265 -0
  21. package/dist/conversation-BpLQZGPH.js.map +1 -0
  22. package/dist/conversation.d.ts +2 -804
  23. package/dist/conversation.js +2 -55
  24. package/dist/environment-provider-CfLUmKmf.js +1168 -0
  25. package/dist/environment-provider-CfLUmKmf.js.map +1 -0
  26. package/dist/environment-provider-IUGU3epE.d.ts +964 -0
  27. package/dist/environment-provider.d.ts +2 -78
  28. package/dist/environment-provider.js +2 -18
  29. package/dist/errors-DEAvWQPy.js +111 -0
  30. package/dist/errors-DEAvWQPy.js.map +1 -0
  31. package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
  32. package/dist/improvement-cycle-C095kS_g.js +2624 -0
  33. package/dist/improvement-cycle-C095kS_g.js.map +1 -0
  34. package/dist/index-BGdxAwfO.d.ts +838 -0
  35. package/dist/index-C-FYUuFG.d.ts +193 -0
  36. package/dist/index-CbNM40xG.d.ts +140 -0
  37. package/dist/index-DruSKs3Z.d.ts +7224 -0
  38. package/dist/index-Efjb3nrQ.d.ts +671 -0
  39. package/dist/index.d.ts +14 -1058
  40. package/dist/index.js +2106 -2082
  41. package/dist/index.js.map +1 -1
  42. package/dist/intelligence.d.ts +768 -889
  43. package/dist/intelligence.js +1466 -1367
  44. package/dist/intelligence.js.map +1 -1
  45. package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
  46. package/dist/kb-gate-DpaSwXVx.js +80 -0
  47. package/dist/kb-gate-DpaSwXVx.js.map +1 -0
  48. package/dist/knowledge-Ku-mPP4f.js +433 -0
  49. package/dist/knowledge-Ku-mPP4f.js.map +1 -0
  50. package/dist/knowledge.d.ts +2 -150
  51. package/dist/knowledge.js +2 -40
  52. package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
  53. package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
  54. package/dist/loop-runner-bin-CRagyuNb.js +268 -0
  55. package/dist/loop-runner-bin-CRagyuNb.js.map +1 -0
  56. package/dist/loop-runner-bin.d.ts +2 -15
  57. package/dist/loop-runner-bin.js +2 -24
  58. package/dist/loops.d.ts +5 -4164
  59. package/dist/loops.js +8 -419
  60. package/dist/mcp/bin.d.ts +1 -1
  61. package/dist/mcp/bin.js +116 -146
  62. package/dist/mcp/bin.js.map +1 -1
  63. package/dist/mcp/index.d.ts +295 -436
  64. package/dist/mcp/index.js +1242 -1177
  65. package/dist/mcp/index.js.map +1 -1
  66. package/dist/mcp/memory-bin.d.ts +1 -1
  67. package/dist/mcp/memory-bin.js +37 -16
  68. package/dist/mcp/memory-bin.js.map +1 -1
  69. package/dist/memory-server-DL6cE2Ag.js +234 -0
  70. package/dist/memory-server-DL6cE2Ag.js.map +1 -0
  71. package/dist/model-resolution-Btd9iIKV.js +98 -0
  72. package/dist/model-resolution-Btd9iIKV.js.map +1 -0
  73. package/dist/openai-tools-B68JaOCx.d.ts +24 -0
  74. package/dist/openai-tools-CKLy1C7M.js +44 -0
  75. package/dist/openai-tools-CKLy1C7M.js.map +1 -0
  76. package/dist/otel-export-D34IQW1C.js +843 -0
  77. package/dist/otel-export-D34IQW1C.js.map +1 -0
  78. package/dist/platform.d.ts +188 -185
  79. package/dist/platform.js +185 -218
  80. package/dist/platform.js.map +1 -1
  81. package/dist/prepare-B53sPV7M.js +4292 -0
  82. package/dist/prepare-B53sPV7M.js.map +1 -0
  83. package/dist/primeintellect/index.d.ts +149 -145
  84. package/dist/primeintellect/index.js +626 -1003
  85. package/dist/primeintellect/index.js.map +1 -1
  86. package/dist/profiles.d.ts +296 -490
  87. package/dist/profiles.js +722 -749
  88. package/dist/profiles.js.map +1 -1
  89. package/dist/protected-model-port-BLPH5VVv.js +722 -0
  90. package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
  91. package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
  92. package/dist/protected-redaction--F3v1oo8.js +200 -0
  93. package/dist/protected-redaction--F3v1oo8.js.map +1 -0
  94. package/dist/redact-D-u-rrcn.js +82 -0
  95. package/dist/redact-D-u-rrcn.js.map +1 -0
  96. package/dist/redact-kbIOjfjM.d.ts +452 -0
  97. package/dist/researcher-CoVqNhfI.js +433 -0
  98. package/dist/researcher-CoVqNhfI.js.map +1 -0
  99. package/dist/runtime-5zM5XxLr.js +5408 -0
  100. package/dist/runtime-5zM5XxLr.js.map +1 -0
  101. package/dist/sandbox-events-DeI5xX8P.js +316 -0
  102. package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
  103. package/dist/spawn-journal-CwPvKUTa.js +456 -0
  104. package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
  105. package/dist/structural-rollout-IXUEplky.js +1445 -0
  106. package/dist/structural-rollout-IXUEplky.js.map +1 -0
  107. package/dist/substrate-B0TYNrXn.js +27 -0
  108. package/dist/substrate-B0TYNrXn.js.map +1 -0
  109. package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
  110. package/dist/supervise-BiRutHS9.js +7321 -0
  111. package/dist/supervise-BiRutHS9.js.map +1 -0
  112. package/dist/supervisor-DTKhF-RV.js +3826 -0
  113. package/dist/supervisor-DTKhF-RV.js.map +1 -0
  114. package/dist/testing.d.ts +4 -3
  115. package/dist/testing.js +2478 -2637
  116. package/dist/testing.js.map +1 -1
  117. package/dist/tool-server-RcWgLIsL.js +141 -0
  118. package/dist/tool-server-RcWgLIsL.js.map +1 -0
  119. package/dist/trace-propagation-CJJC7SVB.js +57 -0
  120. package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
  121. package/dist/types-BaIpb0XT.d.ts +492 -0
  122. package/dist/types-BevOjfTY.d.ts +765 -0
  123. package/dist/types-C9j4qg6l.d.ts +500 -0
  124. package/dist/types-Cja5OTGh.d.ts +190 -0
  125. package/dist/util-MVgdwuIS.js +145 -0
  126. package/dist/util-MVgdwuIS.js.map +1 -0
  127. package/dist/workspace-archive-BosQiotA.js +575 -0
  128. package/dist/workspace-archive-BosQiotA.js.map +1 -0
  129. package/package.json +44 -56
  130. package/skills/build-with-agent-runtime/SKILL.md +1 -0
  131. package/dist/activation-Cm-9MMX1.d.ts +0 -69
  132. package/dist/analyst-loop.js.map +0 -1
  133. package/dist/backends-BO4Jqoe2.d.ts +0 -134
  134. package/dist/candidate-execution/index.js.map +0 -1
  135. package/dist/chunk-2KGAN2HM.js +0 -1256
  136. package/dist/chunk-2KGAN2HM.js.map +0 -1
  137. package/dist/chunk-2VZYRB55.js +0 -834
  138. package/dist/chunk-2VZYRB55.js.map +0 -1
  139. package/dist/chunk-3MDZX7YU.js +0 -125
  140. package/dist/chunk-3MDZX7YU.js.map +0 -1
  141. package/dist/chunk-5IBQAPVB.js +0 -29
  142. package/dist/chunk-5IBQAPVB.js.map +0 -1
  143. package/dist/chunk-5QOB7H74.js +0 -387
  144. package/dist/chunk-5QOB7H74.js.map +0 -1
  145. package/dist/chunk-C5RTIBNZ.js +0 -48
  146. package/dist/chunk-C5RTIBNZ.js.map +0 -1
  147. package/dist/chunk-CTRA64LY.js +0 -680
  148. package/dist/chunk-CTRA64LY.js.map +0 -1
  149. package/dist/chunk-DPEUKJRO.js +0 -27
  150. package/dist/chunk-DPEUKJRO.js.map +0 -1
  151. package/dist/chunk-FD2MBMOH.js +0 -494
  152. package/dist/chunk-FD2MBMOH.js.map +0 -1
  153. package/dist/chunk-H5QPIZNX.js +0 -907
  154. package/dist/chunk-H5QPIZNX.js.map +0 -1
  155. package/dist/chunk-HLKC4UYB.js +0 -3514
  156. package/dist/chunk-HLKC4UYB.js.map +0 -1
  157. package/dist/chunk-HNP72PNU.js +0 -192
  158. package/dist/chunk-HNP72PNU.js.map +0 -1
  159. package/dist/chunk-ISPWRSEC.js +0 -408
  160. package/dist/chunk-ISPWRSEC.js.map +0 -1
  161. package/dist/chunk-KRBFHMV6.js +0 -1228
  162. package/dist/chunk-KRBFHMV6.js.map +0 -1
  163. package/dist/chunk-M22PL4GH.js +0 -171
  164. package/dist/chunk-M22PL4GH.js.map +0 -1
  165. package/dist/chunk-NURIQBJQ.js +0 -72
  166. package/dist/chunk-NURIQBJQ.js.map +0 -1
  167. package/dist/chunk-OPVWXJ2H.js +0 -75
  168. package/dist/chunk-OPVWXJ2H.js.map +0 -1
  169. package/dist/chunk-PZZKQVQV.js +0 -52
  170. package/dist/chunk-PZZKQVQV.js.map +0 -1
  171. package/dist/chunk-Q2JSAVQ3.js +0 -671
  172. package/dist/chunk-Q2JSAVQ3.js.map +0 -1
  173. package/dist/chunk-RDOAVVHY.js +0 -699
  174. package/dist/chunk-RDOAVVHY.js.map +0 -1
  175. package/dist/chunk-SGKPNBXE.js +0 -60
  176. package/dist/chunk-SGKPNBXE.js.map +0 -1
  177. package/dist/chunk-SMQXZGLZ.js +0 -351
  178. package/dist/chunk-SMQXZGLZ.js.map +0 -1
  179. package/dist/chunk-UHEZW5BU.js +0 -2918
  180. package/dist/chunk-UHEZW5BU.js.map +0 -1
  181. package/dist/chunk-UPWGXKXB.js +0 -254
  182. package/dist/chunk-UPWGXKXB.js.map +0 -1
  183. package/dist/chunk-VISA6CI3.js +0 -200
  184. package/dist/chunk-VISA6CI3.js.map +0 -1
  185. package/dist/chunk-WMTCUOQL.js +0 -474
  186. package/dist/chunk-WMTCUOQL.js.map +0 -1
  187. package/dist/chunk-WRTOVNN4.js +0 -4728
  188. package/dist/chunk-WRTOVNN4.js.map +0 -1
  189. package/dist/chunk-WSTRQZYQ.js +0 -5576
  190. package/dist/chunk-WSTRQZYQ.js.map +0 -1
  191. package/dist/chunk-XBG2W2VW.js +0 -6434
  192. package/dist/chunk-XBG2W2VW.js.map +0 -1
  193. package/dist/chunk-YEJR7IXO.js +0 -68
  194. package/dist/chunk-YEJR7IXO.js.map +0 -1
  195. package/dist/chunk-YJZA2BIK.js +0 -1338
  196. package/dist/chunk-YJZA2BIK.js.map +0 -1
  197. package/dist/completion-gate-BMy5LGoP.d.ts +0 -256
  198. package/dist/conversation.js.map +0 -1
  199. package/dist/coordination-BZZSVYpZ.d.ts +0 -2570
  200. package/dist/environment-provider.js.map +0 -1
  201. package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
  202. package/dist/knowledge.js.map +0 -1
  203. package/dist/local-harness-BDNcl6jI.d.ts +0 -175
  204. package/dist/loop-runner-bin-68aoM9-7.d.ts +0 -199
  205. package/dist/loop-runner-bin.js.map +0 -1
  206. package/dist/loops.js.map +0 -1
  207. package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
  208. package/dist/protected-model-port-B4t-OQjL.d.ts +0 -271
  209. package/dist/redact-BuFjxBUJ.d.ts +0 -481
  210. package/dist/sanitize-DEbPNtyI.d.ts +0 -328
  211. package/dist/structural-rollout-DEh6CEsa.d.ts +0 -446
  212. package/dist/supervise-4_48wwvy.d.ts +0 -379
  213. package/dist/types-BCoemcXU.d.ts +0 -802
  214. package/dist/types-BwoZWq-i.d.ts +0 -510
  215. package/dist/types-Cbp72qyu.d.ts +0 -491
  216. package/dist/types-CmYCMbFT.d.ts +0 -203
  217. package/dist/types-CvNwMzQt.d.ts +0 -957
  218. package/dist/worktree-fanout-DxhAWr5Z.d.ts +0 -999
@@ -0,0 +1,1168 @@
1
+ import { f as zeroTokenUsage } from "./util-MVgdwuIS.js";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ //#region src/runtime/tangle-sandbox-exact-process-provider.ts
4
+ const exactProcessProviderMarker = "agent-runtime.exact-process-provider";
5
+ const exactProcessEgressMarker = "agent-runtime.exact-process-egress";
6
+ /**
7
+ * Adapt Tangle Sandbox's managed control runtime to Runtime's exact-process provider.
8
+ *
9
+ * The adapter deliberately exposes no ordinary agent environment: an exact experiment
10
+ * must start a fresh Sandbox with no managed agent and launch its declared argv directly.
11
+ */
12
+ function createTangleSandboxExactProcessProvider(client, options = {}) {
13
+ const name = options.name ?? "tangle-sandbox-exact-process";
14
+ if (!name.trim()) throw new Error("Tangle Sandbox exact-process provider name must not be empty");
15
+ return {
16
+ name,
17
+ exactProcess: {
18
+ async create(input) {
19
+ throwIfAborted(input.signal);
20
+ assertNoProviderOptions(input.providerOptions);
21
+ const egressPolicy = sandboxEgressPolicy(input.egress);
22
+ const metadata = exactMetadata(input.metadata, name, egressPolicy);
23
+ const sandbox = await client.create({
24
+ environment: requiredText(input.image, "exact-process image"),
25
+ agent: false,
26
+ bare: false,
27
+ ephemeral: true,
28
+ egressPolicy,
29
+ resources: sandboxResources(input),
30
+ maxLifetimeSeconds: sandboxLifetimeSeconds(input.maxLifetimeMs),
31
+ metadata,
32
+ idempotencyKey: requiredText(input.idempotencyKey, "exact-process idempotency key")
33
+ }, {
34
+ ...input.provisionTimeoutMs === void 0 ? {} : { timeoutMs: positiveInteger(input.provisionTimeoutMs, "provision timeout") },
35
+ ...input.signal === void 0 ? {} : { signal: input.signal }
36
+ });
37
+ try {
38
+ throwIfAborted(input.signal);
39
+ assertExactSandboxMetadata(sandbox, metadata);
40
+ await assertExactSandboxEgress(sandbox, egressPolicy);
41
+ } catch (error) {
42
+ await discardInvalidSandbox(sandbox, error);
43
+ }
44
+ return sandboxAsExactProcessEnvironment(sandbox, name);
45
+ },
46
+ async get(id) {
47
+ const sandbox = await client.get(id);
48
+ if (!sandbox || !isExactSandbox(sandbox, name)) return null;
49
+ await assertExactSandboxEgress(sandbox, egressFromMetadata(sandbox.metadata));
50
+ return sandboxAsExactProcessEnvironment(sandbox, name);
51
+ },
52
+ async list(query) {
53
+ assertNoProviderOptions(query?.providerOptions);
54
+ const sandboxes = await client.list();
55
+ return Promise.all(sandboxes.filter((sandbox) => isExactSandbox(sandbox, name)).filter((sandbox) => metadataMatches(sandbox.metadata, query?.metadata)).map(async (sandbox) => {
56
+ await assertExactSandboxEgress(sandbox, egressFromMetadata(sandbox.metadata));
57
+ return sandboxAsExactProcessEnvironment(sandbox, name);
58
+ }));
59
+ }
60
+ },
61
+ capabilities: exactProcessOnlyCapabilities,
62
+ async create() {
63
+ throw new Error(`agent environment provider "${name}" supports exactProcess.create() only`);
64
+ }
65
+ };
66
+ }
67
+ function sandboxAsExactProcessEnvironment(sandbox, provider) {
68
+ return {
69
+ id: requiredText(sandbox.id, "Sandbox id"),
70
+ provider,
71
+ ...sandbox.metadata ? { metadata: sandbox.metadata } : {},
72
+ process: {
73
+ async list() {
74
+ return (await sandbox.process.list()).map((status) => exactProcessStatus(status));
75
+ },
76
+ async get(pid) {
77
+ const process = await sandbox.process.get(pid);
78
+ return process ? sandboxProcessAsExactProcess(process) : null;
79
+ },
80
+ async spawn(input, options) {
81
+ return sandboxProcessAsExactProcess(await afterAbortCheck(options?.signal, () => sandbox.process.spawnExact(input.executable, [...input.args], {
82
+ cwd: input.cwd,
83
+ env: { ...input.env },
84
+ inheritEnv: false,
85
+ ...input.stdin === void 0 ? {} : { stdin: input.stdin },
86
+ timeoutMs: input.timeoutMs
87
+ })));
88
+ }
89
+ },
90
+ async writeFile(path, bytes, options) {
91
+ if (sandbox.fs.supportsWriteMode !== true) throw new Error("Tangle Sandbox does not declare exact file-mode support");
92
+ await afterAbortCheck(options.signal, () => sandbox.fs.write(path, Buffer.from(bytes).toString("base64"), {
93
+ encoding: "base64",
94
+ mode: fileMode(options.mode)
95
+ }));
96
+ },
97
+ async readFile(path, options) {
98
+ const maxBytes = nonnegativeInteger(options.maxBytes, "exact-process file read maximum");
99
+ const initialSize = nonnegativeInteger((await afterAbortCheck(options.signal, () => sandbox.fs.stat(path))).size, `Tangle Sandbox file size for "${path}"`);
100
+ if (initialSize > maxBytes) throw new Error(`Tangle Sandbox file "${path}" exceeds the ${maxBytes}-byte exact read maximum`);
101
+ const result = await afterAbortCheck(options.signal, () => sandbox.fs.readBatch([path], { encoding: "base64" }));
102
+ const failure = result.errors.find((entry) => entry.path === path);
103
+ if (failure) throw new Error(`Tangle Sandbox failed to read "${path}": ${failure.error}`);
104
+ const files = result.files.filter((entry) => entry.path === path);
105
+ if (files.length !== 1) throw new Error(`Tangle Sandbox returned ${files.length} files for exact read "${path}"`);
106
+ const file = files[0];
107
+ if (file.encoding !== "base64") throw new Error(`Tangle Sandbox returned non-binary content for exact read "${path}"`);
108
+ const size = nonnegativeInteger(file.size, `Tangle Sandbox file size for "${path}"`);
109
+ if (size !== initialSize) throw new Error(`Tangle Sandbox file "${path}" changed during exact read`);
110
+ if (size > maxBytes) throw new Error(`Tangle Sandbox file "${path}" exceeds the ${maxBytes}-byte exact read maximum`);
111
+ const bytes = Buffer.from(file.content, "base64");
112
+ if (bytes.byteLength !== size || bytes.toString("base64") !== file.content) throw new Error(`Tangle Sandbox returned an invalid binary payload for exact read "${path}"`);
113
+ return Uint8Array.from(bytes);
114
+ },
115
+ async destroy() {
116
+ await sandbox.delete();
117
+ }
118
+ };
119
+ }
120
+ function sandboxProcessAsExactProcess(process) {
121
+ const pid = positiveInteger(process.pid, "Tangle Sandbox process pid");
122
+ return {
123
+ pid,
124
+ async status() {
125
+ return exactProcessStatus(await process.status(), pid);
126
+ },
127
+ async wait() {
128
+ const waitExitCode = await process.wait();
129
+ if (!Number.isSafeInteger(waitExitCode)) throw new Error("Tangle Sandbox process wait returned an invalid exit code");
130
+ const status = exactProcessStatus(await process.status(), pid);
131
+ if (status.running || !status.termination) throw new Error("Tangle Sandbox process wait returned before terminal status");
132
+ if (status.termination.kind === "exit" && status.termination.exitCode !== waitExitCode) throw new Error("Tangle Sandbox process wait and status disagree on exit code");
133
+ return status.termination;
134
+ },
135
+ async kill() {
136
+ await process.kill("SIGKILL", { tree: true });
137
+ },
138
+ async *stdout() {
139
+ yield* process.stdout();
140
+ },
141
+ async *stderr() {
142
+ yield* process.stderr();
143
+ }
144
+ };
145
+ }
146
+ function exactProcessStatus(status, expectedPid) {
147
+ const pid = positiveInteger(status.pid, "Tangle Sandbox process pid");
148
+ if (expectedPid !== void 0 && pid !== expectedPid) throw new Error("Tangle Sandbox process status changed process identity");
149
+ if (typeof status.running !== "boolean") throw new Error("Tangle Sandbox process status is missing running state");
150
+ if (!Number.isSafeInteger(status.exitCode)) throw new Error("Tangle Sandbox process status is missing an integer exit code");
151
+ const exitSignal = optionalText(status.exitSignal, "Tangle Sandbox process exit signal");
152
+ if (status.running) {
153
+ if (status.exitCode !== -1) throw new Error("Tangle Sandbox running process must report exit code -1");
154
+ if (exitSignal) throw new Error("Tangle Sandbox running process must not report an exit signal");
155
+ return {
156
+ pid,
157
+ running: true,
158
+ exitCode: -1
159
+ };
160
+ }
161
+ const termination = exitSignal ? {
162
+ kind: "signal",
163
+ signal: exitSignal
164
+ } : status.exitCode >= 0 ? {
165
+ kind: "exit",
166
+ exitCode: status.exitCode
167
+ } : void 0;
168
+ if (!termination) throw new Error("Tangle Sandbox stopped process has no terminal reason");
169
+ return {
170
+ pid,
171
+ running: false,
172
+ exitCode: status.exitCode,
173
+ ...exitSignal ? { exitSignal } : {},
174
+ termination
175
+ };
176
+ }
177
+ function exactMetadata(metadata, provider, egressPolicy) {
178
+ for (const marker of [exactProcessProviderMarker, exactProcessEgressMarker]) if (Object.hasOwn(metadata, marker)) throw new Error(`exact-process metadata must not set "${marker}"`);
179
+ return {
180
+ ...metadata,
181
+ [exactProcessProviderMarker]: provider,
182
+ [exactProcessEgressMarker]: serializeEgressPolicy(egressPolicy)
183
+ };
184
+ }
185
+ function isExactSandbox(sandbox, provider) {
186
+ return sandbox.metadata?.[exactProcessProviderMarker] === provider;
187
+ }
188
+ function metadataMatches(metadata, expected) {
189
+ return expected === void 0 || Object.entries(expected).every(([key, value]) => isDeepStrictEqual(metadata?.[key], value));
190
+ }
191
+ function assertExactSandboxMetadata(sandbox, expected) {
192
+ if (!metadataMatches(sandbox.metadata, expected)) throw new Error("Tangle Sandbox did not persist exact-process metadata");
193
+ }
194
+ function egressFromMetadata(metadata) {
195
+ const encoded = metadata?.[exactProcessEgressMarker];
196
+ if (typeof encoded !== "string") throw new Error("Tangle Sandbox exact-process environment is missing egress metadata");
197
+ try {
198
+ const parsed = JSON.parse(encoded);
199
+ if (!parsed || typeof parsed !== "object") throw new Error("expected egress object");
200
+ const policy = parsed;
201
+ if (policy.mode === "blocked" && policy.allowDomains === void 0) return { mode: "blocked" };
202
+ if (policy.mode === "strict" && policy.includeImplicitDomains === false && Array.isArray(policy.allowDomains) && policy.allowDomains.every((domain) => typeof domain === "string")) {
203
+ const allowDomains = sortedDomains(policy.allowDomains);
204
+ if (new Set(allowDomains).size === allowDomains.length) return {
205
+ mode: "strict",
206
+ allowDomains,
207
+ includeImplicitDomains: false
208
+ };
209
+ }
210
+ } catch {
211
+ throw new Error("Tangle Sandbox exact-process environment has invalid egress metadata");
212
+ }
213
+ throw new Error("Tangle Sandbox exact-process environment has invalid egress metadata");
214
+ }
215
+ async function assertExactSandboxEgress(sandbox, expected) {
216
+ const actual = (await sandbox.egress.get()).policy;
217
+ if (actual.mode !== expected.mode) throw new Error(`Tangle Sandbox egress mismatch: expected ${expected.mode}, received ${actual.mode}`);
218
+ if (expected.mode === "blocked") {
219
+ const allowDomains = actual.allowDomains;
220
+ if (actual.mode === "blocked" && (allowDomains === void 0 || Array.isArray(allowDomains) && allowDomains.length === 0)) return;
221
+ throw new Error("Tangle Sandbox blocked egress retained an allowlist");
222
+ }
223
+ if (actual.mode !== "strict") throw new Error("Tangle Sandbox did not return strict egress policy");
224
+ const expectedDomains = sortedDomains(expected.allowDomains);
225
+ if (!isDeepStrictEqual(sortedDomains(actual.allowDomains ?? []), expectedDomains)) throw new Error("Tangle Sandbox strict egress differs from the exact allowlist");
226
+ if (actual.includeImplicitDomains !== false) throw new Error("Tangle Sandbox strict egress retained implicit domains");
227
+ }
228
+ function sandboxEgressPolicy(input) {
229
+ if (input.mode === "blocked") return { mode: "blocked" };
230
+ const allowDomains = input.allowDomains.map((domain) => requiredText(domain, "strict egress domain"));
231
+ if (new Set(allowDomains).size !== allowDomains.length) throw new Error("strict egress domains must not contain duplicates");
232
+ return {
233
+ mode: "strict",
234
+ allowDomains,
235
+ includeImplicitDomains: false
236
+ };
237
+ }
238
+ function serializeEgressPolicy(policy) {
239
+ return JSON.stringify(policy.mode === "blocked" ? { mode: "blocked" } : {
240
+ mode: "strict",
241
+ allowDomains: sortedDomains(policy.allowDomains),
242
+ includeImplicitDomains: false
243
+ });
244
+ }
245
+ function sandboxResources(input) {
246
+ const cpuCores = positiveNumber(input.resources.cpu, "exact-process cpu");
247
+ const memoryMB = positiveInteger(input.resources.memoryMb, "exact-process memory");
248
+ const diskMb = positiveInteger(input.resources.diskMb, "exact-process disk");
249
+ if (diskMb % 1024 !== 0) throw new Error("Tangle Sandbox exact-process disk must be a whole GiB");
250
+ return {
251
+ cpuCores,
252
+ memoryMB,
253
+ diskGB: diskMb / 1024
254
+ };
255
+ }
256
+ function sandboxLifetimeSeconds(maxLifetimeMs) {
257
+ const milliseconds = positiveInteger(maxLifetimeMs, "exact-process maximum lifetime");
258
+ if (milliseconds % 1e3 !== 0) throw new Error("Tangle Sandbox exact-process maximum lifetime must be a whole number of seconds");
259
+ return milliseconds / 1e3;
260
+ }
261
+ function fileMode(value) {
262
+ const mode = nonnegativeInteger(value, "exact-process file mode");
263
+ if (mode > 4095) throw new Error("exact-process file mode exceeds POSIX mode bits");
264
+ return mode;
265
+ }
266
+ function assertNoProviderOptions(providerOptions) {
267
+ if (providerOptions && Object.keys(providerOptions).length > 0) throw new Error("Tangle Sandbox exact-process provider does not accept providerOptions");
268
+ }
269
+ function exactProcessOnlyCapabilities() {
270
+ return {
271
+ profile: {
272
+ namedProfiles: false,
273
+ systemPrompt: false,
274
+ instructions: false,
275
+ tools: false,
276
+ permissions: false,
277
+ mcp: false,
278
+ subagents: false,
279
+ resources: {
280
+ files: false,
281
+ instructions: false,
282
+ tools: false,
283
+ skills: false,
284
+ agents: false,
285
+ commands: false
286
+ },
287
+ hooks: false,
288
+ modes: false,
289
+ runtimeUpdate: false,
290
+ validation: false
291
+ },
292
+ streaming: {
293
+ live: false,
294
+ replay: false,
295
+ detach: false,
296
+ turnIdempotency: false
297
+ },
298
+ sessions: {
299
+ continue: false,
300
+ list: false,
301
+ messages: false
302
+ },
303
+ workspace: {
304
+ read: false,
305
+ write: false,
306
+ exec: false,
307
+ git: false,
308
+ upload: false,
309
+ download: false
310
+ },
311
+ branching: {
312
+ checkpoint: false,
313
+ fork: false
314
+ },
315
+ placement: false,
316
+ usage: false,
317
+ confidential: false,
318
+ exactProcess: { egress: ["blocked", "strict"] }
319
+ };
320
+ }
321
+ async function discardInvalidSandbox(sandbox, cause) {
322
+ try {
323
+ await sandbox.delete();
324
+ } catch (destroyError) {
325
+ throw new AggregateError([cause, destroyError], "Tangle Sandbox exact-process creation failed and cleanup failed");
326
+ }
327
+ throw cause;
328
+ }
329
+ function sortedDomains(domains) {
330
+ return [...domains].sort((left, right) => left.localeCompare(right));
331
+ }
332
+ function requiredText(value, label) {
333
+ if (typeof value !== "string" || !value.trim()) throw new Error(`${label} must be a non-empty string`);
334
+ return value;
335
+ }
336
+ function optionalText(value, label) {
337
+ if (value === void 0) return void 0;
338
+ return requiredText(value, label);
339
+ }
340
+ function positiveNumber(value, label) {
341
+ if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be positive`);
342
+ return value;
343
+ }
344
+ function positiveInteger(value, label) {
345
+ if (!Number.isSafeInteger(value) || value < 1) throw new Error(`${label} must be a positive integer`);
346
+ return value;
347
+ }
348
+ function nonnegativeInteger(value, label) {
349
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a non-negative integer`);
350
+ return value;
351
+ }
352
+ function throwIfAborted(signal) {
353
+ signal?.throwIfAborted();
354
+ }
355
+ async function afterAbortCheck(signal, operation) {
356
+ throwIfAborted(signal);
357
+ const result = await operation();
358
+ throwIfAborted(signal);
359
+ return result;
360
+ }
361
+ //#endregion
362
+ //#region src/runtime/environment-provider.ts
363
+ var ValidationError = class extends Error {
364
+ constructor(message, options) {
365
+ super(message, options);
366
+ this.name = "ValidationError";
367
+ }
368
+ };
369
+ /** Create a registry that resolves provider names to concrete provider instances.
370
+ * @experimental */
371
+ function createAgentEnvironmentProviderRegistry(providers = []) {
372
+ const entries = /* @__PURE__ */ new Map();
373
+ const registry = {
374
+ register(provider, options = {}) {
375
+ if (!provider.name) throw new ValidationError("agent environment provider registry: provider.name required");
376
+ if (!options.replace && entries.has(provider.name)) throw new ValidationError(`agent environment provider registry: provider "${provider.name}" already registered`);
377
+ entries.set(provider.name, provider);
378
+ },
379
+ has(name) {
380
+ return entries.has(name);
381
+ },
382
+ get(name) {
383
+ return entries.get(name);
384
+ },
385
+ require(name) {
386
+ const provider = entries.get(name);
387
+ if (!provider) {
388
+ const available = Array.from(entries.keys()).sort();
389
+ throw new ValidationError(`agent environment provider registry: provider "${name}" is not registered${available.length > 0 ? `; available: ${available.join(", ")}` : ""}`);
390
+ }
391
+ return provider;
392
+ },
393
+ names() {
394
+ return Array.from(entries.keys()).sort();
395
+ },
396
+ providers() {
397
+ return registry.names().map((name) => registry.require(name));
398
+ },
399
+ async capabilities(name) {
400
+ return registry.require(name).capabilities();
401
+ }
402
+ };
403
+ for (const provider of providers) registry.register(provider);
404
+ return registry;
405
+ }
406
+ /** Resolve a provider instance or registry name, failing loudly when a name is unknown.
407
+ * @experimental */
408
+ function resolveAgentEnvironmentProvider(provider, registry) {
409
+ if (typeof provider !== "string") return provider;
410
+ if (!registry) throw new ValidationError(`agent environment provider "${provider}" requires an AgentEnvironmentProviderRegistry`);
411
+ return registry.require(provider);
412
+ }
413
+ /** Adapt a neutral environment provider to the `SandboxClient` interface used by existing loop paths.
414
+ * @experimental */
415
+ function providerAsSandboxClient(provider, options = {}) {
416
+ return { async create(createOptions) {
417
+ const mapped = {
418
+ ...options.defaults ?? {},
419
+ ...createInputFromSandboxOptions(createOptions),
420
+ ...options.mapCreateOptions?.(createOptions) ?? {}
421
+ };
422
+ if (mapped.profile === void 0) throw new ValidationError(`providerAsSandboxClient(${provider.name}): profile required in defaults or CreateSandboxOptions.backend.profile`);
423
+ return environmentAsSandboxInstance(await provider.create(mapped), { requireTerminalEvent: options.requireTerminalEvent ?? true });
424
+ } };
425
+ }
426
+ /** Adapt a `SandboxClient` into the shared `AgentEnvironmentProvider` contract.
427
+ * @experimental */
428
+ function sandboxClientAsProvider(client, options = {}) {
429
+ const providerName = options.name ?? "tangle-sandbox";
430
+ return {
431
+ name: providerName,
432
+ capabilities: async () => {
433
+ if (options.capabilities) return typeof options.capabilities === "function" ? options.capabilities() : options.capabilities;
434
+ return defaultTangleSandboxCapabilities({ namedProfiles: options.resolveProfile !== void 0 });
435
+ },
436
+ ...options.validateProfile ? { validateProfile: options.validateProfile } : {},
437
+ async create(input) {
438
+ const createOptions = options.mapCreateInput?.(input) ?? await sandboxOptionsFromCreateInput(input, options.defaultBackend ?? "opencode", options.resolveProfile);
439
+ return sandboxInstanceAsEnvironment(await client.create(createOptions), providerName, client);
440
+ },
441
+ ...hasGet(client) ? { async get(id) {
442
+ const box = await client.get(id);
443
+ return box ? sandboxInstanceAsEnvironment(box, providerName, client) : null;
444
+ } } : {},
445
+ ...hasList(client) ? { async list(query) {
446
+ return (await client.list(query?.providerOptions)).map((box) => ({
447
+ id: String(box.id),
448
+ provider: providerName,
449
+ name: typeof box.name === "string" ? box.name : void 0,
450
+ status: statusFromUnknown(readBoxStatus(box)),
451
+ metadata: readBoxMetadata(box)
452
+ }));
453
+ } } : {}
454
+ };
455
+ }
456
+ /** Adapt an environment provider into an `ExecutorFactory` for `createExecutor`.
457
+ * @experimental */
458
+ function providerAsExecutor(provider, options = {}) {
459
+ return (spec, ctx) => createProviderExecutor(provider, spec.profile, ctx, options);
460
+ }
461
+ function createProviderExecutor(provider, profile, ctx, options) {
462
+ const controller = new AbortController();
463
+ const abortIfSignalled = () => {
464
+ if (ctx.signal.aborted) controller.abort();
465
+ };
466
+ abortIfSignalled();
467
+ if (!ctx.signal.aborted) ctx.signal.addEventListener("abort", abortIfSignalled, { once: true });
468
+ let environment;
469
+ let artifact;
470
+ return {
471
+ runtime: options.runtime ?? provider.name,
472
+ execute(task, signal) {
473
+ return streamProviderExecutor({
474
+ provider,
475
+ profile,
476
+ task,
477
+ signal,
478
+ controller,
479
+ options,
480
+ onEnvironment: (env) => {
481
+ environment = env;
482
+ },
483
+ onArtifact: (next) => {
484
+ artifact = next;
485
+ }
486
+ });
487
+ },
488
+ async teardown(_grace) {
489
+ controller.abort();
490
+ await environment?.destroy?.();
491
+ return { destroyed: true };
492
+ },
493
+ resultArtifact() {
494
+ if (!artifact) throw new ValidationError(`providerAsExecutor(${provider.name}): resultArtifact() read before stream drained`);
495
+ return artifact;
496
+ }
497
+ };
498
+ }
499
+ async function* streamProviderExecutor(args) {
500
+ const started = Date.now();
501
+ const linked = mergeAbortSignals(args.signal, args.controller.signal);
502
+ const environment = await args.provider.create({
503
+ ...args.options.defaults ?? {},
504
+ profile: args.profile,
505
+ signal: linked
506
+ });
507
+ args.onEnvironment(environment);
508
+ const turn = args.options.taskToTurn?.(args.task, args.profile) ?? taskToTurnInput(args.task, linked);
509
+ const events = [];
510
+ const tokens = zeroTokenUsage();
511
+ let usd = 0;
512
+ let text = "";
513
+ let terminal = false;
514
+ try {
515
+ for await (const event of environment.stream({
516
+ ...turn,
517
+ signal: linked
518
+ })) {
519
+ events.push(event);
520
+ text += textFromEnvironmentEvent(event);
521
+ const usage = usageFromEnvironmentEvent(event);
522
+ if (usage.input || usage.output) {
523
+ tokens.input += usage.input;
524
+ tokens.output += usage.output;
525
+ yield {
526
+ kind: "tokens",
527
+ input: usage.input,
528
+ output: usage.output
529
+ };
530
+ }
531
+ if (usage.usd) {
532
+ usd += usage.usd;
533
+ yield {
534
+ kind: "cost",
535
+ usd: usage.usd
536
+ };
537
+ }
538
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
539
+ }
540
+ if ((args.options.requireTerminalEvent ?? true) && !terminal) throw new ValidationError(`providerAsExecutor(${args.provider.name}): stream ended without a terminal result/done/status event`);
541
+ yield { kind: "iteration" };
542
+ const result = resultFromEvents(events, text);
543
+ const spent = {
544
+ iterations: 1,
545
+ tokens,
546
+ usd,
547
+ ms: Date.now() - started
548
+ };
549
+ args.onArtifact({
550
+ outRef: contentRef(`provider:${args.provider.name}`, result),
551
+ out: result,
552
+ spent
553
+ });
554
+ } finally {
555
+ if (args.options.destroyOnSettle ?? true) await environment.destroy?.();
556
+ }
557
+ }
558
+ function createInputFromSandboxOptions(options) {
559
+ const profile = options?.backend?.profile;
560
+ const backend = options?.backend?.type;
561
+ return {
562
+ ...profile !== void 0 ? { profile } : {},
563
+ ...backend ? { backend } : {},
564
+ workspace: {
565
+ ...options?.environment ? { environment: options.environment } : {},
566
+ ...options?.git?.url ? { repoUrl: options.git.url } : {},
567
+ ...options?.git?.ref ? { gitRef: options.git.ref } : {}
568
+ },
569
+ ...options?.resources ? { resources: options.resources } : {},
570
+ ...options?.env ? { env: options.env } : {},
571
+ ...options?.secrets ? { secrets: options.secrets } : {},
572
+ ...options?.metadata ? { metadata: options.metadata } : {},
573
+ ...options?.name ? { name: options.name } : {},
574
+ ...options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {},
575
+ providerOptions: { sandboxCreateOptions: options ?? {} }
576
+ };
577
+ }
578
+ async function sandboxOptionsFromCreateInput(input, defaultBackend, resolveProfile) {
579
+ const backendType = input.backend ?? defaultBackend;
580
+ const workspace = input.workspace ?? {};
581
+ const environment = sandboxEnvironmentFromWorkspace(workspace);
582
+ const providerOptions = input.providerOptions?.sandboxCreateOptions;
583
+ const base = providerOptions && typeof providerOptions === "object" ? { ...providerOptions } : {};
584
+ assertSandboxSecretNames(input.secrets);
585
+ assertSandboxSecretNames(base.secrets);
586
+ const profile = await sandboxProfileFromReference(input.profile, resolveProfile);
587
+ const { profile: _baseProfile, ...baseBackend } = base.backend ?? {};
588
+ return {
589
+ ...base,
590
+ ...environment ? { environment } : {},
591
+ ...workspace.repoUrl ? { git: {
592
+ url: workspace.repoUrl,
593
+ ref: workspace.gitRef
594
+ } } : {},
595
+ ...input.resources ? { resources: input.resources } : {},
596
+ ...input.env ? { env: input.env } : {},
597
+ ...Array.isArray(input.secrets) ? { secrets: input.secrets } : {},
598
+ ...input.metadata ? { metadata: input.metadata } : {},
599
+ ...input.name ? { name: input.name } : {},
600
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {},
601
+ backend: {
602
+ ...baseBackend,
603
+ type: backendType,
604
+ profile
605
+ }
606
+ };
607
+ }
608
+ function assertSandboxSecretNames(secrets) {
609
+ if (secrets !== void 0 && (!Array.isArray(secrets) || secrets.some((secret) => typeof secret !== "string" || secret.trim().length === 0))) throw new ValidationError("Tangle Sandbox secret names must be non-empty strings; secret values are unsupported");
610
+ }
611
+ function sandboxEnvironmentFromWorkspace(workspace) {
612
+ if (workspace.environment !== void 0 && workspace.image !== void 0 && workspace.environment !== workspace.image) throw new ValidationError("Tangle Sandbox accepts one environment value; workspace.environment and workspace.image must match");
613
+ return workspace.environment ?? workspace.image;
614
+ }
615
+ async function sandboxProfileFromReference(profile, resolveProfile) {
616
+ if (typeof profile !== "string") return profile;
617
+ if (!resolveProfile) throw new ValidationError(`Tangle Sandbox requires an inline AgentProfile; named profile "${profile}" needs SandboxClientProviderOptions.resolveProfile`);
618
+ return resolveProfile(profile);
619
+ }
620
+ function environmentAsSandboxInstance(environment, options) {
621
+ return {
622
+ id: environment.id,
623
+ name: environment.name,
624
+ status: "running",
625
+ async refresh() {
626
+ await environment.refresh?.();
627
+ },
628
+ async *streamPrompt(message, promptOptions) {
629
+ let terminal = false;
630
+ const input = turnInputFromPrompt(message, promptOptions);
631
+ for await (const event of environment.stream(input)) {
632
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
633
+ const usageEvent = usageSandboxEvent(event);
634
+ if (usageEvent) yield usageEvent;
635
+ yield sandboxEventFromEnvironmentEvent(event);
636
+ }
637
+ if (options.requireTerminalEvent && !terminal) throw new ValidationError(`providerAsSandboxClient(${environment.provider}): stream ended without a terminal result/done/status event`);
638
+ },
639
+ async prompt(message, promptOptions) {
640
+ const events = [];
641
+ let text = "";
642
+ let usage;
643
+ let terminal = false;
644
+ for await (const event of environment.stream(turnInputFromPrompt(message, promptOptions))) {
645
+ events.push(event);
646
+ if (isTerminalEnvironmentEvent(event)) terminal = true;
647
+ text += textFromEnvironmentEvent(event);
648
+ usage = mergeTokenUsage(usage, event.usage);
649
+ }
650
+ if (options.requireTerminalEvent && !terminal) throw new ValidationError(`providerAsSandboxClient(${environment.provider}): prompt ended without a terminal result/done/status event`);
651
+ return {
652
+ response: resultFromEvents(events, text).content,
653
+ success: true,
654
+ status: "success",
655
+ durationMs: 0,
656
+ ...usage ? { usage } : {}
657
+ };
658
+ },
659
+ ...environment.dispatch && environment.session ? { async dispatchPrompt(message, promptOptions) {
660
+ const session = await environment.dispatch?.(turnInputFromPrompt(message, promptOptions));
661
+ if (!session) throw new ValidationError("providerAsSandboxClient: dispatch returned no session");
662
+ return sandboxDispatchResultFromSessionRef(session);
663
+ } } : {},
664
+ ...environment.session ? { session(id) {
665
+ return sandboxSessionFromAgentSession(environment.session?.(id));
666
+ } } : {},
667
+ ...environment.read ? { read: environment.read.bind(environment) } : {},
668
+ ...environment.write ? { write: environment.write.bind(environment) } : {},
669
+ ...environment.exec ? { exec: environment.exec.bind(environment) } : {},
670
+ ...environment.checkpoint ? { async checkpoint(checkpointOptions) {
671
+ const checkpoint = await environment.checkpoint?.(checkpointOptions);
672
+ return {
673
+ checkpointId: checkpoint?.id,
674
+ id: checkpoint?.id
675
+ };
676
+ } } : {},
677
+ ...environment.fork ? { async fork(checkpointId, forkOptions) {
678
+ const forked = await environment.fork?.({ id: checkpointId }, forkOptions);
679
+ if (!forked) throw new ValidationError("providerAsSandboxClient: fork returned no environment");
680
+ return environmentAsSandboxInstance(forked, options);
681
+ } } : {},
682
+ async delete() {
683
+ await environment.destroy?.();
684
+ }
685
+ };
686
+ }
687
+ function sandboxInstanceAsEnvironment(box, providerName, client) {
688
+ return {
689
+ id: String(box.id),
690
+ provider: providerName,
691
+ ...typeof box.name === "string" ? { name: box.name } : {},
692
+ async status() {
693
+ await maybeRefresh(box);
694
+ return statusFromUnknown(readBoxStatus(box));
695
+ },
696
+ async *stream(input) {
697
+ for await (const event of box.streamPrompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input))) yield environmentEventFromSandboxEvent(event);
698
+ },
699
+ ...hasDispatchPrompt(box) ? { async dispatch(input) {
700
+ return sessionRefFromSandboxDispatch(await box.dispatchPrompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input)), providerName);
701
+ } } : {},
702
+ ...hasSession(box) ? { session(id) {
703
+ return sandboxSessionAsAgentSession(box.session(id));
704
+ } } : {},
705
+ ...hasRead(box) ? { read: box.read.bind(box) } : {},
706
+ ...hasWrite(box) ? { write: box.write.bind(box) } : {},
707
+ ...hasExec(box) ? { async exec(command, options) {
708
+ return execResultFromSandboxExecResult(await box.exec(command, options));
709
+ } } : {},
710
+ async checkpoint(options) {
711
+ return {
712
+ id: (await box.snapshot({ ...options?.name ? { tags: [options.name] } : {} })).snapshotId,
713
+ provider: providerName,
714
+ ...options?.metadata ? { metadata: options.metadata } : {}
715
+ };
716
+ },
717
+ async fork(checkpoint, options) {
718
+ return sandboxInstanceAsEnvironment(await client.create({
719
+ fromSnapshot: checkpoint.id,
720
+ fromSandboxId: String(box.id),
721
+ ...options?.name ? { name: options.name } : {},
722
+ ...options?.metadata ? { metadata: options.metadata } : {}
723
+ }), providerName, client);
724
+ },
725
+ async placement() {
726
+ return placementInfoFromLoopPlacement(client.describePlacement?.(box), box);
727
+ },
728
+ async refresh() {
729
+ await maybeRefresh(box);
730
+ },
731
+ async destroy() {
732
+ await destroyBox(box);
733
+ }
734
+ };
735
+ }
736
+ function sandboxSessionAsAgentSession(session) {
737
+ return {
738
+ id: session.id,
739
+ async status() {
740
+ const status = await session.status();
741
+ if (!status) return null;
742
+ return sessionStatusFromUnknown(status.status);
743
+ },
744
+ async *events(options) {
745
+ for await (const event of session.events(options)) yield environmentEventFromSandboxEvent(event);
746
+ },
747
+ async result() {
748
+ return agentTurnResultFromPromptResult(await session.result());
749
+ },
750
+ async prompt(input) {
751
+ return agentTurnResultFromPromptResult(await session.prompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input)));
752
+ },
753
+ cancel() {
754
+ return session.interrupt().then(() => void 0);
755
+ }
756
+ };
757
+ }
758
+ function sandboxSessionFromAgentSession(session) {
759
+ if (!session) throw new ValidationError("providerAsSandboxClient: session is unavailable");
760
+ return {
761
+ id: session.id,
762
+ async status() {
763
+ const status = await session.status();
764
+ if (!status) return null;
765
+ return {
766
+ id: session.id,
767
+ status: sandboxSessionStatusFromAgentSessionStatus(status)
768
+ };
769
+ },
770
+ async *events(options) {
771
+ for await (const event of session.events(options)) yield sandboxEventFromEnvironmentEvent(event);
772
+ },
773
+ async result() {
774
+ return promptResultFromAgentTurnResult(await session.result());
775
+ },
776
+ async prompt(message, options) {
777
+ return promptResultFromAgentTurnResult(await session.prompt(turnInputFromPrompt(message, options)));
778
+ },
779
+ async interrupt() {
780
+ await session.cancel();
781
+ return { cancelled: true };
782
+ }
783
+ };
784
+ }
785
+ function sandboxSessionStatusFromAgentSessionStatus(status) {
786
+ switch (status) {
787
+ case "pending":
788
+ case "provisioning": return "queued";
789
+ case "running": return "running";
790
+ case "completed": return "completed";
791
+ case "cancelled": return "cancelled";
792
+ case "stopped":
793
+ case "failed":
794
+ case "expired":
795
+ case "unknown": return "failed";
796
+ }
797
+ }
798
+ function promptResultFromAgentTurnResult(result) {
799
+ return {
800
+ response: result.text,
801
+ success: result.success,
802
+ status: result.success ? "success" : "failed",
803
+ durationMs: 0,
804
+ ...result.error ? { error: result.error } : {},
805
+ ...result.usage ? {
806
+ usage: {
807
+ inputTokens: result.usage.inputTokens,
808
+ outputTokens: result.usage.outputTokens
809
+ },
810
+ ...result.usage.cost === void 0 ? {} : { costUsd: result.usage.cost }
811
+ } : {}
812
+ };
813
+ }
814
+ function environmentEventFromSandboxEvent(event) {
815
+ const data = event.data && typeof event.data === "object" ? event.data : {};
816
+ return {
817
+ type: String(event.type),
818
+ data,
819
+ ...event.id ? { id: event.id } : {},
820
+ usage: tokenUsageFromData(data),
821
+ providerEvent: event
822
+ };
823
+ }
824
+ function sandboxEventFromEnvironmentEvent(event) {
825
+ return {
826
+ type: event.type,
827
+ data: {
828
+ ...event.data,
829
+ ...event.usage ? { usage: tokenUsageData(event.usage) } : {}
830
+ },
831
+ ...event.id ? { id: event.id } : {}
832
+ };
833
+ }
834
+ function usageSandboxEvent(event) {
835
+ if (!event.usage || isUsageType(event.type)) return void 0;
836
+ const usage = tokenUsageData(event.usage);
837
+ if (usage.inputTokens === void 0 && usage.outputTokens === void 0 && usage.totalCostUsd === void 0) return;
838
+ return {
839
+ type: "llm_call",
840
+ data: usage
841
+ };
842
+ }
843
+ function tokenUsageData(usage) {
844
+ return {
845
+ inputTokens: usage.inputTokens,
846
+ outputTokens: usage.outputTokens,
847
+ totalCostUsd: usage.cost
848
+ };
849
+ }
850
+ function turnInputFromPrompt(message, options) {
851
+ return {
852
+ ...typeof message === "string" ? { prompt: message } : { parts: message },
853
+ ...options?.sessionId ? { sessionId: options.sessionId } : {},
854
+ ...options?.model ? { model: options.model } : {},
855
+ ...options?.timeoutMs ? { timeoutMs: options.timeoutMs } : {},
856
+ ...options?.executionId ? { executionId: options.executionId } : {},
857
+ ...options?.lastEventId ? { lastEventId: options.lastEventId } : {},
858
+ ...options?.turnId ? { turnId: options.turnId } : {},
859
+ ...options?.detach !== void 0 ? { detach: options.detach } : {},
860
+ ...options?.context ? { context: options.context } : {},
861
+ ...options?.signal ? { signal: options.signal } : {},
862
+ ...options?.backend ? { providerOptions: { backend: options.backend } } : {}
863
+ };
864
+ }
865
+ function promptFromTurnInput(input) {
866
+ if (input.parts) return input.parts.map(promptPartFromInputPart);
867
+ return input.prompt ?? "";
868
+ }
869
+ function promptPartFromInputPart(part) {
870
+ if (part.type === "text" || part.type === "image") return part;
871
+ if (part.content !== void 0 || part.path !== void 0) throw new ValidationError("Tangle Sandbox file prompt parts require a URL; inline content and local paths are not representable");
872
+ if (!part.filename || !part.url) throw new ValidationError("Tangle Sandbox file prompt parts require both filename and URL");
873
+ return {
874
+ type: "file",
875
+ filename: part.filename,
876
+ ...part.mediaType ? { mediaType: part.mediaType } : {},
877
+ url: part.url
878
+ };
879
+ }
880
+ function promptOptionsFromTurnInput(input) {
881
+ return {
882
+ ...input.sessionId ? { sessionId: input.sessionId } : {},
883
+ ...input.model ? { model: input.model } : {},
884
+ ...input.timeoutMs ? { timeoutMs: input.timeoutMs } : {},
885
+ ...input.context ? { context: input.context } : {},
886
+ ...input.signal ? { signal: input.signal } : {},
887
+ ...input.executionId ? { executionId: input.executionId } : {},
888
+ ...input.lastEventId ? { lastEventId: input.lastEventId } : {},
889
+ ...input.turnId ? { turnId: input.turnId } : {},
890
+ ...input.detach !== void 0 ? { detach: input.detach } : {}
891
+ };
892
+ }
893
+ function taskToTurnInput(task, signal) {
894
+ return {
895
+ prompt: taskToPrompt(task),
896
+ signal
897
+ };
898
+ }
899
+ function taskToPrompt(task) {
900
+ if (typeof task === "string") return task;
901
+ if (task && typeof task === "object") {
902
+ const record = task;
903
+ for (const key of [
904
+ "prompt",
905
+ "content",
906
+ "task",
907
+ "message"
908
+ ]) if (typeof record[key] === "string") return record[key];
909
+ }
910
+ return JSON.stringify(task);
911
+ }
912
+ function resultFromEvents(events, fallbackText) {
913
+ for (let i = events.length - 1; i >= 0; i -= 1) {
914
+ const event = events[i];
915
+ const text = event ? resultTextFromData(event.data) : void 0;
916
+ if (text !== void 0) return {
917
+ content: text,
918
+ events
919
+ };
920
+ }
921
+ return {
922
+ content: fallbackText,
923
+ events
924
+ };
925
+ }
926
+ function textFromEnvironmentEvent(event) {
927
+ if (typeof event.normalized === "object" && event.normalized && event.normalized.type === "message.part.updated") return typeof event.normalized.delta === "string" ? event.normalized.delta : "";
928
+ const data = event.data;
929
+ for (const key of [
930
+ "delta",
931
+ "chunk",
932
+ "content",
933
+ "text"
934
+ ]) if (typeof data[key] === "string" && !isTerminalEnvironmentEvent(event)) return data[key];
935
+ return "";
936
+ }
937
+ function resultTextFromData(data) {
938
+ for (const key of [
939
+ "finalText",
940
+ "text",
941
+ "response",
942
+ "resultSummary",
943
+ "content"
944
+ ]) if (typeof data[key] === "string") return data[key];
945
+ }
946
+ function isTerminalEnvironmentEvent(event) {
947
+ if (event.type === "result" || event.type === "done" || event.type === "final") return true;
948
+ if (event.type.endsWith(".completed") || event.type.endsWith(".failed")) return true;
949
+ if (event.type === "status") {
950
+ const status = event.data.status;
951
+ return status === "completed" || status === "failed" || status === "cancelled";
952
+ }
953
+ return false;
954
+ }
955
+ function isUsageType(type) {
956
+ return type === "llm_call" || type === "usage" || type === "cost.usage";
957
+ }
958
+ function usageFromEnvironmentEvent(event) {
959
+ const usage = event.usage ?? tokenUsageFromData(event.data);
960
+ return {
961
+ input: finiteNumber(usage?.inputTokens) ?? 0,
962
+ output: finiteNumber(usage?.outputTokens) ?? 0,
963
+ usd: finiteNumber(usage?.cost) ?? finiteNumber(event.data.costUsd) ?? finiteNumber(event.data.totalCostUsd) ?? 0
964
+ };
965
+ }
966
+ function tokenUsageFromData(data) {
967
+ const usageRecord = data.usage && typeof data.usage === "object" ? data.usage : data.tokenUsage && typeof data.tokenUsage === "object" ? data.tokenUsage : data;
968
+ const inputTokens = finiteNumber(usageRecord.inputTokens) ?? finiteNumber(usageRecord.tokensIn) ?? finiteNumber(usageRecord.prompt_tokens);
969
+ const outputTokens = finiteNumber(usageRecord.outputTokens) ?? finiteNumber(usageRecord.tokensOut) ?? finiteNumber(usageRecord.completion_tokens);
970
+ const cost = finiteNumber(usageRecord.cost) ?? finiteNumber(usageRecord.costUsd) ?? finiteNumber(usageRecord.totalCostUsd) ?? finiteNumber(data.costUsd) ?? finiteNumber(data.totalCostUsd);
971
+ if (inputTokens === void 0 && outputTokens === void 0 && cost === void 0) return void 0;
972
+ return {
973
+ inputTokens: inputTokens ?? 0,
974
+ outputTokens: outputTokens ?? 0,
975
+ ...cost !== void 0 ? { cost } : {}
976
+ };
977
+ }
978
+ function mergeTokenUsage(left, right) {
979
+ if (!left) return right;
980
+ if (!right) return left;
981
+ return {
982
+ inputTokens: left.inputTokens + right.inputTokens,
983
+ outputTokens: left.outputTokens + right.outputTokens,
984
+ ...left.cost !== void 0 || right.cost !== void 0 ? { cost: (left.cost ?? 0) + (right.cost ?? 0) } : {}
985
+ };
986
+ }
987
+ function finiteNumber(value) {
988
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
989
+ }
990
+ function agentTurnResultFromPromptResult(result) {
991
+ const record = result;
992
+ return {
993
+ text: typeof record.response === "string" ? record.response : typeof record.text === "string" ? record.text : typeof record.finalText === "string" ? record.finalText : "",
994
+ success: typeof record.success === "boolean" ? record.success : true,
995
+ ...typeof record.error === "string" ? { error: record.error } : {},
996
+ usage: tokenUsageFromData(record)
997
+ };
998
+ }
999
+ function sandboxDispatchResultFromSessionRef(session) {
1000
+ const status = session.metadata && Object.hasOwn(session.metadata, "status") ? sessionStatusFromUnknown(session.metadata?.status) : "running";
1001
+ return {
1002
+ sessionId: session.id,
1003
+ status,
1004
+ alreadyExisted: session.metadata?.alreadyExisted === true
1005
+ };
1006
+ }
1007
+ function sessionRefFromSandboxDispatch(dispatched, providerName) {
1008
+ const record = dispatched && typeof dispatched === "object" ? dispatched : void 0;
1009
+ const id = record?.sessionId ?? record?.id;
1010
+ if (typeof id !== "string" || id.length === 0) throw new ValidationError("sandboxClientAsProvider: dispatch returned no session id");
1011
+ if (!record) throw new ValidationError("sandboxClientAsProvider: dispatch returned no session record");
1012
+ return {
1013
+ id,
1014
+ provider: providerName,
1015
+ metadata: {
1016
+ ...record.status ? { status: record.status } : {},
1017
+ ...record.alreadyExisted !== void 0 ? { alreadyExisted: record.alreadyExisted } : {}
1018
+ }
1019
+ };
1020
+ }
1021
+ function execResultFromSandboxExecResult(result) {
1022
+ const record = result;
1023
+ const exitCode = finiteNumber(record.exitCode) ?? finiteNumber(record.code);
1024
+ if (exitCode === void 0) throw new ValidationError("sandboxClientAsProvider: exec returned no exit code");
1025
+ return {
1026
+ exitCode,
1027
+ stdout: typeof record.stdout === "string" ? record.stdout : "",
1028
+ stderr: typeof record.stderr === "string" ? record.stderr : ""
1029
+ };
1030
+ }
1031
+ function statusFromUnknown(status) {
1032
+ if (status === "pending" || status === "provisioning" || status === "running") return status;
1033
+ if (status === "stopped" || status === "failed" || status === "expired") return status;
1034
+ if (status === "completed") return "stopped";
1035
+ if (status === "cancelled") return "stopped";
1036
+ return "unknown";
1037
+ }
1038
+ function sessionStatusFromUnknown(status) {
1039
+ if (status === "completed" || status === "cancelled") return status;
1040
+ return statusFromUnknown(status);
1041
+ }
1042
+ function readBoxStatus(box) {
1043
+ return box.status;
1044
+ }
1045
+ function readBoxMetadata(box) {
1046
+ const metadata = box.metadata;
1047
+ return metadata && typeof metadata === "object" ? metadata : void 0;
1048
+ }
1049
+ async function maybeRefresh(box) {
1050
+ const refresh = box.refresh;
1051
+ if (typeof refresh === "function") await refresh.call(box);
1052
+ }
1053
+ async function destroyBox(box) {
1054
+ const deleteBox = box.delete;
1055
+ if (typeof deleteBox === "function") await deleteBox.call(box);
1056
+ }
1057
+ function placementInfoFromLoopPlacement(placement, box) {
1058
+ if (!placement) return {
1059
+ kind: "sandbox",
1060
+ sandboxId: String(box.id)
1061
+ };
1062
+ return {
1063
+ kind: placement.kind === "fleet" ? "fleet" : "sandbox",
1064
+ ...placement.sandboxId ? { sandboxId: placement.sandboxId } : { sandboxId: String(box.id) },
1065
+ ...placement.fleetId ? { fleetId: placement.fleetId } : {},
1066
+ ...placement.machineId ? { machineId: placement.machineId } : {}
1067
+ };
1068
+ }
1069
+ function defaultTangleSandboxCapabilities(options) {
1070
+ return {
1071
+ profile: {
1072
+ namedProfiles: options.namedProfiles,
1073
+ systemPrompt: true,
1074
+ instructions: true,
1075
+ tools: true,
1076
+ permissions: true,
1077
+ mcp: true,
1078
+ subagents: true,
1079
+ resources: {
1080
+ files: true,
1081
+ instructions: true,
1082
+ tools: true,
1083
+ skills: true,
1084
+ agents: true,
1085
+ commands: true
1086
+ },
1087
+ hooks: true,
1088
+ modes: true,
1089
+ runtimeUpdate: true,
1090
+ validation: true
1091
+ },
1092
+ streaming: {
1093
+ live: true,
1094
+ replay: true,
1095
+ detach: true,
1096
+ turnIdempotency: true
1097
+ },
1098
+ sessions: {
1099
+ continue: true,
1100
+ list: true,
1101
+ messages: true
1102
+ },
1103
+ workspace: {
1104
+ read: true,
1105
+ write: true,
1106
+ exec: true,
1107
+ git: true,
1108
+ upload: true,
1109
+ download: true
1110
+ },
1111
+ branching: {
1112
+ checkpoint: true,
1113
+ fork: true
1114
+ },
1115
+ placement: true,
1116
+ usage: true,
1117
+ confidential: true
1118
+ };
1119
+ }
1120
+ function mergeAbortSignals(a, b) {
1121
+ const controller = new AbortController();
1122
+ const abort = () => controller.abort();
1123
+ if (a.aborted || b.aborted) controller.abort();
1124
+ else {
1125
+ a.addEventListener("abort", abort, { once: true });
1126
+ b.addEventListener("abort", abort, { once: true });
1127
+ }
1128
+ return controller.signal;
1129
+ }
1130
+ function contentRef(prefix, value) {
1131
+ let str;
1132
+ try {
1133
+ str = JSON.stringify(value) ?? String(value);
1134
+ } catch {
1135
+ str = String(value);
1136
+ }
1137
+ let hash = 2166136261;
1138
+ for (let i = 0; i < str.length; i += 1) {
1139
+ hash ^= str.charCodeAt(i);
1140
+ hash = Math.imul(hash, 16777619);
1141
+ }
1142
+ return `${prefix}:${(hash >>> 0).toString(16).padStart(8, "0")}`;
1143
+ }
1144
+ function hasGet(client) {
1145
+ return typeof client.get === "function";
1146
+ }
1147
+ function hasList(client) {
1148
+ return typeof client.list === "function";
1149
+ }
1150
+ function hasDispatchPrompt(box) {
1151
+ return typeof box.dispatchPrompt === "function";
1152
+ }
1153
+ function hasSession(box) {
1154
+ return typeof box.session === "function";
1155
+ }
1156
+ function hasRead(box) {
1157
+ return typeof box.read === "function";
1158
+ }
1159
+ function hasWrite(box) {
1160
+ return typeof box.write === "function";
1161
+ }
1162
+ function hasExec(box) {
1163
+ return typeof box.exec === "function";
1164
+ }
1165
+ //#endregion
1166
+ export { sandboxClientAsProvider as a, resolveAgentEnvironmentProvider as i, providerAsExecutor as n, createTangleSandboxExactProcessProvider as o, providerAsSandboxClient as r, createAgentEnvironmentProviderRegistry as t };
1167
+
1168
+ //# sourceMappingURL=environment-provider-CfLUmKmf.js.map