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