@tangle-network/sandbox 0.9.6 → 0.10.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 +28 -0
- package/dist/agent/index.d.ts +2 -2
- package/dist/auth/index.js +66 -25
- package/dist/{client-vBERsxhj.js → client-InX98Zxk.js} +98 -83
- package/dist/{client-DUY6Pdwf.d.ts → client-cfdZckhU.d.ts} +5 -1
- 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-CAay0NFR.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-DcOyvnIy.d.ts → sandbox-Bm2C9Phd.d.ts} +871 -162
- package/dist/{sandbox-UQrmff8d.js → sandbox-CeimsfC8.js} +688 -166
- package/dist/tangle/index.d.ts +1 -1
- package/dist/tangle/index.js +1 -1
- package/dist/{tangle-DRzRB6z1.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;
|
|
@@ -30,7 +32,9 @@ function normalizeRuntimeBackendConfig(backend, options = {}) {
|
|
|
30
32
|
...typeof backend?.profile === "string" ? { profile: backend.profile } : {},
|
|
31
33
|
...inlineProfile ? { inlineProfile } : callerInlineProfile ? { inlineProfile: callerInlineProfile } : {},
|
|
32
34
|
...backend?.model ? { model: backend.model } : options.model ? { model: parseModelString(options.model) } : {},
|
|
33
|
-
...backend?.server ? { server: backend.server } : {}
|
|
35
|
+
...backend?.server ? { server: backend.server } : {},
|
|
36
|
+
...backend?.interactions !== void 0 ? { interactions: backend.interactions } : {},
|
|
37
|
+
...backend?.metadata !== void 0 ? { metadata: backend.metadata } : {}
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
/**
|
|
@@ -97,19 +101,42 @@ function toBackendProfile(profile) {
|
|
|
97
101
|
...timeout !== void 0 ? { timeout } : {}
|
|
98
102
|
}];
|
|
99
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;
|
|
100
120
|
return {
|
|
101
121
|
name: profile.name,
|
|
122
|
+
description: profile.description,
|
|
123
|
+
version: profile.version,
|
|
124
|
+
tags: profile.tags,
|
|
125
|
+
...profileExtends ? { extends: profileExtends } : {},
|
|
102
126
|
model: profile.model?.default,
|
|
127
|
+
small_model: profile.model?.small,
|
|
103
128
|
...profile.prompt?.systemPrompt ? { systemPrompt: profile.prompt.systemPrompt } : {},
|
|
104
129
|
...Object.keys(tools).length > 0 ? { tools } : {},
|
|
105
130
|
...profile.prompt?.instructions?.length ? { instructions: profile.prompt.instructions } : {},
|
|
106
131
|
...Object.keys(permission).length > 0 ? { permission } : {},
|
|
107
132
|
...mcp ? { mcp } : {},
|
|
108
133
|
...profile.connections?.length ? { connections: profile.connections } : {},
|
|
109
|
-
...
|
|
134
|
+
...agents ? { agent: agents } : {},
|
|
110
135
|
...profile.resources && hasAnyProfileResource(profile.resources) ? { resources: profile.resources } : {},
|
|
111
136
|
...profile.hooks ? { hooks: profile.hooks } : {},
|
|
112
137
|
...profile.modes ? { modes: profile.modes } : {},
|
|
138
|
+
...commands ? { command: commands } : {},
|
|
139
|
+
...plugins?.length ? { plugin: plugins } : {},
|
|
113
140
|
...profile.extensions ? { extensions: profile.extensions } : {}
|
|
114
141
|
};
|
|
115
142
|
}
|
|
@@ -572,6 +599,244 @@ function collectAgentResponseText(events) {
|
|
|
572
599
|
return responseText && responseText.trim().length > 0 ? responseText : void 0;
|
|
573
600
|
}
|
|
574
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
|
|
575
840
|
//#region src/interactive.ts
|
|
576
841
|
/**
|
|
577
842
|
* Handle for one session's interactive harness. Obtained via
|
|
@@ -629,7 +894,7 @@ var InteractiveSessionHandle = class {
|
|
|
629
894
|
* A single agent session inside a sandbox. Created via
|
|
630
895
|
* `box.session(id)` — does not hit the network until a method is called.
|
|
631
896
|
*/
|
|
632
|
-
var SandboxSession = class {
|
|
897
|
+
var SandboxSession = class SandboxSession {
|
|
633
898
|
/**
|
|
634
899
|
* @internal SDK-internal constructor — apps should call `box.session(id)`.
|
|
635
900
|
*/
|
|
@@ -672,6 +937,16 @@ var SandboxSession = class {
|
|
|
672
937
|
return this.box._sessionResult(this.id);
|
|
673
938
|
}
|
|
674
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
|
+
/**
|
|
675
950
|
* Continue this session with an additional prompt. Equivalent to
|
|
676
951
|
* `box.prompt(message, { ...opts, sessionId: this.id })` but reads
|
|
677
952
|
* naturally on a Session reference.
|
|
@@ -683,6 +958,13 @@ var SandboxSession = class {
|
|
|
683
958
|
});
|
|
684
959
|
}
|
|
685
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
|
+
/**
|
|
686
968
|
* Abort the session's in-flight execution; the session and its messages
|
|
687
969
|
* are preserved (this does not delete the session). Void-returning alias
|
|
688
970
|
* of `interrupt()` — use `interrupt()` when you need to know whether an
|
|
@@ -693,6 +975,22 @@ var SandboxSession = class {
|
|
|
693
975
|
async cancel() {
|
|
694
976
|
return this.box._sessionCancel(this.id);
|
|
695
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
|
+
}
|
|
696
994
|
/**
|
|
697
995
|
* Drive this session's harness in INTERACTIVE mode: spawn its native TUI,
|
|
698
996
|
* stream the live framebuffer, and inject prompts as keystrokes. Distinct
|
|
@@ -720,14 +1018,34 @@ var SandboxSession = class {
|
|
|
720
1018
|
}
|
|
721
1019
|
/**
|
|
722
1020
|
* Answer a question the agent asked via a question tool invocation. `answers`
|
|
723
|
-
* maps each question id to the selected option(s).
|
|
724
|
-
*
|
|
1021
|
+
* maps each question id to the selected option(s). Backend-agnostic: works
|
|
1022
|
+
* with any backend that raises kind:"question" interactions — OpenCode
|
|
1023
|
+
* natively, or CLI backends with `BackendConfig.interactions.question`
|
|
1024
|
+
* enabled. Backends with no question support reject loudly.
|
|
725
1025
|
*/
|
|
726
1026
|
async answer(answers) {
|
|
727
1027
|
return this.box._answerQuestion(this.id, answers);
|
|
728
1028
|
}
|
|
729
1029
|
};
|
|
730
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
|
|
731
1049
|
//#region src/sandbox.ts
|
|
732
1050
|
/**
|
|
733
1051
|
* Sandbox Instance
|
|
@@ -1000,10 +1318,15 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1000
1318
|
client;
|
|
1001
1319
|
info;
|
|
1002
1320
|
defaultRuntimeBackend;
|
|
1321
|
+
runtime;
|
|
1003
1322
|
constructor(client, info, defaultRuntimeBackend) {
|
|
1004
1323
|
this.client = client;
|
|
1005
1324
|
this.info = info;
|
|
1006
1325
|
this.defaultRuntimeBackend = defaultRuntimeBackend;
|
|
1326
|
+
this.runtime = new SandboxRuntimeApi({
|
|
1327
|
+
ensureRunning: () => this.ensureRunning(),
|
|
1328
|
+
fetch: (path, init) => this.runtimeFetch(path, init)
|
|
1329
|
+
});
|
|
1007
1330
|
}
|
|
1008
1331
|
/** Unique sandbox identifier */
|
|
1009
1332
|
get id() {
|
|
@@ -1045,6 +1368,10 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1045
1368
|
get error() {
|
|
1046
1369
|
return this.info.error;
|
|
1047
1370
|
}
|
|
1371
|
+
/** GPU lease attached during sandbox creation, when requested. */
|
|
1372
|
+
get gpuLease() {
|
|
1373
|
+
return this.info.gpuLease;
|
|
1374
|
+
}
|
|
1048
1375
|
/** Web terminal URL for browser-based access */
|
|
1049
1376
|
get url() {
|
|
1050
1377
|
return this.info.connection?.webTerminalUrl;
|
|
@@ -1085,7 +1412,8 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1085
1412
|
startedAt: this.startedAt,
|
|
1086
1413
|
lastActivityAt: this.lastActivityAt,
|
|
1087
1414
|
expiresAt: this.expiresAt,
|
|
1088
|
-
error: this.error
|
|
1415
|
+
error: this.error,
|
|
1416
|
+
gpuLease: this.gpuLease
|
|
1089
1417
|
};
|
|
1090
1418
|
}
|
|
1091
1419
|
/**
|
|
@@ -1415,11 +1743,15 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1415
1743
|
*/
|
|
1416
1744
|
async write(path, content, options) {
|
|
1417
1745
|
await this.ensureRunning();
|
|
1418
|
-
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}` : ""}`, {
|
|
1419
1750
|
method: "POST",
|
|
1420
1751
|
body: JSON.stringify({
|
|
1421
1752
|
path,
|
|
1422
1753
|
content,
|
|
1754
|
+
encoding: options?.encoding,
|
|
1423
1755
|
mode: options?.mode
|
|
1424
1756
|
})
|
|
1425
1757
|
});
|
|
@@ -1427,6 +1759,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1427
1759
|
const body = await response.text();
|
|
1428
1760
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
1429
1761
|
}
|
|
1762
|
+
return (await response.json()).data;
|
|
1430
1763
|
}
|
|
1431
1764
|
/**
|
|
1432
1765
|
* Write many files in one paced, retry-aware batch — see
|
|
@@ -1527,6 +1860,13 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1527
1860
|
controller.abort();
|
|
1528
1861
|
}
|
|
1529
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
|
+
}
|
|
1530
1870
|
/**
|
|
1531
1871
|
* Stream events from an agent prompt.
|
|
1532
1872
|
* Use this for real-time updates during agent execution.
|
|
@@ -1558,16 +1898,27 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1558
1898
|
}
|
|
1559
1899
|
} catch (err) {
|
|
1560
1900
|
if (isCallerAbort()) return;
|
|
1901
|
+
this.logStreamCheckpoint("synthetic_error", {
|
|
1902
|
+
sessionId,
|
|
1903
|
+
executionId,
|
|
1904
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1905
|
+
});
|
|
1561
1906
|
yield toStreamErrorEvent(err);
|
|
1562
1907
|
} finally {
|
|
1563
|
-
if (!receivedTerminal && !isCallerAbort())
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
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
|
+
}
|
|
1571
1922
|
}
|
|
1572
1923
|
}
|
|
1573
1924
|
/**
|
|
@@ -1589,8 +1940,22 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1589
1940
|
origin: "runtime"
|
|
1590
1941
|
});
|
|
1591
1942
|
};
|
|
1943
|
+
const streamStartedAt = Date.now();
|
|
1944
|
+
const logStreamCheckpoint = (checkpoint, data = {}) => {
|
|
1945
|
+
this.logStreamCheckpoint(checkpoint, {
|
|
1946
|
+
elapsedMs: Date.now() - streamStartedAt,
|
|
1947
|
+
...data
|
|
1948
|
+
});
|
|
1949
|
+
};
|
|
1592
1950
|
let response;
|
|
1593
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
|
+
});
|
|
1594
1959
|
response = await this.runtimeFetch("/agents/run/stream", {
|
|
1595
1960
|
method: "POST",
|
|
1596
1961
|
signal: streamSignal,
|
|
@@ -1606,11 +1971,17 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1606
1971
|
turnId: options?.turnId,
|
|
1607
1972
|
metadata: options?.context,
|
|
1608
1973
|
requireVisibleAssistantOutput: options?.requireVisibleAssistantOutput,
|
|
1974
|
+
...timeoutMs ? { timeoutMs } : {},
|
|
1609
1975
|
...options?.detach ? { detach: true } : {},
|
|
1610
1976
|
backend: normalizeRuntimeBackendConfig(options?.backend ?? this.defaultRuntimeBackend, { model: options?.model })
|
|
1611
1977
|
})
|
|
1612
1978
|
});
|
|
1979
|
+
logStreamCheckpoint("runtime_response_headers", {
|
|
1980
|
+
status: response.status,
|
|
1981
|
+
ok: response.ok
|
|
1982
|
+
});
|
|
1613
1983
|
} catch (err) {
|
|
1984
|
+
logStreamCheckpoint("runtime_post_failed", { error: err instanceof Error ? err.message : String(err) });
|
|
1614
1985
|
throwIfTimedOut();
|
|
1615
1986
|
throw err;
|
|
1616
1987
|
}
|
|
@@ -1633,17 +2004,39 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1633
2004
|
const MAX_RECONNECT_ATTEMPTS = RECONNECT_BACKOFF_MS.length;
|
|
1634
2005
|
let lastReplayStatus;
|
|
1635
2006
|
let lastExecutionStatus;
|
|
2007
|
+
let firstSseEventSeen = false;
|
|
1636
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
|
+
}
|
|
1637
2016
|
if (event.id) lastEventId = event.id;
|
|
1638
2017
|
if (event.type === "execution.started" && event.data?.executionId) executionId = event.data.executionId;
|
|
1639
2018
|
const eventSessionId = event.data?.sessionId;
|
|
1640
2019
|
if (typeof eventSessionId === "string" && eventSessionId.length > 0) sessionId = eventSessionId;
|
|
1641
|
-
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
|
+
}
|
|
1642
2029
|
yield event;
|
|
1643
2030
|
}
|
|
1644
2031
|
if (receivedTerminal) return;
|
|
1645
2032
|
throwIfTimedOut();
|
|
1646
2033
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
2034
|
+
logStreamCheckpoint("stream_drop", {
|
|
2035
|
+
executionId,
|
|
2036
|
+
sessionId,
|
|
2037
|
+
lastEventId,
|
|
2038
|
+
receivedTerminal
|
|
2039
|
+
});
|
|
1647
2040
|
if (!executionId) throw new NetworkError("Prompt stream dropped before execution.started; cannot reconnect", {
|
|
1648
2041
|
endpoint: "/agents/run/stream",
|
|
1649
2042
|
origin: "runtime"
|
|
@@ -1652,6 +2045,12 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1652
2045
|
throwIfTimedOut();
|
|
1653
2046
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
1654
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
|
+
});
|
|
1655
2054
|
await new Promise((resolve) => setTimeout(resolve, RECONNECT_BACKOFF_MS[attempt - 1]));
|
|
1656
2055
|
throwIfTimedOut();
|
|
1657
2056
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
@@ -1661,6 +2060,11 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1661
2060
|
method: "GET",
|
|
1662
2061
|
signal: streamSignal
|
|
1663
2062
|
});
|
|
2063
|
+
logStreamCheckpoint("replay_response_status", {
|
|
2064
|
+
attempt,
|
|
2065
|
+
status: replayResponse.status,
|
|
2066
|
+
ok: replayResponse.ok
|
|
2067
|
+
});
|
|
1664
2068
|
if (!replayResponse.ok) {
|
|
1665
2069
|
lastReplayStatus = replayResponse.status;
|
|
1666
2070
|
console.warn(`[sandbox-sdk] Replay endpoint returned ${replayResponse.status}, attempt ${attempt}`);
|
|
@@ -1670,6 +2074,13 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1670
2074
|
lastExecutionStatus = info.status;
|
|
1671
2075
|
if (info.status === "completed" || info.status === "failed" || info.status === "cancelled") {
|
|
1672
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
|
+
});
|
|
1673
2084
|
yield {
|
|
1674
2085
|
type: "done",
|
|
1675
2086
|
data: {
|
|
@@ -1688,18 +2099,46 @@ var SandboxInstance = class SandboxInstance {
|
|
|
1688
2099
|
continue;
|
|
1689
2100
|
}
|
|
1690
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
|
+
}
|
|
1691
2110
|
if (event.type === "history.replay.start" || event.type === "history.replay.end") continue;
|
|
1692
2111
|
if (event.id) lastEventId = event.id;
|
|
1693
2112
|
const eventSessionId = event.data?.sessionId;
|
|
1694
2113
|
if (typeof eventSessionId === "string" && eventSessionId.length > 0) sessionId = eventSessionId;
|
|
1695
|
-
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
|
+
}
|
|
1696
2124
|
yield event;
|
|
1697
2125
|
}
|
|
1698
|
-
if (receivedTerminal)
|
|
2126
|
+
if (receivedTerminal) {
|
|
2127
|
+
logStreamCheckpoint("reconnect_attempt_end", {
|
|
2128
|
+
attempt,
|
|
2129
|
+
status: "terminal_received"
|
|
2130
|
+
});
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
1699
2133
|
throwIfTimedOut();
|
|
1700
2134
|
if (options?.signal?.aborted || streamSignal?.aborted) return;
|
|
1701
2135
|
} catch (err) {
|
|
1702
2136
|
throwIfTimedOut();
|
|
2137
|
+
logStreamCheckpoint("reconnect_attempt_end", {
|
|
2138
|
+
attempt,
|
|
2139
|
+
status: "failed",
|
|
2140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2141
|
+
});
|
|
1703
2142
|
console.warn(`[sandbox-sdk] Reconnection attempt ${attempt} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1704
2143
|
}
|
|
1705
2144
|
}
|
|
@@ -2011,6 +2450,22 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2011
2450
|
after: match.after
|
|
2012
2451
|
};
|
|
2013
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
|
+
}
|
|
2014
2469
|
/**
|
|
2015
2470
|
* Live whole-sandbox resource usage (memory + CPU) from the container cgroup.
|
|
2016
2471
|
*
|
|
@@ -2245,6 +2700,8 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2245
2700
|
return {
|
|
2246
2701
|
supportsWriteMode: true,
|
|
2247
2702
|
read: (path) => this.read(path),
|
|
2703
|
+
readBatch: (paths, options) => this.fsReadBatch(paths, options),
|
|
2704
|
+
tree: (path, options) => this.fsTree(path, options),
|
|
2248
2705
|
write: (path, content, options) => this.write(path, content, options),
|
|
2249
2706
|
writeMany: (files, options) => this.writeMany(files, options),
|
|
2250
2707
|
search: (query, options) => this.search(query, options),
|
|
@@ -2259,6 +2716,12 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2259
2716
|
exists: (path) => this.fsExists(path)
|
|
2260
2717
|
};
|
|
2261
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
|
+
}
|
|
2262
2725
|
async fsUpload(localPath, remotePath, options) {
|
|
2263
2726
|
await this.ensureRunning();
|
|
2264
2727
|
const fs = await import("node:fs/promises");
|
|
@@ -2365,6 +2828,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2365
2828
|
const params = new URLSearchParams();
|
|
2366
2829
|
if (options?.all) params.set("all", "true");
|
|
2367
2830
|
if (options?.long) params.set("long", "true");
|
|
2831
|
+
if (options?.sessionId) params.set("sessionId", options.sessionId);
|
|
2368
2832
|
const query = params.toString();
|
|
2369
2833
|
const url = query ? `/fs/list${path}?${query}` : `/fs/list${path}`;
|
|
2370
2834
|
const response = await this.runtimeFetch(url, { method: "GET" });
|
|
@@ -2410,8 +2874,21 @@ var SandboxInstance = class SandboxInstance {
|
|
|
2410
2874
|
}
|
|
2411
2875
|
async fsDelete(path, options) {
|
|
2412
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
|
+
}
|
|
2413
2889
|
const params = new URLSearchParams();
|
|
2414
2890
|
if (options?.recursive) params.set("recursive", "true");
|
|
2891
|
+
if (options?.sessionId) params.set("sessionId", options.sessionId);
|
|
2415
2892
|
const query = params.toString();
|
|
2416
2893
|
const url = query ? `/fs${path}?${query}` : `/fs${path}`;
|
|
2417
2894
|
const response = await this.runtimeFetch(url, { method: "DELETE" });
|
|
@@ -3042,6 +3519,20 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3042
3519
|
update: (policy) => this.egressUpdate(policy)
|
|
3043
3520
|
};
|
|
3044
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
|
+
}
|
|
3045
3536
|
async networkUpdate(config) {
|
|
3046
3537
|
if (config.blockOutbound !== void 0 && config.allowList !== void 0) {
|
|
3047
3538
|
if (config.blockOutbound && config.allowList.length > 0) throw new Error("blockOutbound and allowList are mutually exclusive");
|
|
@@ -3119,6 +3610,44 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3119
3610
|
source: data.source
|
|
3120
3611
|
};
|
|
3121
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
|
+
}
|
|
3122
3651
|
/**
|
|
3123
3652
|
* Validate CIDR notation (IPv4 and IPv6)
|
|
3124
3653
|
*/
|
|
@@ -3519,132 +4048,60 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3519
4048
|
};
|
|
3520
4049
|
}
|
|
3521
4050
|
/**
|
|
3522
|
-
*
|
|
3523
|
-
*
|
|
3524
|
-
*
|
|
3525
|
-
* enabling true pause/resume and fork operations. Unlike snapshots which
|
|
3526
|
-
* only preserve filesystem state, checkpoints preserve process memory,
|
|
3527
|
-
* open file descriptors, and execution state.
|
|
3528
|
-
*
|
|
3529
|
-
* **Requirements:** CRIU must be available on the host. Check availability
|
|
3530
|
-
* with `client.criuStatus()` before calling.
|
|
3531
|
-
*
|
|
3532
|
-
* **Note:** By default, checkpoint stops the sandbox. Use `leaveRunning: true`
|
|
3533
|
-
* to keep it running (creates a copy-on-write checkpoint).
|
|
3534
|
-
*
|
|
3535
|
-
* @param options - Checkpoint options
|
|
3536
|
-
* @returns Checkpoint result with ID and metadata
|
|
3537
|
-
*
|
|
3538
|
-
* @example Basic checkpoint (stops sandbox)
|
|
3539
|
-
* ```typescript
|
|
3540
|
-
* const checkpoint = await box.checkpoint();
|
|
3541
|
-
* console.log(`Checkpoint: ${checkpoint.checkpointId}`);
|
|
3542
|
-
* // Sandbox is now stopped, resume with box.resume()
|
|
3543
|
-
* ```
|
|
3544
|
-
*
|
|
3545
|
-
* @example Checkpoint without stopping
|
|
3546
|
-
* ```typescript
|
|
3547
|
-
* const checkpoint = await box.checkpoint({
|
|
3548
|
-
* tags: ["before-deploy"],
|
|
3549
|
-
* leaveRunning: true,
|
|
3550
|
-
* });
|
|
3551
|
-
* // Sandbox continues running
|
|
3552
|
-
* ```
|
|
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.
|
|
3553
4054
|
*/
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
method: "POST",
|
|
3557
|
-
body: JSON.stringify({
|
|
3558
|
-
tags: options?.tags,
|
|
3559
|
-
leaveRunning: options?.leaveRunning,
|
|
3560
|
-
includeSnapshot: options?.includeSnapshot
|
|
3561
|
-
})
|
|
3562
|
-
});
|
|
3563
|
-
if (!response.ok) {
|
|
3564
|
-
const body = await response.text();
|
|
3565
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3566
|
-
}
|
|
3567
|
-
const data = await response.json();
|
|
3568
|
-
return {
|
|
3569
|
-
checkpointId: data.checkpointId ?? data.id,
|
|
3570
|
-
createdAt: new Date(data.createdAt ?? ""),
|
|
3571
|
-
sizeBytes: data.sizeBytes,
|
|
3572
|
-
tags: data.tags ?? []
|
|
3573
|
-
};
|
|
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);
|
|
3574
4057
|
}
|
|
3575
4058
|
/**
|
|
3576
|
-
*
|
|
3577
|
-
*
|
|
3578
|
-
* @returns Array of checkpoint metadata
|
|
3579
|
-
*
|
|
3580
|
-
* @example
|
|
3581
|
-
* ```typescript
|
|
3582
|
-
* const checkpoints = await box.listCheckpoints();
|
|
3583
|
-
* for (const cp of checkpoints) {
|
|
3584
|
-
* console.log(`${cp.checkpointId}: ${cp.createdAt}`);
|
|
3585
|
-
* }
|
|
3586
|
-
* ```
|
|
4059
|
+
* @deprecated CRIU checkpoints were removed. List durable filesystem state
|
|
4060
|
+
* with {@link listSnapshots}. This method now throws.
|
|
3587
4061
|
*/
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
if (!response.ok) {
|
|
3591
|
-
const body = await response.text();
|
|
3592
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3593
|
-
}
|
|
3594
|
-
const data = await response.json();
|
|
3595
|
-
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);
|
|
3596
4064
|
}
|
|
3597
4065
|
/**
|
|
3598
|
-
*
|
|
3599
|
-
*
|
|
3600
|
-
* @param checkpointId - ID of the checkpoint to delete
|
|
4066
|
+
* @deprecated CRIU checkpoints were removed. This method now throws.
|
|
3601
4067
|
*/
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
if (!response.ok) {
|
|
3605
|
-
const body = await response.text();
|
|
3606
|
-
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3607
|
-
}
|
|
4068
|
+
deleteCheckpoint() {
|
|
4069
|
+
throw new CapabilityError("deleteCheckpoint() was removed: checkpoints no longer exist", "CHECKPOINT_REMOVED", 410);
|
|
3608
4070
|
}
|
|
3609
4071
|
/**
|
|
3610
|
-
*
|
|
3611
|
-
*
|
|
3612
|
-
*
|
|
3613
|
-
*
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
*
|
|
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.
|
|
3620
4087
|
*
|
|
3621
|
-
* @param
|
|
3622
|
-
* @param options -
|
|
3623
|
-
* @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.
|
|
3624
4091
|
*
|
|
3625
|
-
* @example
|
|
3626
|
-
* ```typescript
|
|
3627
|
-
* const checkpoint = await box.checkpoint({ leaveRunning: true });
|
|
3628
|
-
* const forked = await box.fork(checkpoint.checkpointId);
|
|
3629
|
-
* // forked has same memory state as box at checkpoint time
|
|
3630
|
-
* ```
|
|
3631
|
-
*
|
|
3632
|
-
* @example Fork with custom config
|
|
4092
|
+
* @example
|
|
3633
4093
|
* ```typescript
|
|
3634
|
-
* const
|
|
3635
|
-
*
|
|
3636
|
-
* env: { EXPERIMENT: "true" },
|
|
3637
|
-
* });
|
|
4094
|
+
* const [a, b, c] = await box.branch(3);
|
|
4095
|
+
* // a, b, c each share box's memory state at branch time
|
|
3638
4096
|
* ```
|
|
3639
4097
|
*/
|
|
3640
|
-
async
|
|
3641
|
-
|
|
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`, {
|
|
3642
4101
|
method: "POST",
|
|
3643
4102
|
body: JSON.stringify({
|
|
3644
|
-
|
|
3645
|
-
name: options?.name,
|
|
4103
|
+
count,
|
|
3646
4104
|
env: options?.env,
|
|
3647
|
-
resources: options?.resources,
|
|
3648
4105
|
metadata: options?.metadata
|
|
3649
4106
|
})
|
|
3650
4107
|
});
|
|
@@ -3652,8 +4109,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3652
4109
|
const body = await response.text();
|
|
3653
4110
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3654
4111
|
}
|
|
3655
|
-
|
|
3656
|
-
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));
|
|
3657
4113
|
}
|
|
3658
4114
|
/**
|
|
3659
4115
|
* Stop the sandbox (keeps state for resume).
|
|
@@ -3890,17 +4346,6 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3890
4346
|
abortController.abort();
|
|
3891
4347
|
}
|
|
3892
4348
|
}
|
|
3893
|
-
parseCheckpointInfo(cp) {
|
|
3894
|
-
return {
|
|
3895
|
-
checkpointId: cp.checkpointId ?? cp.id,
|
|
3896
|
-
sandboxId: cp.sandboxId ?? cp.projectRef ?? this.id,
|
|
3897
|
-
createdAt: new Date(cp.createdAt),
|
|
3898
|
-
tags: cp.tags ?? [],
|
|
3899
|
-
sizeBytes: cp.sizeBytes,
|
|
3900
|
-
hasMemoryState: cp.hasMemoryState ?? true,
|
|
3901
|
-
hasFilesystemSnapshot: cp.hasFilesystemSnapshot ?? false
|
|
3902
|
-
};
|
|
3903
|
-
}
|
|
3904
4349
|
async ensureRunning() {
|
|
3905
4350
|
await this.refresh();
|
|
3906
4351
|
if (this.status !== "running") throw new StateError(`Sandbox is not running (status: ${this.status})`, this.status, "running");
|
|
@@ -3952,15 +4397,51 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3952
4397
|
async registerSessionMapping(opts) {
|
|
3953
4398
|
const response = await this.client.fetch(`/v1/session/${encodeURIComponent(opts.sessionId)}/mapping`, {
|
|
3954
4399
|
method: "PUT",
|
|
4400
|
+
headers: { "x-user-id": opts.userId },
|
|
3955
4401
|
body: JSON.stringify({
|
|
3956
|
-
|
|
3957
|
-
|
|
4402
|
+
sidecarSessionId: opts.runtimeSessionId,
|
|
4403
|
+
...opts.sidecarId ? { sidecarId: opts.sidecarId } : {},
|
|
4404
|
+
...opts.projectRef ? { projectRef: opts.projectRef } : {}
|
|
3958
4405
|
})
|
|
3959
4406
|
});
|
|
4407
|
+
if (response.status === 410) return {
|
|
4408
|
+
success: false,
|
|
4409
|
+
sessionId: opts.sessionId,
|
|
4410
|
+
reprovisionRequired: true,
|
|
4411
|
+
code: "STALE_SIDECAR"
|
|
4412
|
+
};
|
|
3960
4413
|
if (!response.ok) {
|
|
3961
4414
|
const body = await response.text();
|
|
3962
4415
|
throw parseErrorResponse(response.status, body, void 0, response.headers);
|
|
3963
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
|
+
};
|
|
3964
4445
|
}
|
|
3965
4446
|
parseInfo(data) {
|
|
3966
4447
|
return {
|
|
@@ -3974,6 +4455,7 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3974
4455
|
lastActivityAt: data.lastActivityAt ? new Date(data.lastActivityAt) : void 0,
|
|
3975
4456
|
expiresAt: data.expiresAt ? new Date(data.expiresAt) : void 0,
|
|
3976
4457
|
error: data.error,
|
|
4458
|
+
gpuLease: data.gpuLease ?? this.info.gpuLease,
|
|
3977
4459
|
startupDiagnostics: normalizeStartupDiagnostics(data.startupDiagnostics) ?? this.info?.startupDiagnostics
|
|
3978
4460
|
};
|
|
3979
4461
|
}
|
|
@@ -3988,6 +4470,30 @@ var SandboxInstance = class SandboxInstance {
|
|
|
3988
4470
|
session(id) {
|
|
3989
4471
|
return new SandboxSession(this, id);
|
|
3990
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
|
+
}
|
|
3991
4497
|
/**
|
|
3992
4498
|
* List sessions on this sandbox, optionally filtering by status. Returns
|
|
3993
4499
|
* `SandboxSession` instances paired with their last-known
|
|
@@ -4095,6 +4601,44 @@ var SandboxInstance = class SandboxInstance {
|
|
|
4095
4601
|
metadata: m.info.metadata
|
|
4096
4602
|
}));
|
|
4097
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
|
+
}
|
|
4098
4642
|
/**
|
|
4099
4643
|
* Look up a cached turn result by idempotency key. Returns the cached
|
|
4100
4644
|
* payload if a turn with this `turnId` previously completed on the
|
|
@@ -4437,28 +4981,6 @@ function settleTurnDrive(result) {
|
|
|
4437
4981
|
result
|
|
4438
4982
|
};
|
|
4439
4983
|
}
|
|
4440
|
-
function normalizeSessionInfo(raw) {
|
|
4441
|
-
const id = raw.id;
|
|
4442
|
-
if (typeof id !== "string") return null;
|
|
4443
|
-
const status = raw.status || "running";
|
|
4444
|
-
return {
|
|
4445
|
-
id,
|
|
4446
|
-
status: [
|
|
4447
|
-
"queued",
|
|
4448
|
-
"running",
|
|
4449
|
-
"completed",
|
|
4450
|
-
"failed",
|
|
4451
|
-
"cancelled"
|
|
4452
|
-
].includes(status) ? status : "running",
|
|
4453
|
-
backend: typeof raw.backendType === "string" ? raw.backendType : typeof raw.backend === "string" ? raw.backend : void 0,
|
|
4454
|
-
model: typeof raw.model === "string" ? raw.model : void 0,
|
|
4455
|
-
promptCount: typeof raw.promptCount === "number" ? raw.promptCount : void 0,
|
|
4456
|
-
createdAt: raw.createdAt ? new Date(raw.createdAt) : void 0,
|
|
4457
|
-
startedAt: raw.startedAt ? new Date(raw.startedAt) : void 0,
|
|
4458
|
-
endedAt: raw.endedAt ? new Date(raw.endedAt) : void 0,
|
|
4459
|
-
raw
|
|
4460
|
-
};
|
|
4461
|
-
}
|
|
4462
4984
|
var DirectRuntimeHttpClient = class {
|
|
4463
4985
|
baseClient;
|
|
4464
4986
|
sandboxId;
|
|
@@ -4525,4 +5047,4 @@ function quoteForShell(value) {
|
|
|
4525
5047
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
4526
5048
|
}
|
|
4527
5049
|
//#endregion
|
|
4528
|
-
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 };
|