@tangle-network/sandbox 0.9.7 → 0.10.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.
- package/README.md +28 -0
- package/dist/agent/index.d.ts +2 -2
- package/dist/auth/index.js +66 -25
- package/dist/{client-DWkQOg1k.d.ts → client-BgKAw8YA.d.ts} +22 -2
- package/dist/{client-BZSkXIEp.js → client-DeHvk634.js} +121 -83
- package/dist/collaboration/index.js +1 -1
- package/dist/{collaboration-BxlfZ2Uh.js → collaboration-D17lnOJX.js} +1 -1
- package/dist/core.d.ts +3 -3
- package/dist/core.js +3 -3
- package/dist/{errors-DZsfJUuc.js → errors-DSz87Rkk.js} +10 -1
- package/dist/{errors-1Se5ATyZ.d.ts → errors-H9268M_g.d.ts} +5 -1
- package/dist/{index-DLH5MBrq.d.ts → index-DS4SOkKG.d.ts} +9 -4
- package/dist/index.d.ts +470 -7
- package/dist/index.js +562 -10
- package/dist/intelligence/index.js +1 -1
- package/dist/{sandbox-B6qbvsur.d.ts → sandbox-Bm2C9Phd.d.ts} +843 -164
- package/dist/{sandbox-bDWrUu8i.js → sandbox-CeimsfC8.js} +682 -164
- package/dist/tangle/index.d.ts +1 -1
- package/dist/tangle/index.js +1 -1
- package/dist/{tangle-CMGJEZit.js → tangle-DayyZe-i.js} +115 -37
- package/package.json +3 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { c as
|
|
1
|
+
import { c as SandboxError, d as TimeoutError, f as ValidationError, i as NetworkError, l as ServerError, n as CapabilityError, p as parseErrorResponse, s as QuotaError, t as AuthError, u as StateError } from "./errors-DSz87Rkk.js";
|
|
2
2
|
import { addTokenUsage, readTokenCostUsd, readTokenUsage } from "@tangle-network/agent-core";
|
|
3
3
|
//#region src/backend-config.ts
|
|
4
|
+
const LEGACY_QUESTION_ALIAS_KEY = ["question", "Channel"].join("");
|
|
4
5
|
function parseModelString(model) {
|
|
5
6
|
const parts = model.split("/");
|
|
6
7
|
if (parts.length >= 2) return {
|
|
@@ -17,6 +18,7 @@ function parseModelString(model) {
|
|
|
17
18
|
*/
|
|
18
19
|
function normalizeRuntimeBackendConfig(backend, options = {}) {
|
|
19
20
|
if (!backend && !options.model) return void 0;
|
|
21
|
+
if (backend && LEGACY_QUESTION_ALIAS_KEY in backend) throw new Error(`[sandbox-sdk] backend.${LEGACY_QUESTION_ALIAS_KEY} was removed. Use backend.interactions.question instead.`);
|
|
20
22
|
const portableProfile = backend?.profile && typeof backend.profile !== "string" ? backend.profile : void 0;
|
|
21
23
|
const inlineProfile = portableProfile ? toBackendProfile(portableProfile) : void 0;
|
|
22
24
|
const callerInlineProfile = backend?.inlineProfile;
|
|
@@ -32,7 +34,7 @@ function normalizeRuntimeBackendConfig(backend, options = {}) {
|
|
|
32
34
|
...backend?.model ? { model: backend.model } : options.model ? { model: parseModelString(options.model) } : {},
|
|
33
35
|
...backend?.server ? { server: backend.server } : {},
|
|
34
36
|
...backend?.interactions !== void 0 ? { interactions: backend.interactions } : {},
|
|
35
|
-
...backend?.
|
|
37
|
+
...backend?.metadata !== void 0 ? { metadata: backend.metadata } : {}
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
@@ -99,19 +101,42 @@ function toBackendProfile(profile) {
|
|
|
99
101
|
...timeout !== void 0 ? { timeout } : {}
|
|
100
102
|
}];
|
|
101
103
|
})) : void 0;
|
|
104
|
+
const openCodeExtension = profile.extensions?.opencode;
|
|
105
|
+
const plugins = openCodeExtension?.plugins;
|
|
106
|
+
if (plugins !== void 0 && (!Array.isArray(plugins) || plugins.some((plugin) => typeof plugin !== "string" || !plugin.trim()))) throw new Error("backend.profile.extensions.opencode.plugins must be an array of non-empty package names");
|
|
107
|
+
const commands = openCodeExtension?.commands;
|
|
108
|
+
if (commands !== void 0 && (commands === null || typeof commands !== "object" || Array.isArray(commands))) throw new Error("backend.profile.extensions.opencode.commands must be an object");
|
|
109
|
+
const profileExtends = openCodeExtension?.extends;
|
|
110
|
+
if (profileExtends !== void 0 && typeof profileExtends !== "string" && (!Array.isArray(profileExtends) || profileExtends.some((entry) => typeof entry !== "string" || !entry.trim()))) throw new Error("backend.profile.extensions.opencode.extends must be a profile name or array of profile names");
|
|
111
|
+
const agents = profile.subagents ? Object.fromEntries(Object.entries(profile.subagents).map(([name, subagent]) => [name, {
|
|
112
|
+
description: subagent.description,
|
|
113
|
+
prompt: subagent.prompt,
|
|
114
|
+
model: subagent.model,
|
|
115
|
+
tools: subagent.tools,
|
|
116
|
+
permission: subagent.permissions,
|
|
117
|
+
maxSteps: subagent.maxSteps,
|
|
118
|
+
...subagent.metadata ?? {}
|
|
119
|
+
}])) : void 0;
|
|
102
120
|
return {
|
|
103
121
|
name: profile.name,
|
|
122
|
+
description: profile.description,
|
|
123
|
+
version: profile.version,
|
|
124
|
+
tags: profile.tags,
|
|
125
|
+
...profileExtends ? { extends: profileExtends } : {},
|
|
104
126
|
model: profile.model?.default,
|
|
127
|
+
small_model: profile.model?.small,
|
|
105
128
|
...profile.prompt?.systemPrompt ? { systemPrompt: profile.prompt.systemPrompt } : {},
|
|
106
129
|
...Object.keys(tools).length > 0 ? { tools } : {},
|
|
107
130
|
...profile.prompt?.instructions?.length ? { instructions: profile.prompt.instructions } : {},
|
|
108
131
|
...Object.keys(permission).length > 0 ? { permission } : {},
|
|
109
132
|
...mcp ? { mcp } : {},
|
|
110
133
|
...profile.connections?.length ? { connections: profile.connections } : {},
|
|
111
|
-
...
|
|
134
|
+
...agents ? { agent: agents } : {},
|
|
112
135
|
...profile.resources && hasAnyProfileResource(profile.resources) ? { resources: profile.resources } : {},
|
|
113
136
|
...profile.hooks ? { hooks: profile.hooks } : {},
|
|
114
137
|
...profile.modes ? { modes: profile.modes } : {},
|
|
138
|
+
...commands ? { command: commands } : {},
|
|
139
|
+
...plugins?.length ? { plugin: plugins } : {},
|
|
115
140
|
...profile.extensions ? { extensions: profile.extensions } : {}
|
|
116
141
|
};
|
|
117
142
|
}
|
|
@@ -574,6 +599,244 @@ function collectAgentResponseText(events) {
|
|
|
574
599
|
return responseText && responseText.trim().length > 0 ? responseText : void 0;
|
|
575
600
|
}
|
|
576
601
|
//#endregion
|
|
602
|
+
//#region src/runtime-api.ts
|
|
603
|
+
/** Internal typed client for routes served by a sandbox runtime. */
|
|
604
|
+
var SandboxRuntimeApi = class {
|
|
605
|
+
terminals;
|
|
606
|
+
constructor(transport) {
|
|
607
|
+
this.transport = transport;
|
|
608
|
+
this.terminals = {
|
|
609
|
+
create: (options, request) => this.createTerminal(options, request),
|
|
610
|
+
input: (terminalId, data, request) => this.writeTerminal(terminalId, data, request),
|
|
611
|
+
list: () => this.listTerminals(),
|
|
612
|
+
get: (terminalId) => this.getTerminal(terminalId)
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
async health() {
|
|
616
|
+
await this.transport.ensureRunning();
|
|
617
|
+
return this.json("/health", { method: "GET" });
|
|
618
|
+
}
|
|
619
|
+
async ports() {
|
|
620
|
+
await this.transport.ensureRunning();
|
|
621
|
+
return (await this.json("/ports", { method: "GET" })).data?.ports ?? [];
|
|
622
|
+
}
|
|
623
|
+
async profiles() {
|
|
624
|
+
await this.transport.ensureRunning();
|
|
625
|
+
return this.json("/profiles", { method: "GET" });
|
|
626
|
+
}
|
|
627
|
+
async readFiles(paths, options = {}) {
|
|
628
|
+
if (paths.length === 0) return {
|
|
629
|
+
files: [],
|
|
630
|
+
errors: [],
|
|
631
|
+
stats: {
|
|
632
|
+
requested: 0,
|
|
633
|
+
succeeded: 0,
|
|
634
|
+
failed: 0
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
await this.transport.ensureRunning();
|
|
638
|
+
const files = [];
|
|
639
|
+
const errors = [];
|
|
640
|
+
let requested = 0;
|
|
641
|
+
let succeeded = 0;
|
|
642
|
+
let failed = 0;
|
|
643
|
+
for (let offset = 0; offset < paths.length; offset += 100) {
|
|
644
|
+
const chunk = paths.slice(offset, offset + 100);
|
|
645
|
+
const params = new URLSearchParams();
|
|
646
|
+
if (options.sessionId) params.set("sessionId", options.sessionId);
|
|
647
|
+
const query = params.toString();
|
|
648
|
+
const payload = await this.json(`/files/read-batch${query ? `?${query}` : ""}`, {
|
|
649
|
+
method: "POST",
|
|
650
|
+
body: JSON.stringify({
|
|
651
|
+
paths: chunk,
|
|
652
|
+
...options.encoding ? { encoding: options.encoding } : {}
|
|
653
|
+
})
|
|
654
|
+
});
|
|
655
|
+
for (const [path, result] of Object.entries(payload.data.files)) if (result.success) files.push({
|
|
656
|
+
path,
|
|
657
|
+
content: result.content,
|
|
658
|
+
encoding: result.encoding,
|
|
659
|
+
hash: result.hash,
|
|
660
|
+
size: result.size,
|
|
661
|
+
mtime: result.mtime
|
|
662
|
+
});
|
|
663
|
+
else errors.push({
|
|
664
|
+
path,
|
|
665
|
+
error: result.error,
|
|
666
|
+
code: result.code
|
|
667
|
+
});
|
|
668
|
+
const results = Object.values(payload.data.files);
|
|
669
|
+
requested += payload.data.stats?.requested ?? chunk.length;
|
|
670
|
+
succeeded += payload.data.stats?.succeeded ?? results.filter((entry) => entry.success).length;
|
|
671
|
+
failed += payload.data.stats?.failed ?? results.filter((entry) => !entry.success).length;
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
files,
|
|
675
|
+
errors,
|
|
676
|
+
stats: {
|
|
677
|
+
requested,
|
|
678
|
+
succeeded,
|
|
679
|
+
failed
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
async fileTree(path, options = {}) {
|
|
684
|
+
if (options.maxDepth !== void 0 && (!Number.isInteger(options.maxDepth) || options.maxDepth < 1 || options.maxDepth > 20)) throw new ValidationError("maxDepth must be an integer between 1 and 20");
|
|
685
|
+
await this.transport.ensureRunning();
|
|
686
|
+
const params = new URLSearchParams({ path });
|
|
687
|
+
if (options.maxDepth !== void 0) params.set("maxDepth", String(options.maxDepth));
|
|
688
|
+
if (options.sessionId) params.set("sessionId", options.sessionId);
|
|
689
|
+
return (await this.json(`/files/tree?${params}`, { method: "GET" })).data;
|
|
690
|
+
}
|
|
691
|
+
async createSession(options) {
|
|
692
|
+
await this.transport.ensureRunning();
|
|
693
|
+
const info = normalizeSessionInfo(await this.json("/agents/sessions", {
|
|
694
|
+
method: "POST",
|
|
695
|
+
body: JSON.stringify({
|
|
696
|
+
...options.title !== void 0 ? { title: options.title } : {},
|
|
697
|
+
...options.parentId !== void 0 ? { parentID: options.parentId } : {},
|
|
698
|
+
backend: normalizeRuntimeBackendConfig(options.backend)
|
|
699
|
+
})
|
|
700
|
+
}));
|
|
701
|
+
if (!info) throw new ServerError("Session creation response missing session id", 502, {
|
|
702
|
+
endpoint: "/agents/sessions",
|
|
703
|
+
origin: "runtime"
|
|
704
|
+
});
|
|
705
|
+
return info;
|
|
706
|
+
}
|
|
707
|
+
async createTaskSession(options) {
|
|
708
|
+
await this.transport.ensureRunning();
|
|
709
|
+
const info = await this.json("/tasks", {
|
|
710
|
+
method: "POST",
|
|
711
|
+
body: JSON.stringify({
|
|
712
|
+
sessionId: options.sessionId,
|
|
713
|
+
backend: normalizeRuntimeBackendConfig(options.backend),
|
|
714
|
+
title: options.title,
|
|
715
|
+
...options.parentSessionId !== void 0 ? { parentSessionId: options.parentSessionId } : {},
|
|
716
|
+
...options.profile !== void 0 ? { profile: options.profile } : {},
|
|
717
|
+
...options.isolateFileWrites !== void 0 ? { isolateFileWrites: options.isolateFileWrites } : {}
|
|
718
|
+
})
|
|
719
|
+
});
|
|
720
|
+
if (!info.id) throw new ServerError("Task session creation response missing session id", 502, {
|
|
721
|
+
endpoint: "/tasks",
|
|
722
|
+
origin: "runtime"
|
|
723
|
+
});
|
|
724
|
+
return info;
|
|
725
|
+
}
|
|
726
|
+
async sendSessionMessage(id, request, options = {}) {
|
|
727
|
+
if (options.timeoutMs !== void 0 && options.timeoutMs <= 0) throw new ValidationError("timeoutMs must be greater than zero");
|
|
728
|
+
await this.transport.ensureRunning();
|
|
729
|
+
const headers = new Headers({ "x-no-retry": "true" });
|
|
730
|
+
if (options.credentials?.apiKey) headers.set("X-Backend-Api-Key", options.credentials.apiKey);
|
|
731
|
+
if (options.credentials?.baseUrl) headers.set("X-Backend-Base-Url", options.credentials.baseUrl);
|
|
732
|
+
const timeoutSignal = options.timeoutMs !== void 0 ? AbortSignal.timeout(options.timeoutMs) : void 0;
|
|
733
|
+
const signal = options.signal && timeoutSignal ? AbortSignal.any([options.signal, timeoutSignal]) : options.signal ?? timeoutSignal;
|
|
734
|
+
return this.json(`/agents/sessions/${encodeURIComponent(id)}/messages`, {
|
|
735
|
+
method: "POST",
|
|
736
|
+
headers,
|
|
737
|
+
signal,
|
|
738
|
+
body: JSON.stringify({
|
|
739
|
+
...request.messageId !== void 0 ? { messageID: request.messageId } : {},
|
|
740
|
+
parts: request.parts,
|
|
741
|
+
...request.system !== void 0 ? { system: request.system } : {},
|
|
742
|
+
...request.agent !== void 0 ? { agent: request.agent } : {},
|
|
743
|
+
...request.model !== void 0 ? { model: {
|
|
744
|
+
providerID: request.model.providerId,
|
|
745
|
+
modelID: request.model.modelId
|
|
746
|
+
} } : {},
|
|
747
|
+
...request.reasoningEffort !== void 0 ? { reasoningEffort: request.reasoningEffort } : {},
|
|
748
|
+
...request.turnId !== void 0 ? { turnId: request.turnId } : {},
|
|
749
|
+
...request.interactions !== void 0 ? { interactions: request.interactions } : {}
|
|
750
|
+
})
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
async deleteSession(id) {
|
|
754
|
+
await this.transport.ensureRunning();
|
|
755
|
+
await this.request(`/agents/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
756
|
+
}
|
|
757
|
+
async taskSessionChanges(id) {
|
|
758
|
+
await this.transport.ensureRunning();
|
|
759
|
+
return this.json(`/tasks/${encodeURIComponent(id)}/changes`, { method: "GET" });
|
|
760
|
+
}
|
|
761
|
+
async commitTaskSession(id, options = {}) {
|
|
762
|
+
await this.transport.ensureRunning();
|
|
763
|
+
return this.json(`/tasks/${encodeURIComponent(id)}/changes`, {
|
|
764
|
+
method: "POST",
|
|
765
|
+
body: JSON.stringify({
|
|
766
|
+
...options.message !== void 0 ? { message: options.message } : {},
|
|
767
|
+
...options.files !== void 0 ? { files: options.files } : {}
|
|
768
|
+
})
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
async createTerminal(options = {}, request = {}) {
|
|
772
|
+
await this.transport.ensureRunning();
|
|
773
|
+
const params = new URLSearchParams();
|
|
774
|
+
if (request.sessionId) params.set("sessionId", request.sessionId);
|
|
775
|
+
const query = params.toString();
|
|
776
|
+
return (await this.json(`/terminals${query ? `?${query}` : ""}`, {
|
|
777
|
+
method: "POST",
|
|
778
|
+
body: JSON.stringify(options)
|
|
779
|
+
})).data;
|
|
780
|
+
}
|
|
781
|
+
async writeTerminal(terminalId, data, request = {}) {
|
|
782
|
+
await this.transport.ensureRunning();
|
|
783
|
+
const params = new URLSearchParams();
|
|
784
|
+
if (request.sessionId) params.set("sessionId", request.sessionId);
|
|
785
|
+
const query = params.toString();
|
|
786
|
+
await this.request(`/terminals/${encodeURIComponent(terminalId)}/input${query ? `?${query}` : ""}`, {
|
|
787
|
+
method: "POST",
|
|
788
|
+
body: JSON.stringify({ data })
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
async listTerminals() {
|
|
792
|
+
await this.transport.ensureRunning();
|
|
793
|
+
return (await this.json("/terminals", { method: "GET" })).data ?? [];
|
|
794
|
+
}
|
|
795
|
+
async getTerminal(terminalId) {
|
|
796
|
+
await this.transport.ensureRunning();
|
|
797
|
+
const response = await this.transport.fetch(`/terminals/${encodeURIComponent(terminalId)}`, { method: "GET" });
|
|
798
|
+
if (response.status === 404) return null;
|
|
799
|
+
await this.assertOk(response);
|
|
800
|
+
return (await response.json()).data;
|
|
801
|
+
}
|
|
802
|
+
async json(path, init) {
|
|
803
|
+
return await (await this.request(path, init)).json();
|
|
804
|
+
}
|
|
805
|
+
async request(path, init) {
|
|
806
|
+
const response = await this.transport.fetch(path, init);
|
|
807
|
+
await this.assertOk(response);
|
|
808
|
+
return response;
|
|
809
|
+
}
|
|
810
|
+
async assertOk(response) {
|
|
811
|
+
if (response.ok) return;
|
|
812
|
+
const body = await response.text();
|
|
813
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
function normalizeSessionInfo(raw) {
|
|
817
|
+
const id = raw.id;
|
|
818
|
+
if (typeof id !== "string") return null;
|
|
819
|
+
const status = raw.status || "running";
|
|
820
|
+
return {
|
|
821
|
+
id,
|
|
822
|
+
parentId: typeof raw.parentID === "string" ? raw.parentID : typeof raw.parentId === "string" ? raw.parentId : void 0,
|
|
823
|
+
status: [
|
|
824
|
+
"queued",
|
|
825
|
+
"running",
|
|
826
|
+
"completed",
|
|
827
|
+
"failed",
|
|
828
|
+
"cancelled"
|
|
829
|
+
].includes(status) ? status : "running",
|
|
830
|
+
backend: typeof raw.backendType === "string" ? raw.backendType : typeof raw.backend === "string" ? raw.backend : void 0,
|
|
831
|
+
model: typeof raw.model === "string" ? raw.model : void 0,
|
|
832
|
+
promptCount: typeof raw.promptCount === "number" ? raw.promptCount : void 0,
|
|
833
|
+
createdAt: raw.createdAt ? new Date(raw.createdAt) : void 0,
|
|
834
|
+
startedAt: raw.startedAt ? new Date(raw.startedAt) : void 0,
|
|
835
|
+
endedAt: raw.endedAt ? new Date(raw.endedAt) : void 0,
|
|
836
|
+
raw
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
//#endregion
|
|
577
840
|
//#region src/interactive.ts
|
|
578
841
|
/**
|
|
579
842
|
* Handle for one session's interactive harness. Obtained via
|
|
@@ -631,7 +894,7 @@ var InteractiveSessionHandle = class {
|
|
|
631
894
|
* A single agent session inside a sandbox. Created via
|
|
632
895
|
* `box.session(id)` — does not hit the network until a method is called.
|
|
633
896
|
*/
|
|
634
|
-
var SandboxSession = class {
|
|
897
|
+
var SandboxSession = class SandboxSession {
|
|
635
898
|
/**
|
|
636
899
|
* @internal SDK-internal constructor — apps should call `box.session(id)`.
|
|
637
900
|
*/
|
|
@@ -674,6 +937,16 @@ var SandboxSession = class {
|
|
|
674
937
|
return this.box._sessionResult(this.id);
|
|
675
938
|
}
|
|
676
939
|
/**
|
|
940
|
+
* List persisted messages for this session, including in-flight assistant
|
|
941
|
+
* content when the runtime has flushed partial output.
|
|
942
|
+
*/
|
|
943
|
+
async messages(opts = {}) {
|
|
944
|
+
return this.box.messages({
|
|
945
|
+
...opts,
|
|
946
|
+
sessionId: this.id
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
677
950
|
* Continue this session with an additional prompt. Equivalent to
|
|
678
951
|
* `box.prompt(message, { ...opts, sessionId: this.id })` but reads
|
|
679
952
|
* naturally on a Session reference.
|
|
@@ -685,6 +958,13 @@ var SandboxSession = class {
|
|
|
685
958
|
});
|
|
686
959
|
}
|
|
687
960
|
/**
|
|
961
|
+
* Send a structured message through the session message endpoint. Model and
|
|
962
|
+
* message identifiers are translated to the runtime's wire names by the SDK.
|
|
963
|
+
*/
|
|
964
|
+
async sendMessage(request, options) {
|
|
965
|
+
return this.box._sessionSendMessage(this.id, request, options);
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
688
968
|
* Abort the session's in-flight execution; the session and its messages
|
|
689
969
|
* are preserved (this does not delete the session). Void-returning alias
|
|
690
970
|
* of `interrupt()` — use `interrupt()` when you need to know whether an
|
|
@@ -695,6 +975,22 @@ var SandboxSession = class {
|
|
|
695
975
|
async cancel() {
|
|
696
976
|
return this.box._sessionCancel(this.id);
|
|
697
977
|
}
|
|
978
|
+
/** Delete this session and its persisted runtime state. */
|
|
979
|
+
async delete() {
|
|
980
|
+
return this.box._sessionDelete(this.id);
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Fork this session into a new queued session. The fork shares the
|
|
984
|
+
* parent workspace and copies conversation history up to `messageId`
|
|
985
|
+
* when supplied.
|
|
986
|
+
*/
|
|
987
|
+
async fork(opts) {
|
|
988
|
+
const info = await this.box._sessionFork(this.id, opts);
|
|
989
|
+
return {
|
|
990
|
+
session: new SandboxSession(this.box, info.id),
|
|
991
|
+
info
|
|
992
|
+
};
|
|
993
|
+
}
|
|
698
994
|
/**
|
|
699
995
|
* Drive this session's harness in INTERACTIVE mode: spawn its native TUI,
|
|
700
996
|
* stream the live framebuffer, and inject prompts as keystrokes. Distinct
|
|
@@ -732,6 +1028,24 @@ var SandboxSession = class {
|
|
|
732
1028
|
}
|
|
733
1029
|
};
|
|
734
1030
|
//#endregion
|
|
1031
|
+
//#region src/task-session.ts
|
|
1032
|
+
/** A background task session with isolated changeset operations. */
|
|
1033
|
+
var SandboxTaskSession = class extends SandboxSession {
|
|
1034
|
+
/** @internal Apps should call `box.taskSession(id)`. */
|
|
1035
|
+
constructor(taskBox, id) {
|
|
1036
|
+
super(taskBox, id);
|
|
1037
|
+
this.taskBox = taskBox;
|
|
1038
|
+
}
|
|
1039
|
+
/** Read the task's isolated file changes. */
|
|
1040
|
+
async changes() {
|
|
1041
|
+
return this.taskBox._taskSessionChanges(this.id);
|
|
1042
|
+
}
|
|
1043
|
+
/** Apply all or a selected subset of the task's isolated file changes. */
|
|
1044
|
+
async commit(options) {
|
|
1045
|
+
return this.taskBox._taskSessionCommit(this.id, options);
|
|
1046
|
+
}
|
|
1047
|
+
};
|
|
1048
|
+
//#endregion
|
|
735
1049
|
//#region src/sandbox.ts
|
|
736
1050
|
/**
|
|
737
1051
|
* Sandbox Instance
|
|
@@ -1004,10 +1318,15 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1004
1318
|
client;
|
|
1005
1319
|
info;
|
|
1006
1320
|
defaultRuntimeBackend;
|
|
1321
|
+
runtime;
|
|
1007
1322
|
constructor(client, info, defaultRuntimeBackend) {
|
|
1008
1323
|
this.client = client;
|
|
1009
1324
|
this.info = info;
|
|
1010
1325
|
this.defaultRuntimeBackend = defaultRuntimeBackend;
|
|
1326
|
+
this.runtime = new SandboxRuntimeApi({
|
|
1327
|
+
ensureRunning: () => this.ensureRunning(),
|
|
1328
|
+
fetch: (path, init) => this.runtimeFetch(path, init)
|
|
1329
|
+
});
|
|
1011
1330
|
}
|
|
1012
1331
|
/** Unique sandbox identifier */
|
|
1013
1332
|
get id() {
|
|
@@ -1049,6 +1368,10 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1049
1368
|
get error() {
|
|
1050
1369
|
return this.info.error;
|
|
1051
1370
|
}
|
|
1371
|
+
/** GPU lease attached during sandbox creation, when requested. */
|
|
1372
|
+
get gpuLease() {
|
|
1373
|
+
return this.info.gpuLease;
|
|
1374
|
+
}
|
|
1052
1375
|
/** Web terminal URL for browser-based access */
|
|
1053
1376
|
get url() {
|
|
1054
1377
|
return this.info.connection?.webTerminalUrl;
|
|
@@ -1089,7 +1412,8 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1089
1412
|
startedAt: this.startedAt,
|
|
1090
1413
|
lastActivityAt: this.lastActivityAt,
|
|
1091
1414
|
expiresAt: this.expiresAt,
|
|
1092
|
-
error: this.error
|
|
1415
|
+
error: this.error,
|
|
1416
|
+
gpuLease: this.gpuLease
|
|
1093
1417
|
};
|
|
1094
1418
|
}
|
|
1095
1419
|
/**
|
|
@@ -1419,11 +1743,15 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1419
1743
|
*/
|
|
1420
1744
|
async write(path, content, options) {
|
|
1421
1745
|
await this.ensureRunning();
|
|
1422
|
-
const
|
|
1746
|
+
const params = new URLSearchParams();
|
|
1747
|
+
if (options?.sessionId) params.set("sessionId", options.sessionId);
|
|
1748
|
+
const query = params.toString();
|
|
1749
|
+
const response = await this.runtimeFetch(`/files/write${query ? `?${query}` : ""}`, {
|
|
1423
1750
|
method: "POST",
|
|
1424
1751
|
body: JSON.stringify({
|
|
1425
1752
|
path,
|
|
1426
1753
|
content,
|
|
1754
|
+
encoding: options?.encoding,
|
|
1427
1755
|
mode: options?.mode
|
|
1428
1756
|
})
|
|
1429
1757
|
});
|
|
@@ -1431,6 +1759,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1431
1759
|
const body = await response.text();
|
|
1432
1760
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
1433
1761
|
}
|
|
1762
|
+
return (await response.json()).data;
|
|
1434
1763
|
}
|
|
1435
1764
|
/**
|
|
1436
1765
|
* Write many files in one paced, retry-aware batch — see
|
|
@@ -1531,6 +1860,13 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1531
1860
|
controller.abort();
|
|
1532
1861
|
}
|
|
1533
1862
|
}
|
|
1863
|
+
logStreamCheckpoint(checkpoint, data = {}) {
|
|
1864
|
+
if (globalThis.process?.env?.TANGLE_SANDBOX_SDK_STREAM_DEBUG !== "1") return;
|
|
1865
|
+
console.debug("[sandbox-sdk] stream checkpoint", {
|
|
1866
|
+
checkpoint,
|
|
1867
|
+
...data
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1534
1870
|
/**
|
|
1535
1871
|
* Stream events from an agent prompt.
|
|
1536
1872
|
* Use this for real-time updates during agent execution.
|
|
@@ -1562,16 +1898,27 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1562
1898
|
}
|
|
1563
1899
|
} catch (err) {
|
|
1564
1900
|
if (isCallerAbort()) return;
|
|
1901
|
+
this.logStreamCheckpoint("synthetic_error", {
|
|
1902
|
+
sessionId,
|
|
1903
|
+
executionId,
|
|
1904
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1905
|
+
});
|
|
1565
1906
|
yield toStreamErrorEvent(err);
|
|
1566
1907
|
} finally {
|
|
1567
|
-
if (!receivedTerminal && !isCallerAbort())
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1908
|
+
if (!receivedTerminal && !isCallerAbort()) {
|
|
1909
|
+
this.logStreamCheckpoint("synthetic_terminal", {
|
|
1910
|
+
sessionId,
|
|
1911
|
+
executionId
|
|
1912
|
+
});
|
|
1913
|
+
yield {
|
|
1914
|
+
type: "done",
|
|
1915
|
+
data: {
|
|
1916
|
+
status: "failed",
|
|
1917
|
+
...sessionId ? { sessionId } : {},
|
|
1918
|
+
...executionId ? { executionId } : {}
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1575
1922
|
}
|
|
1576
1923
|
}
|
|
1577
1924
|
/**
|
|
@@ -1593,8 +1940,22 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1593
1940
|
origin: "runtime"
|
|
1594
1941
|
});
|
|
1595
1942
|
};
|
|
1943
|
+
const streamStartedAt = Date.now();
|
|
1944
|
+
const logStreamCheckpoint = (checkpoint, data = {}) => {
|
|
1945
|
+
this.logStreamCheckpoint(checkpoint, {
|
|
1946
|
+
elapsedMs: Date.now() - streamStartedAt,
|
|
1947
|
+
...data
|
|
1948
|
+
});
|
|
1949
|
+
};
|
|
1596
1950
|
let response;
|
|
1597
1951
|
try {
|
|
1952
|
+
logStreamCheckpoint("runtime_post_start", {
|
|
1953
|
+
endpoint: "/agents/run/stream",
|
|
1954
|
+
sessionId: options?.sessionId,
|
|
1955
|
+
executionId: options?.executionId,
|
|
1956
|
+
hasLastEventId: Boolean(options?.lastEventId),
|
|
1957
|
+
detach: options?.detach === true
|
|
1958
|
+
});
|
|
1598
1959
|
response = await this.runtimeFetch("/agents/run/stream", {
|
|
1599
1960
|
method: "POST",
|
|
1600
1961
|
signal: streamSignal,
|
|
@@ -1610,11 +1971,17 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1610
1971
|
turnId: options?.turnId,
|
|
1611
1972
|
metadata: options?.context,
|
|
1612
1973
|
requireVisibleAssistantOutput: options?.requireVisibleAssistantOutput,
|
|
1974
|
+
...timeoutMs ? { timeoutMs } : {},
|
|
1613
1975
|
...options?.detach ? { detach: true } : {},
|
|
1614
1976
|
backend: normalizeRuntimeBackendConfig(options?.backend ?? this.defaultRuntimeBackend, { model: options?.model })
|
|
1615
1977
|
})
|
|
1616
1978
|
});
|
|
1979
|
+
logStreamCheckpoint("runtime_response_headers", {
|
|
1980
|
+
status: response.status,
|
|
1981
|
+
ok: response.ok
|
|
1982
|
+
});
|
|
1617
1983
|
} catch (err) {
|
|
1984
|
+
logStreamCheckpoint("runtime_post_failed", { error: err instanceof Error ? err.message : String(err) });
|
|
1618
1985
|
throwIfTimedOut();
|
|
1619
1986
|
throw err;
|
|
1620
1987
|
}
|
|
@@ -1637,17 +2004,39 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1637
2004
|
const MAX_RECONNECT_ATTEMPTS = RECONNECT_BACKOFF_MS.length;
|
|
1638
2005
|
let lastReplayStatus;
|
|
1639
2006
|
let lastExecutionStatus;
|
|
2007
|
+
let firstSseEventSeen = false;
|
|
1640
2008
|
for await (const event of this.parseSSEStream(response, streamSignal)) {
|
|
2009
|
+
if (!firstSseEventSeen) {
|
|
2010
|
+
firstSseEventSeen = true;
|
|
2011
|
+
logStreamCheckpoint("first_sse_event", {
|
|
2012
|
+
eventType: event.type,
|
|
2013
|
+
eventId: event.id
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
1641
2016
|
if (event.id) lastEventId = event.id;
|
|
1642
2017
|
if (event.type === "execution.started" && event.data?.executionId) executionId = event.data.executionId;
|
|
1643
2018
|
const eventSessionId = event.data?.sessionId;
|
|
1644
2019
|
if (typeof eventSessionId === "string" && eventSessionId.length > 0) sessionId = eventSessionId;
|
|
1645
|
-
if (event.type === "result" || event.type === "done")
|
|
2020
|
+
if (event.type === "result" || event.type === "done") {
|
|
2021
|
+
receivedTerminal = true;
|
|
2022
|
+
logStreamCheckpoint("terminal_event", {
|
|
2023
|
+
eventType: event.type,
|
|
2024
|
+
eventId: event.id,
|
|
2025
|
+
sessionId,
|
|
2026
|
+
executionId
|
|
2027
|
+
});
|
|
2028
|
+
}
|
|
1646
2029
|
yield event;
|
|
1647
2030
|
}
|
|
1648
2031
|
if (receivedTerminal) return;
|
|
1649
2032
|
throwIfTimedOut();
|
|
1650
2033
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
2034
|
+
logStreamCheckpoint("stream_drop", {
|
|
2035
|
+
executionId,
|
|
2036
|
+
sessionId,
|
|
2037
|
+
lastEventId,
|
|
2038
|
+
receivedTerminal
|
|
2039
|
+
});
|
|
1651
2040
|
if (!executionId) throw new NetworkError("Prompt stream dropped before execution.started; cannot reconnect", {
|
|
1652
2041
|
endpoint: "/agents/run/stream",
|
|
1653
2042
|
origin: "runtime"
|
|
@@ -1656,6 +2045,12 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1656
2045
|
throwIfTimedOut();
|
|
1657
2046
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
1658
2047
|
console.warn(`[sandbox-sdk] Stream dropped without terminal event, reconnecting (attempt ${attempt}/${MAX_RECONNECT_ATTEMPTS})`);
|
|
2048
|
+
logStreamCheckpoint("reconnect_attempt_start", {
|
|
2049
|
+
attempt,
|
|
2050
|
+
executionId,
|
|
2051
|
+
sessionId,
|
|
2052
|
+
lastEventId
|
|
2053
|
+
});
|
|
1659
2054
|
await new Promise((resolve) => setTimeout(resolve, RECONNECT_BACKOFF_MS[attempt - 1]));
|
|
1660
2055
|
throwIfTimedOut();
|
|
1661
2056
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
@@ -1665,6 +2060,11 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1665
2060
|
method: "GET",
|
|
1666
2061
|
signal: streamSignal
|
|
1667
2062
|
});
|
|
2063
|
+
logStreamCheckpoint("replay_response_status", {
|
|
2064
|
+
attempt,
|
|
2065
|
+
status: replayResponse.status,
|
|
2066
|
+
ok: replayResponse.ok
|
|
2067
|
+
});
|
|
1668
2068
|
if (!replayResponse.ok) {
|
|
1669
2069
|
lastReplayStatus = replayResponse.status;
|
|
1670
2070
|
console.warn(`[sandbox-sdk] Replay endpoint returned ${replayResponse.status}, attempt ${attempt}`);
|
|
@@ -1674,6 +2074,13 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1674
2074
|
lastExecutionStatus = info.status;
|
|
1675
2075
|
if (info.status === "completed" || info.status === "failed" || info.status === "cancelled") {
|
|
1676
2076
|
console.warn(`[sandbox-sdk] Replay 404 but session ${sessionId} is terminal (${info.status}); ending stream gracefully`);
|
|
2077
|
+
logStreamCheckpoint("terminal_event", {
|
|
2078
|
+
eventType: "done",
|
|
2079
|
+
synthetic: true,
|
|
2080
|
+
reason: "replay_unavailable_terminal_session",
|
|
2081
|
+
sessionId,
|
|
2082
|
+
executionId
|
|
2083
|
+
});
|
|
1677
2084
|
yield {
|
|
1678
2085
|
type: "done",
|
|
1679
2086
|
data: {
|
|
@@ -1692,18 +2099,46 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1692
2099
|
continue;
|
|
1693
2100
|
}
|
|
1694
2101
|
for await (const event of this.parseSSEStream(replayResponse, streamSignal)) {
|
|
2102
|
+
if (!firstSseEventSeen) {
|
|
2103
|
+
firstSseEventSeen = true;
|
|
2104
|
+
logStreamCheckpoint("first_sse_event", {
|
|
2105
|
+
eventType: event.type,
|
|
2106
|
+
eventId: event.id,
|
|
2107
|
+
replay: true
|
|
2108
|
+
});
|
|
2109
|
+
}
|
|
1695
2110
|
if (event.type === "history.replay.start" || event.type === "history.replay.end") continue;
|
|
1696
2111
|
if (event.id) lastEventId = event.id;
|
|
1697
2112
|
const eventSessionId = event.data?.sessionId;
|
|
1698
2113
|
if (typeof eventSessionId === "string" && eventSessionId.length > 0) sessionId = eventSessionId;
|
|
1699
|
-
if (event.type === "result" || event.type === "done")
|
|
2114
|
+
if (event.type === "result" || event.type === "done") {
|
|
2115
|
+
receivedTerminal = true;
|
|
2116
|
+
logStreamCheckpoint("terminal_event", {
|
|
2117
|
+
eventType: event.type,
|
|
2118
|
+
eventId: event.id,
|
|
2119
|
+
replay: true,
|
|
2120
|
+
sessionId,
|
|
2121
|
+
executionId
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
1700
2124
|
yield event;
|
|
1701
2125
|
}
|
|
1702
|
-
if (receivedTerminal)
|
|
2126
|
+
if (receivedTerminal) {
|
|
2127
|
+
logStreamCheckpoint("reconnect_attempt_end", {
|
|
2128
|
+
attempt,
|
|
2129
|
+
status: "terminal_received"
|
|
2130
|
+
});
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
1703
2133
|
throwIfTimedOut();
|
|
1704
2134
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
1705
2135
|
} catch (err) {
|
|
1706
2136
|
throwIfTimedOut();
|
|
2137
|
+
logStreamCheckpoint("reconnect_attempt_end", {
|
|
2138
|
+
attempt,
|
|
2139
|
+
status: "failed",
|
|
2140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2141
|
+
});
|
|
1707
2142
|
console.warn(`[sandbox-sdk] Reconnection attempt ${attempt} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1708
2143
|
}
|
|
1709
2144
|
}
|
|
@@ -2015,6 +2450,22 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2015
2450
|
after: match.after
|
|
2016
2451
|
};
|
|
2017
2452
|
}
|
|
2453
|
+
/** Basic health reported by the runtime inside this sandbox. */
|
|
2454
|
+
async runtimeHealth() {
|
|
2455
|
+
return this.runtime.health();
|
|
2456
|
+
}
|
|
2457
|
+
/** Return the runtime's current listening-port snapshot. */
|
|
2458
|
+
async ports() {
|
|
2459
|
+
return this.runtime.ports();
|
|
2460
|
+
}
|
|
2461
|
+
/** Interactive terminal operations for this runtime. */
|
|
2462
|
+
get terminals() {
|
|
2463
|
+
return this.runtime.terminals;
|
|
2464
|
+
}
|
|
2465
|
+
/** List profiles installed in this sandbox runtime. */
|
|
2466
|
+
async listProfiles() {
|
|
2467
|
+
return this.runtime.profiles();
|
|
2468
|
+
}
|
|
2018
2469
|
/**
|
|
2019
2470
|
* Live whole-sandbox resource usage (memory + CPU) from the container cgroup.
|
|
2020
2471
|
*
|
|
@@ -2249,6 +2700,8 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2249
2700
|
return {
|
|
2250
2701
|
supportsWriteMode: true,
|
|
2251
2702
|
read: (path) => this.read(path),
|
|
2703
|
+
readBatch: (paths, options) => this.fsReadBatch(paths, options),
|
|
2704
|
+
tree: (path, options) => this.fsTree(path, options),
|
|
2252
2705
|
write: (path, content, options) => this.write(path, content, options),
|
|
2253
2706
|
writeMany: (files, options) => this.writeMany(files, options),
|
|
2254
2707
|
search: (query, options) => this.search(query, options),
|
|
@@ -2263,6 +2716,12 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2263
2716
|
exists: (path) => this.fsExists(path)
|
|
2264
2717
|
};
|
|
2265
2718
|
}
|
|
2719
|
+
async fsReadBatch(paths, options = {}) {
|
|
2720
|
+
return this.runtime.readFiles(paths, options);
|
|
2721
|
+
}
|
|
2722
|
+
async fsTree(path, options = {}) {
|
|
2723
|
+
return this.runtime.fileTree(path, options);
|
|
2724
|
+
}
|
|
2266
2725
|
async fsUpload(localPath, remotePath, options) {
|
|
2267
2726
|
await this.ensureRunning();
|
|
2268
2727
|
const fs = await import("node:fs/promises");
|
|
@@ -2369,6 +2828,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2369
2828
|
const params = new URLSearchParams();
|
|
2370
2829
|
if (options?.all) params.set("all", "true");
|
|
2371
2830
|
if (options?.long) params.set("long", "true");
|
|
2831
|
+
if (options?.sessionId) params.set("sessionId", options.sessionId);
|
|
2372
2832
|
const query = params.toString();
|
|
2373
2833
|
const url = query ? `/fs/list${path}?${query}` : `/fs/list${path}`;
|
|
2374
2834
|
const response = await this.runtimeFetch(url, { method: "GET" });
|
|
@@ -2414,8 +2874,21 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2414
2874
|
}
|
|
2415
2875
|
async fsDelete(path, options) {
|
|
2416
2876
|
await this.ensureRunning();
|
|
2877
|
+
if (options?.sessionId && !options.recursive) {
|
|
2878
|
+
const params = new URLSearchParams({ sessionId: options.sessionId });
|
|
2879
|
+
const response = await this.runtimeFetch(`/files/delete?${params}`, {
|
|
2880
|
+
method: "POST",
|
|
2881
|
+
body: JSON.stringify({ path })
|
|
2882
|
+
});
|
|
2883
|
+
if (!response.ok) {
|
|
2884
|
+
const body = await response.text();
|
|
2885
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
2886
|
+
}
|
|
2887
|
+
return;
|
|
2888
|
+
}
|
|
2417
2889
|
const params = new URLSearchParams();
|
|
2418
2890
|
if (options?.recursive) params.set("recursive", "true");
|
|
2891
|
+
if (options?.sessionId) params.set("sessionId", options.sessionId);
|
|
2419
2892
|
const query = params.toString();
|
|
2420
2893
|
const url = query ? `/fs${path}?${query}` : `/fs${path}`;
|
|
2421
2894
|
const response = await this.runtimeFetch(url, { method: "DELETE" });
|
|
@@ -3046,6 +3519,20 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3046
3519
|
update: (policy) => this.egressUpdate(policy)
|
|
3047
3520
|
};
|
|
3048
3521
|
}
|
|
3522
|
+
/**
|
|
3523
|
+
* On-demand GPU leases attached to this sandbox.
|
|
3524
|
+
*
|
|
3525
|
+
* The base sandbox stays cheap; `attach` starts a temporary external GPU
|
|
3526
|
+
* worker with an explicit spend cap, and `detach` destroys it.
|
|
3527
|
+
*/
|
|
3528
|
+
get gpu() {
|
|
3529
|
+
return {
|
|
3530
|
+
attach: (options) => this.gpuAttach(options),
|
|
3531
|
+
list: () => this.gpuList(),
|
|
3532
|
+
exec: (leaseId, options) => this.gpuExec(leaseId, options),
|
|
3533
|
+
detach: (leaseId) => this.gpuDetach(leaseId)
|
|
3534
|
+
};
|
|
3535
|
+
}
|
|
3049
3536
|
async networkUpdate(config) {
|
|
3050
3537
|
if (config.blockOutbound !== void 0 && config.allowList !== void 0) {
|
|
3051
3538
|
if (config.blockOutbound && config.allowList.length > 0) throw new Error("blockOutbound and allowList are mutually exclusive");
|
|
@@ -3123,6 +3610,44 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3123
3610
|
source: data.source
|
|
3124
3611
|
};
|
|
3125
3612
|
}
|
|
3613
|
+
async gpuAttach(options) {
|
|
3614
|
+
const response = await this.client.fetch(`/v1/sandboxes/${encodeURIComponent(this.id)}/gpu/leases`, {
|
|
3615
|
+
method: "POST",
|
|
3616
|
+
body: JSON.stringify(options)
|
|
3617
|
+
});
|
|
3618
|
+
if (!response.ok) {
|
|
3619
|
+
const body = await response.text();
|
|
3620
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3621
|
+
}
|
|
3622
|
+
return (await response.json()).lease;
|
|
3623
|
+
}
|
|
3624
|
+
async gpuList() {
|
|
3625
|
+
const response = await this.client.fetch(`/v1/sandboxes/${encodeURIComponent(this.id)}/gpu/leases`);
|
|
3626
|
+
if (!response.ok) {
|
|
3627
|
+
const body = await response.text();
|
|
3628
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3629
|
+
}
|
|
3630
|
+
return (await response.json()).leases ?? [];
|
|
3631
|
+
}
|
|
3632
|
+
async gpuExec(leaseId, options) {
|
|
3633
|
+
const response = await this.client.fetch(`/v1/sandboxes/${encodeURIComponent(this.id)}/gpu/leases/${encodeURIComponent(leaseId)}/exec`, {
|
|
3634
|
+
method: "POST",
|
|
3635
|
+
body: JSON.stringify(options)
|
|
3636
|
+
});
|
|
3637
|
+
if (!response.ok) {
|
|
3638
|
+
const body = await response.text();
|
|
3639
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3640
|
+
}
|
|
3641
|
+
return await response.json();
|
|
3642
|
+
}
|
|
3643
|
+
async gpuDetach(leaseId) {
|
|
3644
|
+
const response = await this.client.fetch(`/v1/sandboxes/${encodeURIComponent(this.id)}/gpu/leases/${encodeURIComponent(leaseId)}`, { method: "DELETE" });
|
|
3645
|
+
if (!response.ok) {
|
|
3646
|
+
const body = await response.text();
|
|
3647
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3648
|
+
}
|
|
3649
|
+
return (await response.json()).lease;
|
|
3650
|
+
}
|
|
3126
3651
|
/**
|
|
3127
3652
|
* Validate CIDR notation (IPv4 and IPv6)
|
|
3128
3653
|
*/
|
|
@@ -3523,132 +4048,60 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3523
4048
|
};
|
|
3524
4049
|
}
|
|
3525
4050
|
/**
|
|
3526
|
-
*
|
|
3527
|
-
*
|
|
3528
|
-
*
|
|
3529
|
-
* enabling true pause/resume and fork operations. Unlike snapshots which
|
|
3530
|
-
* only preserve filesystem state, checkpoints preserve process memory,
|
|
3531
|
-
* open file descriptors, and execution state.
|
|
3532
|
-
*
|
|
3533
|
-
* **Requirements:** CRIU must be available on the host. Check availability
|
|
3534
|
-
* with `client.criuStatus()` before calling.
|
|
3535
|
-
*
|
|
3536
|
-
* **Note:** By default, checkpoint stops the sandbox. Use `leaveRunning: true`
|
|
3537
|
-
* to keep it running (creates a copy-on-write checkpoint).
|
|
3538
|
-
*
|
|
3539
|
-
* @param options - Checkpoint options
|
|
3540
|
-
* @returns Checkpoint result with ID and metadata
|
|
3541
|
-
*
|
|
3542
|
-
* @example Basic checkpoint (stops sandbox)
|
|
3543
|
-
* ```typescript
|
|
3544
|
-
* const checkpoint = await box.checkpoint();
|
|
3545
|
-
* console.log(`Checkpoint: ${checkpoint.checkpointId}`);
|
|
3546
|
-
* // Sandbox is now stopped, resume with box.resume()
|
|
3547
|
-
* ```
|
|
3548
|
-
*
|
|
3549
|
-
* @example Checkpoint without stopping
|
|
3550
|
-
* ```typescript
|
|
3551
|
-
* const checkpoint = await box.checkpoint({
|
|
3552
|
-
* tags: ["before-deploy"],
|
|
3553
|
-
* leaveRunning: true,
|
|
3554
|
-
* });
|
|
3555
|
-
* // Sandbox continues running
|
|
3556
|
-
* ```
|
|
4051
|
+
* @deprecated CRIU checkpoints were removed. To branch live memory into
|
|
4052
|
+
* copy-on-write children of a running sandbox use {@link branch}; for durable
|
|
4053
|
+
* filesystem state use {@link snapshot}. This method now throws.
|
|
3557
4054
|
*/
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
method: "POST",
|
|
3561
|
-
body: JSON.stringify({
|
|
3562
|
-
tags: options?.tags,
|
|
3563
|
-
leaveRunning: options?.leaveRunning,
|
|
3564
|
-
includeSnapshot: options?.includeSnapshot
|
|
3565
|
-
})
|
|
3566
|
-
});
|
|
3567
|
-
if (!response.ok) {
|
|
3568
|
-
const body = await response.text();
|
|
3569
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3570
|
-
}
|
|
3571
|
-
const data = await response.json();
|
|
3572
|
-
return {
|
|
3573
|
-
checkpointId: data.checkpointId ?? data.id,
|
|
3574
|
-
createdAt: new Date(data.createdAt ?? ""),
|
|
3575
|
-
sizeBytes: data.sizeBytes,
|
|
3576
|
-
tags: data.tags ?? []
|
|
3577
|
-
};
|
|
4055
|
+
checkpoint() {
|
|
4056
|
+
throw new CapabilityError("checkpoint() was removed: use branch() to fork live memory into copy-on-write children, or snapshot() for durable disk state", "CHECKPOINT_REMOVED", 410);
|
|
3578
4057
|
}
|
|
3579
4058
|
/**
|
|
3580
|
-
*
|
|
3581
|
-
*
|
|
3582
|
-
* @returns Array of checkpoint metadata
|
|
3583
|
-
*
|
|
3584
|
-
* @example
|
|
3585
|
-
* ```typescript
|
|
3586
|
-
* const checkpoints = await box.listCheckpoints();
|
|
3587
|
-
* for (const cp of checkpoints) {
|
|
3588
|
-
* console.log(`${cp.checkpointId}: ${cp.createdAt}`);
|
|
3589
|
-
* }
|
|
3590
|
-
* ```
|
|
4059
|
+
* @deprecated CRIU checkpoints were removed. List durable filesystem state
|
|
4060
|
+
* with {@link listSnapshots}. This method now throws.
|
|
3591
4061
|
*/
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
if (!response.ok) {
|
|
3595
|
-
const body = await response.text();
|
|
3596
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3597
|
-
}
|
|
3598
|
-
const data = await response.json();
|
|
3599
|
-
return (Array.isArray(data) ? data : data.checkpoints ?? []).map((cp) => this.parseCheckpointInfo(cp));
|
|
4062
|
+
listCheckpoints() {
|
|
4063
|
+
throw new CapabilityError("listCheckpoints() was removed: checkpoints no longer exist; use listSnapshots() for durable disk state", "CHECKPOINT_REMOVED", 410);
|
|
3600
4064
|
}
|
|
3601
4065
|
/**
|
|
3602
|
-
*
|
|
3603
|
-
*
|
|
3604
|
-
* @param checkpointId - ID of the checkpoint to delete
|
|
4066
|
+
* @deprecated CRIU checkpoints were removed. This method now throws.
|
|
3605
4067
|
*/
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
if (!response.ok) {
|
|
3609
|
-
const body = await response.text();
|
|
3610
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3611
|
-
}
|
|
4068
|
+
deleteCheckpoint() {
|
|
4069
|
+
throw new CapabilityError("deleteCheckpoint() was removed: checkpoints no longer exist", "CHECKPOINT_REMOVED", 410);
|
|
3612
4070
|
}
|
|
3613
4071
|
/**
|
|
3614
|
-
*
|
|
3615
|
-
*
|
|
3616
|
-
*
|
|
3617
|
-
*
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
*
|
|
4072
|
+
* @deprecated Forking from a CRIU checkpoint was removed. Use {@link branch}
|
|
4073
|
+
* to fork a running sandbox's live memory into copy-on-write children, or
|
|
4074
|
+
* `client.create({ fromSnapshot })` to provision from durable disk state.
|
|
4075
|
+
* This method now throws.
|
|
4076
|
+
*/
|
|
4077
|
+
fork() {
|
|
4078
|
+
throw new CapabilityError("fork() was removed: use branch() to fork live memory into copy-on-write children, or create({ fromSnapshot }) for durable disk state", "FORK_REMOVED", 410);
|
|
4079
|
+
}
|
|
4080
|
+
/**
|
|
4081
|
+
* Branch this RUNNING sandbox into `count` copy-on-write children
|
|
4082
|
+
* (Morph Infinibranch parity). Unlike {@link fork} — which rehydrates one
|
|
4083
|
+
* sandbox from a CRIU checkpoint — branch forks the live VM's memory into
|
|
4084
|
+
* many children at once via Firecracker UFFD copy-on-write: the children
|
|
4085
|
+
* share the parent's clean pages instead of each copying full guest
|
|
4086
|
+
* memory. The parent stays running.
|
|
3624
4087
|
*
|
|
3625
|
-
* @param
|
|
3626
|
-
* @param options -
|
|
3627
|
-
* @returns
|
|
4088
|
+
* @param count - Number of children to create (must be >= 1).
|
|
4089
|
+
* @param options - Per-child overrides.
|
|
4090
|
+
* @returns Exactly `count` new sandbox instances.
|
|
3628
4091
|
*
|
|
3629
|
-
* @example
|
|
3630
|
-
* ```typescript
|
|
3631
|
-
* const checkpoint = await box.checkpoint({ leaveRunning: true });
|
|
3632
|
-
* const forked = await box.fork(checkpoint.checkpointId);
|
|
3633
|
-
* // forked has same memory state as box at checkpoint time
|
|
3634
|
-
* ```
|
|
3635
|
-
*
|
|
3636
|
-
* @example Fork with custom config
|
|
4092
|
+
* @example
|
|
3637
4093
|
* ```typescript
|
|
3638
|
-
* const
|
|
3639
|
-
*
|
|
3640
|
-
* env: { EXPERIMENT: "true" },
|
|
3641
|
-
* });
|
|
4094
|
+
* const [a, b, c] = await box.branch(3);
|
|
4095
|
+
* // a, b, c each share box's memory state at branch time
|
|
3642
4096
|
* ```
|
|
3643
4097
|
*/
|
|
3644
|
-
async
|
|
3645
|
-
|
|
4098
|
+
async branch(count, options) {
|
|
4099
|
+
if (!Number.isInteger(count) || count < 1) throw new ValidationError(`branch count must be an integer >= 1 (got ${count})`);
|
|
4100
|
+
const response = await this.client.fetch(`/v1/sandboxes/${this.id}/branch`, {
|
|
3646
4101
|
method: "POST",
|
|
3647
4102
|
body: JSON.stringify({
|
|
3648
|
-
|
|
3649
|
-
name: options?.name,
|
|
4103
|
+
count,
|
|
3650
4104
|
env: options?.env,
|
|
3651
|
-
resources: options?.resources,
|
|
3652
4105
|
metadata: options?.metadata
|
|
3653
4106
|
})
|
|
3654
4107
|
});
|
|
@@ -3656,8 +4109,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3656
4109
|
const body = await response.text();
|
|
3657
4110
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3658
4111
|
}
|
|
3659
|
-
|
|
3660
|
-
return new SandboxInstance(this.client, this.parseInfo(data.sandbox ?? data), this.defaultRuntimeBackend);
|
|
4112
|
+
return ((await response.json()).children ?? []).map((child) => new SandboxInstance(this.client, this.parseInfo(child), this.defaultRuntimeBackend));
|
|
3661
4113
|
}
|
|
3662
4114
|
/**
|
|
3663
4115
|
* Stop the sandbox (keeps state for resume).
|
|
@@ -3894,17 +4346,6 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3894
4346
|
abortController.abort();
|
|
3895
4347
|
}
|
|
3896
4348
|
}
|
|
3897
|
-
parseCheckpointInfo(cp) {
|
|
3898
|
-
return {
|
|
3899
|
-
checkpointId: cp.checkpointId ?? cp.id,
|
|
3900
|
-
sandboxId: cp.sandboxId ?? cp.projectRef ?? this.id,
|
|
3901
|
-
createdAt: new Date(cp.createdAt),
|
|
3902
|
-
tags: cp.tags ?? [],
|
|
3903
|
-
sizeBytes: cp.sizeBytes,
|
|
3904
|
-
hasMemoryState: cp.hasMemoryState ?? true,
|
|
3905
|
-
hasFilesystemSnapshot: cp.hasFilesystemSnapshot ?? false
|
|
3906
|
-
};
|
|
3907
|
-
}
|
|
3908
4349
|
async ensureRunning() {
|
|
3909
4350
|
await this.refresh();
|
|
3910
4351
|
if (this.status !== "running") throw new StateError(`Sandbox is not running (status: ${this.status})`, this.status, "running");
|
|
@@ -3956,15 +4397,51 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3956
4397
|
async registerSessionMapping(opts) {
|
|
3957
4398
|
const response = await this.client.fetch(`/v1/session/${encodeURIComponent(opts.sessionId)}/mapping`, {
|
|
3958
4399
|
method: "PUT",
|
|
4400
|
+
headers: { "x-user-id": opts.userId },
|
|
3959
4401
|
body: JSON.stringify({
|
|
3960
|
-
|
|
3961
|
-
|
|
4402
|
+
sidecarSessionId: opts.runtimeSessionId,
|
|
4403
|
+
...opts.sidecarId ? { sidecarId: opts.sidecarId } : {},
|
|
4404
|
+
...opts.projectRef ? { projectRef: opts.projectRef } : {}
|
|
3962
4405
|
})
|
|
3963
4406
|
});
|
|
4407
|
+
if (response.status === 410) return {
|
|
4408
|
+
success: false,
|
|
4409
|
+
sessionId: opts.sessionId,
|
|
4410
|
+
reprovisionRequired: true,
|
|
4411
|
+
code: "STALE_SIDECAR"
|
|
4412
|
+
};
|
|
3964
4413
|
if (!response.ok) {
|
|
3965
4414
|
const body = await response.text();
|
|
3966
4415
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3967
4416
|
}
|
|
4417
|
+
const data = await response.json().catch(() => ({}));
|
|
4418
|
+
return {
|
|
4419
|
+
success: data.success ?? true,
|
|
4420
|
+
sessionId: data.sessionId ?? opts.sessionId,
|
|
4421
|
+
sidecarSessionId: data.sidecarSessionId,
|
|
4422
|
+
reprovisionRequired: data.reprovisionRequired ?? false,
|
|
4423
|
+
code: data.code
|
|
4424
|
+
};
|
|
4425
|
+
}
|
|
4426
|
+
/**
|
|
4427
|
+
* Remove the sidecar session mapping for an agent session. Sandbox deletion
|
|
4428
|
+
* also cleans mappings, so this is only needed to release a mapping while the
|
|
4429
|
+
* sandbox stays alive.
|
|
4430
|
+
*/
|
|
4431
|
+
async unregisterSessionMapping(opts) {
|
|
4432
|
+
const response = await this.client.fetch(`/v1/session/${encodeURIComponent(opts.sessionId)}/mapping`, {
|
|
4433
|
+
method: "DELETE",
|
|
4434
|
+
headers: { "x-user-id": opts.userId }
|
|
4435
|
+
});
|
|
4436
|
+
if (!response.ok) {
|
|
4437
|
+
const body = await response.text();
|
|
4438
|
+
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
4439
|
+
}
|
|
4440
|
+
const data = await response.json().catch(() => ({}));
|
|
4441
|
+
return {
|
|
4442
|
+
success: data.success ?? true,
|
|
4443
|
+
sessionId: data.sessionId ?? opts.sessionId
|
|
4444
|
+
};
|
|
3968
4445
|
}
|
|
3969
4446
|
parseInfo(data) {
|
|
3970
4447
|
return {
|
|
@@ -3978,6 +4455,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3978
4455
|
lastActivityAt: data.lastActivityAt ? new Date(data.lastActivityAt) : void 0,
|
|
3979
4456
|
expiresAt: data.expiresAt ? new Date(data.expiresAt) : void 0,
|
|
3980
4457
|
error: data.error,
|
|
4458
|
+
gpuLease: data.gpuLease ?? this.info.gpuLease,
|
|
3981
4459
|
startupDiagnostics: normalizeStartupDiagnostics(data.startupDiagnostics) ?? this.info?.startupDiagnostics
|
|
3982
4460
|
};
|
|
3983
4461
|
}
|
|
@@ -3992,6 +4470,30 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3992
4470
|
session(id) {
|
|
3993
4471
|
return new SandboxSession(this, id);
|
|
3994
4472
|
}
|
|
4473
|
+
/** Create an agent session and return both its handle and initial metadata. */
|
|
4474
|
+
async createSession(options) {
|
|
4475
|
+
const info = await this.runtime.createSession(options);
|
|
4476
|
+
return {
|
|
4477
|
+
session: this.session(info.id),
|
|
4478
|
+
info
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
4481
|
+
/** Delete an agent session by id. */
|
|
4482
|
+
async deleteSession(id) {
|
|
4483
|
+
return this._sessionDelete(id);
|
|
4484
|
+
}
|
|
4485
|
+
/** Get a lazy background-task session reference. */
|
|
4486
|
+
taskSession(id) {
|
|
4487
|
+
return new SandboxTaskSession(this, id);
|
|
4488
|
+
}
|
|
4489
|
+
/** Create a background task session. Dispatch work with `session.sendMessage()`. */
|
|
4490
|
+
async createTaskSession(options) {
|
|
4491
|
+
const info = await this.runtime.createTaskSession(options);
|
|
4492
|
+
return {
|
|
4493
|
+
session: this.taskSession(info.id),
|
|
4494
|
+
info
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
3995
4497
|
/**
|
|
3996
4498
|
* List sessions on this sandbox, optionally filtering by status. Returns
|
|
3997
4499
|
* `SandboxSession` instances paired with their last-known
|
|
@@ -4099,6 +4601,44 @@ var SandboxInstance = class SandboxInstance {
|
|
|
4099
4601
|
metadata: m.info.metadata
|
|
4100
4602
|
}));
|
|
4101
4603
|
}
|
|
4604
|
+
/** @internal — invoked by SandboxSession.sendMessage(). */
|
|
4605
|
+
async _sessionSendMessage(id, request, options = {}) {
|
|
4606
|
+
return this.runtime.sendSessionMessage(id, request, options);
|
|
4607
|
+
}
|
|
4608
|
+
/** @internal — invoked by SandboxSession.delete(). */
|
|
4609
|
+
async _sessionDelete(id) {
|
|
4610
|
+
return this.runtime.deleteSession(id);
|
|
4611
|
+
}
|
|
4612
|
+
/** @internal — invoked by SandboxTaskSession.changes(). */
|
|
4613
|
+
async _taskSessionChanges(id) {
|
|
4614
|
+
return this.runtime.taskSessionChanges(id);
|
|
4615
|
+
}
|
|
4616
|
+
/** @internal — invoked by SandboxTaskSession.commit(). */
|
|
4617
|
+
async _taskSessionCommit(id, options = {}) {
|
|
4618
|
+
return this.runtime.commitTaskSession(id, options);
|
|
4619
|
+
}
|
|
4620
|
+
async _sessionFork(id, opts = {}) {
|
|
4621
|
+
await this.ensureRunning();
|
|
4622
|
+
const body = {};
|
|
4623
|
+
if (opts.messageId !== void 0) body.messageID = opts.messageId;
|
|
4624
|
+
if (opts.targetBackend !== void 0) body.targetBackend = opts.targetBackend;
|
|
4625
|
+
if (opts.targetModel !== void 0) body.targetModel = opts.targetModel;
|
|
4626
|
+
if (opts.files !== void 0) body.files = opts.files;
|
|
4627
|
+
const response = await this.runtimeFetch(`/agents/sessions/${encodeURIComponent(id)}/forks`, {
|
|
4628
|
+
method: "POST",
|
|
4629
|
+
body: JSON.stringify(body)
|
|
4630
|
+
});
|
|
4631
|
+
if (!response.ok) {
|
|
4632
|
+
const responseBody = await response.text();
|
|
4633
|
+
throw parseErrorResponse(response.status, responseBody, void 0, response.headers);
|
|
4634
|
+
}
|
|
4635
|
+
const info = normalizeSessionInfo(await response.json());
|
|
4636
|
+
if (!info) throw new ServerError("Session fork response missing session id", 502, {
|
|
4637
|
+
origin: "runtime",
|
|
4638
|
+
endpoint: `/agents/sessions/${encodeURIComponent(id)}/forks`
|
|
4639
|
+
});
|
|
4640
|
+
return info;
|
|
4641
|
+
}
|
|
4102
4642
|
/**
|
|
4103
4643
|
* Look up a cached turn result by idempotency key. Returns the cached
|
|
4104
4644
|
* payload if a turn with this `turnId` previously completed on the
|
|
@@ -4441,28 +4981,6 @@ function settleTurnDrive(result) {
|
|
|
4441
4981
|
result
|
|
4442
4982
|
};
|
|
4443
4983
|
}
|
|
4444
|
-
function normalizeSessionInfo(raw) {
|
|
4445
|
-
const id = raw.id;
|
|
4446
|
-
if (typeof id !== "string") return null;
|
|
4447
|
-
const status = raw.status || "running";
|
|
4448
|
-
return {
|
|
4449
|
-
id,
|
|
4450
|
-
status: [
|
|
4451
|
-
"queued",
|
|
4452
|
-
"running",
|
|
4453
|
-
"completed",
|
|
4454
|
-
"failed",
|
|
4455
|
-
"cancelled"
|
|
4456
|
-
].includes(status) ? status : "running",
|
|
4457
|
-
backend: typeof raw.backendType === "string" ? raw.backendType : typeof raw.backend === "string" ? raw.backend : void 0,
|
|
4458
|
-
model: typeof raw.model === "string" ? raw.model : void 0,
|
|
4459
|
-
promptCount: typeof raw.promptCount === "number" ? raw.promptCount : void 0,
|
|
4460
|
-
createdAt: raw.createdAt ? new Date(raw.createdAt) : void 0,
|
|
4461
|
-
startedAt: raw.startedAt ? new Date(raw.startedAt) : void 0,
|
|
4462
|
-
endedAt: raw.endedAt ? new Date(raw.endedAt) : void 0,
|
|
4463
|
-
raw
|
|
4464
|
-
};
|
|
4465
|
-
}
|
|
4466
4984
|
var DirectRuntimeHttpClient = class {
|
|
4467
4985
|
baseClient;
|
|
4468
4986
|
sandboxId;
|
|
@@ -4529,4 +5047,4 @@ function quoteForShell(value) {
|
|
|
4529
5047
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
4530
5048
|
}
|
|
4531
5049
|
//#endregion
|
|
4532
|
-
export {
|
|
5050
|
+
export { normalizeRuntimeBackendConfig as _, InteractiveSessionHandle as a, getSandboxEventText as c, exportTraceBundle as d, otelTraceIdForTangleTrace as f, parseSSEStream as g, encodeTextForWire as h, SandboxSession as i, normalizeConnection as l, encodePromptForWire as m, normalizeStartupDiagnostics as n, applySandboxEventText as o, toOtelJson as p, SandboxTaskSession as r, collectAgentResponseText as s, SandboxInstance as t, buildTraceExportPayload as u, serializeForSidecar as v };
|