@openai/agents-extensions 0.8.4 → 0.9.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/dist/ai-sdk-ui/uiMessageStream.d.ts +5 -0
- package/dist/ai-sdk-ui/uiMessageStream.js +10 -3
- package/dist/ai-sdk-ui/uiMessageStream.js.map +1 -1
- package/dist/ai-sdk-ui/uiMessageStream.mjs +9 -3
- package/dist/ai-sdk-ui/uiMessageStream.mjs.map +1 -1
- package/dist/metadata.js +2 -2
- package/dist/metadata.mjs +2 -2
- package/dist/sandbox/blaxel/index.d.ts +2 -0
- package/dist/sandbox/blaxel/index.js +19 -0
- package/dist/sandbox/blaxel/index.js.map +1 -0
- package/dist/sandbox/blaxel/index.mjs +3 -0
- package/dist/sandbox/blaxel/index.mjs.map +1 -0
- package/dist/sandbox/blaxel/mounts.d.ts +101 -0
- package/dist/sandbox/blaxel/mounts.js +542 -0
- package/dist/sandbox/blaxel/mounts.js.map +1 -0
- package/dist/sandbox/blaxel/mounts.mjs +529 -0
- package/dist/sandbox/blaxel/mounts.mjs.map +1 -0
- package/dist/sandbox/blaxel/sandbox.d.ts +155 -0
- package/dist/sandbox/blaxel/sandbox.js +1110 -0
- package/dist/sandbox/blaxel/sandbox.js.map +1 -0
- package/dist/sandbox/blaxel/sandbox.mjs +1072 -0
- package/dist/sandbox/blaxel/sandbox.mjs.map +1 -0
- package/dist/sandbox/cloudflare/index.d.ts +2 -0
- package/dist/sandbox/cloudflare/index.js +19 -0
- package/dist/sandbox/cloudflare/index.js.map +1 -0
- package/dist/sandbox/cloudflare/index.mjs +3 -0
- package/dist/sandbox/cloudflare/index.mjs.map +1 -0
- package/dist/sandbox/cloudflare/mounts.d.ts +28 -0
- package/dist/sandbox/cloudflare/mounts.js +150 -0
- package/dist/sandbox/cloudflare/mounts.js.map +1 -0
- package/dist/sandbox/cloudflare/mounts.mjs +143 -0
- package/dist/sandbox/cloudflare/mounts.mjs.map +1 -0
- package/dist/sandbox/cloudflare/sandbox.d.ts +91 -0
- package/dist/sandbox/cloudflare/sandbox.js +1163 -0
- package/dist/sandbox/cloudflare/sandbox.js.map +1 -0
- package/dist/sandbox/cloudflare/sandbox.mjs +1125 -0
- package/dist/sandbox/cloudflare/sandbox.mjs.map +1 -0
- package/dist/sandbox/daytona/index.d.ts +2 -0
- package/dist/sandbox/daytona/index.js +19 -0
- package/dist/sandbox/daytona/index.js.map +1 -0
- package/dist/sandbox/daytona/index.mjs +3 -0
- package/dist/sandbox/daytona/index.mjs.map +1 -0
- package/dist/sandbox/daytona/mounts.d.ts +11 -0
- package/dist/sandbox/daytona/mounts.js +17 -0
- package/dist/sandbox/daytona/mounts.js.map +1 -0
- package/dist/sandbox/daytona/mounts.mjs +12 -0
- package/dist/sandbox/daytona/mounts.mjs.map +1 -0
- package/dist/sandbox/daytona/sandbox.d.ts +160 -0
- package/dist/sandbox/daytona/sandbox.js +938 -0
- package/dist/sandbox/daytona/sandbox.js.map +1 -0
- package/dist/sandbox/daytona/sandbox.mjs +900 -0
- package/dist/sandbox/daytona/sandbox.mjs.map +1 -0
- package/dist/sandbox/e2b/index.d.ts +2 -0
- package/dist/sandbox/e2b/index.js +19 -0
- package/dist/sandbox/e2b/index.js.map +1 -0
- package/dist/sandbox/e2b/index.mjs +3 -0
- package/dist/sandbox/e2b/index.mjs.map +1 -0
- package/dist/sandbox/e2b/mounts.d.ts +11 -0
- package/dist/sandbox/e2b/mounts.js +17 -0
- package/dist/sandbox/e2b/mounts.js.map +1 -0
- package/dist/sandbox/e2b/mounts.mjs +12 -0
- package/dist/sandbox/e2b/mounts.mjs.map +1 -0
- package/dist/sandbox/e2b/sandbox.d.ts +169 -0
- package/dist/sandbox/e2b/sandbox.js +829 -0
- package/dist/sandbox/e2b/sandbox.js.map +1 -0
- package/dist/sandbox/e2b/sandbox.mjs +791 -0
- package/dist/sandbox/e2b/sandbox.mjs.map +1 -0
- package/dist/sandbox/modal/index.d.ts +2 -0
- package/dist/sandbox/modal/index.js +19 -0
- package/dist/sandbox/modal/index.js.map +1 -0
- package/dist/sandbox/modal/index.mjs +3 -0
- package/dist/sandbox/modal/index.mjs.map +1 -0
- package/dist/sandbox/modal/mounts.d.ts +24 -0
- package/dist/sandbox/modal/mounts.js +194 -0
- package/dist/sandbox/modal/mounts.js.map +1 -0
- package/dist/sandbox/modal/mounts.mjs +188 -0
- package/dist/sandbox/modal/mounts.mjs.map +1 -0
- package/dist/sandbox/modal/sandbox.d.ts +220 -0
- package/dist/sandbox/modal/sandbox.js +1621 -0
- package/dist/sandbox/modal/sandbox.js.map +1 -0
- package/dist/sandbox/modal/sandbox.mjs +1581 -0
- package/dist/sandbox/modal/sandbox.mjs.map +1 -0
- package/dist/sandbox/runloop/index.d.ts +2 -0
- package/dist/sandbox/runloop/index.js +19 -0
- package/dist/sandbox/runloop/index.js.map +1 -0
- package/dist/sandbox/runloop/index.mjs +3 -0
- package/dist/sandbox/runloop/index.mjs.map +1 -0
- package/dist/sandbox/runloop/mounts.d.ts +11 -0
- package/dist/sandbox/runloop/mounts.js +17 -0
- package/dist/sandbox/runloop/mounts.js.map +1 -0
- package/dist/sandbox/runloop/mounts.mjs +12 -0
- package/dist/sandbox/runloop/mounts.mjs.map +1 -0
- package/dist/sandbox/runloop/sandbox.d.ts +266 -0
- package/dist/sandbox/runloop/sandbox.js +1390 -0
- package/dist/sandbox/runloop/sandbox.js.map +1 -0
- package/dist/sandbox/runloop/sandbox.mjs +1346 -0
- package/dist/sandbox/runloop/sandbox.mjs.map +1 -0
- package/dist/sandbox/shared/archive.d.ts +34 -0
- package/dist/sandbox/shared/archive.js +397 -0
- package/dist/sandbox/shared/archive.js.map +1 -0
- package/dist/sandbox/shared/archive.mjs +389 -0
- package/dist/sandbox/shared/archive.mjs.map +1 -0
- package/dist/sandbox/shared/editor.d.ts +17 -0
- package/dist/sandbox/shared/editor.js +65 -0
- package/dist/sandbox/shared/editor.js.map +1 -0
- package/dist/sandbox/shared/editor.mjs +61 -0
- package/dist/sandbox/shared/editor.mjs.map +1 -0
- package/dist/sandbox/shared/environment.d.ts +1 -0
- package/dist/sandbox/shared/environment.js +13 -0
- package/dist/sandbox/shared/environment.js.map +1 -0
- package/dist/sandbox/shared/environment.mjs +2 -0
- package/dist/sandbox/shared/environment.mjs.map +1 -0
- package/dist/sandbox/shared/git.d.ts +4 -0
- package/dist/sandbox/shared/git.js +20 -0
- package/dist/sandbox/shared/git.js.map +1 -0
- package/dist/sandbox/shared/git.mjs +17 -0
- package/dist/sandbox/shared/git.mjs.map +1 -0
- package/dist/sandbox/shared/inContainerMounts.d.ts +40 -0
- package/dist/sandbox/shared/inContainerMounts.js +670 -0
- package/dist/sandbox/shared/inContainerMounts.js.map +1 -0
- package/dist/sandbox/shared/inContainerMounts.mjs +662 -0
- package/dist/sandbox/shared/inContainerMounts.mjs.map +1 -0
- package/dist/sandbox/shared/index.d.ts +23 -0
- package/dist/sandbox/shared/index.js +112 -0
- package/dist/sandbox/shared/index.js.map +1 -0
- package/dist/sandbox/shared/index.mjs +18 -0
- package/dist/sandbox/shared/index.mjs.map +1 -0
- package/dist/sandbox/shared/localSources.d.ts +8 -0
- package/dist/sandbox/shared/localSources.js +378 -0
- package/dist/sandbox/shared/localSources.js.map +1 -0
- package/dist/sandbox/shared/localSources.mjs +372 -0
- package/dist/sandbox/shared/localSources.mjs.map +1 -0
- package/dist/sandbox/shared/manifest.d.ts +38 -0
- package/dist/sandbox/shared/manifest.js +254 -0
- package/dist/sandbox/shared/manifest.js.map +1 -0
- package/dist/sandbox/shared/manifest.mjs +233 -0
- package/dist/sandbox/shared/manifest.mjs.map +1 -0
- package/dist/sandbox/shared/media.d.ts +1 -0
- package/dist/sandbox/shared/media.js +10 -0
- package/dist/sandbox/shared/media.js.map +1 -0
- package/dist/sandbox/shared/media.mjs +2 -0
- package/dist/sandbox/shared/media.mjs.map +1 -0
- package/dist/sandbox/shared/metadata.d.ts +7 -0
- package/dist/sandbox/shared/metadata.js +87 -0
- package/dist/sandbox/shared/metadata.js.map +1 -0
- package/dist/sandbox/shared/metadata.mjs +81 -0
- package/dist/sandbox/shared/metadata.mjs.map +1 -0
- package/dist/sandbox/shared/output.d.ts +1 -0
- package/dist/sandbox/shared/output.js +8 -0
- package/dist/sandbox/shared/output.js.map +1 -0
- package/dist/sandbox/shared/output.mjs +2 -0
- package/dist/sandbox/shared/output.mjs.map +1 -0
- package/dist/sandbox/shared/paths.d.ts +27 -0
- package/dist/sandbox/shared/paths.js +245 -0
- package/dist/sandbox/shared/paths.js.map +1 -0
- package/dist/sandbox/shared/paths.mjs +236 -0
- package/dist/sandbox/shared/paths.mjs.map +1 -0
- package/dist/sandbox/shared/ports.d.ts +14 -0
- package/dist/sandbox/shared/ports.js +75 -0
- package/dist/sandbox/shared/ports.js.map +1 -0
- package/dist/sandbox/shared/ports.mjs +69 -0
- package/dist/sandbox/shared/ports.mjs.map +1 -0
- package/dist/sandbox/shared/process.d.ts +16 -0
- package/dist/sandbox/shared/process.js +90 -0
- package/dist/sandbox/shared/process.js.map +1 -0
- package/dist/sandbox/shared/process.mjs +86 -0
- package/dist/sandbox/shared/process.mjs.map +1 -0
- package/dist/sandbox/shared/pty.d.ts +81 -0
- package/dist/sandbox/shared/pty.js +382 -0
- package/dist/sandbox/shared/pty.js.map +1 -0
- package/dist/sandbox/shared/pty.mjs +335 -0
- package/dist/sandbox/shared/pty.mjs.map +1 -0
- package/dist/sandbox/shared/runAs.d.ts +46 -0
- package/dist/sandbox/shared/runAs.js +149 -0
- package/dist/sandbox/shared/runAs.js.map +1 -0
- package/dist/sandbox/shared/runAs.mjs +141 -0
- package/dist/sandbox/shared/runAs.mjs.map +1 -0
- package/dist/sandbox/shared/session.d.ts +16 -0
- package/dist/sandbox/shared/session.js +138 -0
- package/dist/sandbox/shared/session.js.map +1 -0
- package/dist/sandbox/shared/session.mjs +128 -0
- package/dist/sandbox/shared/session.mjs.map +1 -0
- package/dist/sandbox/shared/sessionBase.d.ts +90 -0
- package/dist/sandbox/shared/sessionBase.js +446 -0
- package/dist/sandbox/shared/sessionBase.js.map +1 -0
- package/dist/sandbox/shared/sessionBase.mjs +442 -0
- package/dist/sandbox/shared/sessionBase.mjs.map +1 -0
- package/dist/sandbox/shared/sessionState.d.ts +7 -0
- package/dist/sandbox/shared/sessionState.js +35 -0
- package/dist/sandbox/shared/sessionState.js.map +1 -0
- package/dist/sandbox/shared/sessionState.mjs +31 -0
- package/dist/sandbox/shared/sessionState.mjs.map +1 -0
- package/dist/sandbox/shared/snapshots.d.ts +9 -0
- package/dist/sandbox/shared/snapshots.js +62 -0
- package/dist/sandbox/shared/snapshots.js.map +1 -0
- package/dist/sandbox/shared/snapshots.mjs +57 -0
- package/dist/sandbox/shared/snapshots.mjs.map +1 -0
- package/dist/sandbox/shared/typeGuards.d.ts +10 -0
- package/dist/sandbox/shared/typeGuards.js +50 -0
- package/dist/sandbox/shared/typeGuards.js.map +1 -0
- package/dist/sandbox/shared/typeGuards.mjs +38 -0
- package/dist/sandbox/shared/typeGuards.mjs.map +1 -0
- package/dist/sandbox/shared/types.d.ts +24 -0
- package/dist/sandbox/shared/types.js +3 -0
- package/dist/sandbox/shared/types.js.map +1 -0
- package/dist/sandbox/shared/types.mjs +2 -0
- package/dist/sandbox/shared/types.mjs.map +1 -0
- package/dist/sandbox/vercel/index.d.ts +1 -0
- package/dist/sandbox/vercel/index.js +18 -0
- package/dist/sandbox/vercel/index.js.map +1 -0
- package/dist/sandbox/vercel/index.mjs +2 -0
- package/dist/sandbox/vercel/index.mjs.map +1 -0
- package/dist/sandbox/vercel/sandbox.d.ts +135 -0
- package/dist/sandbox/vercel/sandbox.js +1001 -0
- package/dist/sandbox/vercel/sandbox.js.map +1 -0
- package/dist/sandbox/vercel/sandbox.mjs +963 -0
- package/dist/sandbox/vercel/sandbox.mjs.map +1 -0
- package/package.json +108 -4
|
@@ -0,0 +1,1110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BlaxelSandboxClient = exports.BlaxelSandboxSession = exports.DEFAULT_BLAXEL_WORKSPACE_ROOT = void 0;
|
|
37
|
+
const agents_core_1 = require("@openai/agents-core");
|
|
38
|
+
const _shims_1 = require("@openai/agents-core/_shims");
|
|
39
|
+
const sandbox_1 = require("@openai/agents-core/sandbox");
|
|
40
|
+
const shared_1 = require("../shared/index.js");
|
|
41
|
+
const mounts_1 = require("./mounts.js");
|
|
42
|
+
exports.DEFAULT_BLAXEL_WORKSPACE_ROOT = '/workspace';
|
|
43
|
+
const BLAXEL_AUTOGENERATED_NAME_CREATE_ATTEMPTS = 5;
|
|
44
|
+
const BLAXEL_NON_RESUMABLE_SANDBOX_STATUSES = new Set([
|
|
45
|
+
'DEACTIVATING',
|
|
46
|
+
'DEACTIVATED',
|
|
47
|
+
'DELETING',
|
|
48
|
+
'FAILED',
|
|
49
|
+
'TERMINATING',
|
|
50
|
+
'TERMINATED',
|
|
51
|
+
]);
|
|
52
|
+
class BlaxelSandboxSession extends shared_1.RemoteSandboxSessionBase {
|
|
53
|
+
sandbox;
|
|
54
|
+
apiKey;
|
|
55
|
+
ownsSandbox;
|
|
56
|
+
closed = false;
|
|
57
|
+
ptyProcesses = new shared_1.PtyProcessRegistry();
|
|
58
|
+
activeFuseMountPaths = new Set();
|
|
59
|
+
activeDriveMountPaths = new Set();
|
|
60
|
+
constructor(args) {
|
|
61
|
+
super({
|
|
62
|
+
state: args.state,
|
|
63
|
+
options: {
|
|
64
|
+
providerName: 'BlaxelSandboxClient',
|
|
65
|
+
providerId: 'blaxel',
|
|
66
|
+
concurrencyLimits: args.concurrencyLimits,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
this.sandbox = args.sandbox;
|
|
70
|
+
this.apiKey = args.apiKey;
|
|
71
|
+
this.ownsSandbox = args.ownsSandbox ?? true;
|
|
72
|
+
this.ensureMountArtifactScope();
|
|
73
|
+
}
|
|
74
|
+
supportsPty() {
|
|
75
|
+
return Boolean(this.state.sandboxUrl && this.apiKey);
|
|
76
|
+
}
|
|
77
|
+
async writeStdin(args) {
|
|
78
|
+
return await (0, shared_1.writePtyStdin)({
|
|
79
|
+
providerName: 'BlaxelSandboxClient',
|
|
80
|
+
registry: this.ptyProcesses,
|
|
81
|
+
sessionId: args.sessionId,
|
|
82
|
+
chars: args.chars,
|
|
83
|
+
yieldTimeMs: args.yieldTimeMs,
|
|
84
|
+
maxOutputTokens: args.maxOutputTokens,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async execPtyCommand(args) {
|
|
88
|
+
(0, shared_1.assertRunAsUnsupported)('BlaxelSandboxClient', args.runAs);
|
|
89
|
+
if (!this.state.sandboxUrl || !this.apiKey) {
|
|
90
|
+
throw new sandbox_1.SandboxUnsupportedFeatureError('BlaxelSandboxClient tty=true requires a sandbox URL and apiKey.', {
|
|
91
|
+
provider: 'blaxel',
|
|
92
|
+
feature: 'tty',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const start = Date.now();
|
|
96
|
+
const entry = (0, shared_1.createPtyProcessEntry)({ tty: true });
|
|
97
|
+
const socket = await (0, shared_1.openPtyWebSocket)({
|
|
98
|
+
url: buildBlaxelPtyWebSocketUrl({
|
|
99
|
+
sandboxUrl: this.state.sandboxUrl,
|
|
100
|
+
token: this.apiKey,
|
|
101
|
+
sessionId: `pty-${Math.random().toString(16).slice(2, 14)}`,
|
|
102
|
+
cwd: (0, shared_1.resolveSandboxWorkdir)(this.state.manifest.root, args.workdir),
|
|
103
|
+
}),
|
|
104
|
+
providerName: 'BlaxelSandboxClient',
|
|
105
|
+
});
|
|
106
|
+
const removeMessageListener = (0, shared_1.addPtyWebSocketListener)(socket, 'message', (event) => handleBlaxelPtyMessage(entry, event));
|
|
107
|
+
const removeCloseListener = (0, shared_1.addPtyWebSocketListener)(socket, 'close', (event) => {
|
|
108
|
+
(0, shared_1.markPtyDone)(entry, blaxelPtyCloseExitCode(entry, event));
|
|
109
|
+
});
|
|
110
|
+
const removeErrorListener = (0, shared_1.addPtyWebSocketListener)(socket, 'error', () => {
|
|
111
|
+
(0, shared_1.markPtyDone)(entry, 1);
|
|
112
|
+
});
|
|
113
|
+
entry.sendInput = async (chars) => {
|
|
114
|
+
socket.send(JSON.stringify({ type: 'input', data: chars }));
|
|
115
|
+
};
|
|
116
|
+
entry.terminate = async () => {
|
|
117
|
+
removeMessageListener();
|
|
118
|
+
removeCloseListener();
|
|
119
|
+
removeErrorListener();
|
|
120
|
+
socket.close();
|
|
121
|
+
};
|
|
122
|
+
let registered = false;
|
|
123
|
+
try {
|
|
124
|
+
await entry.sendInput(`${(0, shared_1.shellCommandForPty)({
|
|
125
|
+
...args,
|
|
126
|
+
cmd: buildShellCommand(args.cmd, this.state.environment),
|
|
127
|
+
})}\n`);
|
|
128
|
+
const { sessionId, pruned } = this.ptyProcesses.register(entry);
|
|
129
|
+
registered = true;
|
|
130
|
+
if (pruned) {
|
|
131
|
+
await pruned.terminate?.().catch(() => { });
|
|
132
|
+
}
|
|
133
|
+
return await (0, shared_1.formatPtyExecUpdate)({
|
|
134
|
+
registry: this.ptyProcesses,
|
|
135
|
+
sessionId,
|
|
136
|
+
entry,
|
|
137
|
+
startTime: start,
|
|
138
|
+
yieldTimeMs: args.yieldTimeMs,
|
|
139
|
+
maxOutputTokens: args.maxOutputTokens,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
if (!registered) {
|
|
144
|
+
await entry.terminate?.().catch(() => { });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
allowOnDemandExposedPorts() {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
useCachedExposedPortEndpoint(_port) {
|
|
152
|
+
return this.state.exposedPortPublic !== false;
|
|
153
|
+
}
|
|
154
|
+
exposedPortSource() {
|
|
155
|
+
return 'preview URL';
|
|
156
|
+
}
|
|
157
|
+
async resolveRemoteExposedPort(requestedPort) {
|
|
158
|
+
if (!this.sandbox.previews?.createIfNotExists) {
|
|
159
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient exposed port resolution requires the Blaxel previews API.', {
|
|
160
|
+
provider: 'blaxel',
|
|
161
|
+
port: requestedPort,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
let preview;
|
|
165
|
+
try {
|
|
166
|
+
preview = await this.sandbox.previews.createIfNotExists({
|
|
167
|
+
metadata: { name: `port-${requestedPort}` },
|
|
168
|
+
spec: {
|
|
169
|
+
port: requestedPort,
|
|
170
|
+
public: this.state.exposedPortPublic ?? true,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
throw new sandbox_1.SandboxProviderError(`BlaxelSandboxClient failed to create a preview for exposed port ${requestedPort}.`, {
|
|
176
|
+
provider: 'blaxel',
|
|
177
|
+
port: requestedPort,
|
|
178
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
const url = extractBlaxelPreviewUrl(preview);
|
|
182
|
+
if (!url) {
|
|
183
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient preview did not include a URL.', {
|
|
184
|
+
provider: 'blaxel',
|
|
185
|
+
port: requestedPort,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const query = this.state.exposedPortPublic === false
|
|
189
|
+
? await createBlaxelPreviewTokenQuery(preview, this.state.exposedPortUrlTtlS ?? 3600, requestedPort)
|
|
190
|
+
: undefined;
|
|
191
|
+
return (0, shared_1.parseExposedPortEndpoint)(url, {
|
|
192
|
+
providerName: 'BlaxelSandboxClient',
|
|
193
|
+
source: 'preview URL',
|
|
194
|
+
query,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
async prepareWorkspaceRoot() {
|
|
198
|
+
const result = await this.sandbox.process.exec({
|
|
199
|
+
command: `mkdir -p -- ${(0, shared_1.shellQuote)(this.state.manifest.root)}`,
|
|
200
|
+
workingDir: '/',
|
|
201
|
+
waitForCompletion: true,
|
|
202
|
+
timeout: this.state.timeouts?.fastOperationTimeoutMs,
|
|
203
|
+
});
|
|
204
|
+
if ((result.exitCode ?? 1) !== 0) {
|
|
205
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient failed to prepare the workspace root.', {
|
|
206
|
+
provider: 'blaxel',
|
|
207
|
+
operation: 'prepare workspace root',
|
|
208
|
+
sandboxName: this.state.sandboxName,
|
|
209
|
+
root: this.state.manifest.root,
|
|
210
|
+
stderr: result.stderr ?? '',
|
|
211
|
+
stdout: result.stdout ?? '',
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async close() {
|
|
216
|
+
await this.ptyProcesses.terminateAll();
|
|
217
|
+
if (this.state.pauseOnExit || this.closed) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
await (0, shared_1.withSandboxSpan)('sandbox.shutdown', {
|
|
221
|
+
backend_id: 'blaxel',
|
|
222
|
+
sandbox_name: this.state.sandboxName,
|
|
223
|
+
}, async () => {
|
|
224
|
+
await this.unmountActiveMounts();
|
|
225
|
+
if (this.ownsSandbox) {
|
|
226
|
+
await this.sandbox.delete();
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
this.closed = true;
|
|
230
|
+
}
|
|
231
|
+
async shutdown() {
|
|
232
|
+
await this.close();
|
|
233
|
+
}
|
|
234
|
+
async delete() {
|
|
235
|
+
await this.ptyProcesses.terminateAll();
|
|
236
|
+
if (this.closed) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
await (0, shared_1.withSandboxSpan)('sandbox.shutdown', {
|
|
240
|
+
backend_id: 'blaxel',
|
|
241
|
+
sandbox_name: this.state.sandboxName,
|
|
242
|
+
}, async () => {
|
|
243
|
+
await this.unmountActiveMounts();
|
|
244
|
+
if (this.ownsSandbox) {
|
|
245
|
+
await this.sandbox.delete();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
this.closed = true;
|
|
249
|
+
}
|
|
250
|
+
async rehydrateActiveMountPathsFromManifest() {
|
|
251
|
+
for (const { logicalPath, entry, } of this.state.manifest.mountTargetsForMaterialization()) {
|
|
252
|
+
const mountPath = await this.resolveRemotePath(entry.mountPath ?? logicalPath, { forWrite: true });
|
|
253
|
+
if ((0, mounts_1.isBlaxelCloudBucketMountEntry)(entry)) {
|
|
254
|
+
this.activeFuseMountPaths.add(mountPath);
|
|
255
|
+
}
|
|
256
|
+
else if ((0, mounts_1.isBlaxelDriveMountEntry)(entry)) {
|
|
257
|
+
this.activeDriveMountPaths.add(mountPath);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
manifestMetadataSupport() {
|
|
262
|
+
return shared_1.SANDBOX_MANIFEST_METADATA_SUPPORT;
|
|
263
|
+
}
|
|
264
|
+
manifestMaterializationOptions() {
|
|
265
|
+
return {
|
|
266
|
+
materializeMount: this.materializeMountEntry.bind(this),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
assertExecRunAs(_runAs) {
|
|
270
|
+
void _runAs;
|
|
271
|
+
}
|
|
272
|
+
assertFilesystemRunAs(_runAs) {
|
|
273
|
+
void _runAs;
|
|
274
|
+
}
|
|
275
|
+
async materializeMountEntry(absolutePath, entry) {
|
|
276
|
+
const mountPath = await this.resolveRemotePath(entry.mountPath ?? absolutePath, { forWrite: true });
|
|
277
|
+
if (entry.mountStrategy?.type === 'blaxel_cloud_bucket') {
|
|
278
|
+
await (0, mounts_1.mountBlaxelCloudBucket)({
|
|
279
|
+
entry,
|
|
280
|
+
mountPath,
|
|
281
|
+
artifactScope: this.ensureMountArtifactScope(),
|
|
282
|
+
runCommand: this.mountCommandRunner(),
|
|
283
|
+
writeSecretFile: this.writeMountSecretFile.bind(this),
|
|
284
|
+
});
|
|
285
|
+
this.activeFuseMountPaths.add(mountPath);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (entry.mountStrategy?.type === 'blaxel_drive') {
|
|
289
|
+
const config = await (0, mounts_1.mountBlaxelDrive)({
|
|
290
|
+
entry,
|
|
291
|
+
mountPath,
|
|
292
|
+
drives: this.sandbox.drives,
|
|
293
|
+
});
|
|
294
|
+
this.activeDriveMountPaths.add(config.mountPath);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
throw new sandbox_1.SandboxUnsupportedFeatureError('BlaxelSandboxClient only supports BlaxelCloudBucketMountStrategy and BlaxelDriveMountStrategy mount entries.', {
|
|
298
|
+
provider: 'blaxel',
|
|
299
|
+
feature: 'entry.mountStrategy',
|
|
300
|
+
path: absolutePath,
|
|
301
|
+
mountType: entry.type,
|
|
302
|
+
strategyType: entry.mountStrategy?.type,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
async unmountActiveMounts() {
|
|
306
|
+
for (const mountPath of [...this.activeDriveMountPaths].reverse()) {
|
|
307
|
+
try {
|
|
308
|
+
await (0, mounts_1.unmountBlaxelDrive)({
|
|
309
|
+
mountPath,
|
|
310
|
+
drives: this.sandbox.drives,
|
|
311
|
+
});
|
|
312
|
+
this.activeDriveMountPaths.delete(mountPath);
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient failed to unmount an active drive mount.', {
|
|
316
|
+
provider: 'blaxel',
|
|
317
|
+
mountPath,
|
|
318
|
+
cause: unknownErrorMessage(error),
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
for (const mountPath of [...this.activeFuseMountPaths].reverse()) {
|
|
323
|
+
try {
|
|
324
|
+
await (0, mounts_1.unmountBlaxelFuseMount)({
|
|
325
|
+
mountPath,
|
|
326
|
+
artifactScope: this.ensureMountArtifactScope(),
|
|
327
|
+
runCommand: this.mountCommandRunner(),
|
|
328
|
+
});
|
|
329
|
+
this.activeFuseMountPaths.delete(mountPath);
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient failed to unmount an active FUSE mount.', {
|
|
333
|
+
provider: 'blaxel',
|
|
334
|
+
mountPath,
|
|
335
|
+
cause: unknownErrorMessage(error),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
mountCommandRunner() {
|
|
341
|
+
return async (command, options = {}) => {
|
|
342
|
+
const result = await this.sandbox.process.exec({
|
|
343
|
+
command,
|
|
344
|
+
workingDir: '/',
|
|
345
|
+
waitForCompletion: true,
|
|
346
|
+
timeout: options.timeoutMs ??
|
|
347
|
+
this.state.timeouts?.fastOperationTimeoutMs ??
|
|
348
|
+
this.state.timeoutMs,
|
|
349
|
+
});
|
|
350
|
+
return {
|
|
351
|
+
status: result.exitCode ?? 1,
|
|
352
|
+
stdout: result.stdout ?? '',
|
|
353
|
+
stderr: result.stderr ?? '',
|
|
354
|
+
};
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
async writeMountSecretFile(path, content) {
|
|
358
|
+
const operation = this.sandbox.fs.write(path, content);
|
|
359
|
+
await withBlaxelOperationTimeout(operation, this.state.timeouts?.fileUploadTimeoutMs, 'write mount secret', {
|
|
360
|
+
onTimeout: () => {
|
|
361
|
+
void operation.then(async () => {
|
|
362
|
+
await this.sandbox.fs.rm(path).catch(() => { });
|
|
363
|
+
}, () => { });
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
async runRemoteCommand(command, options) {
|
|
368
|
+
const shellCommand = buildShellCommand(command, this.state.environment);
|
|
369
|
+
const commandForUser = options.runAs
|
|
370
|
+
? `sudo -n -u ${(0, shared_1.shellQuote)(options.runAs)} -- sh -lc ${(0, shared_1.shellQuote)(shellCommand)}`
|
|
371
|
+
: shellCommand;
|
|
372
|
+
const result = await this.sandbox.process.exec({
|
|
373
|
+
command: commandForUser,
|
|
374
|
+
workingDir: options.workdir,
|
|
375
|
+
waitForCompletion: true,
|
|
376
|
+
timeout: this.timeoutForCommand(options),
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
status: result.exitCode ?? 1,
|
|
380
|
+
stdout: result.stdout ?? '',
|
|
381
|
+
stderr: result.stderr ?? '',
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async mkdirRemote(path) {
|
|
385
|
+
await this.sandbox.fs.mkdir(path);
|
|
386
|
+
}
|
|
387
|
+
async readRemoteText(path) {
|
|
388
|
+
return await withBlaxelOperationTimeout(this.sandbox.fs.read(path), this.state.timeouts?.fileDownloadTimeoutMs, 'read file');
|
|
389
|
+
}
|
|
390
|
+
async readRemoteFile(path) {
|
|
391
|
+
return await (0, shared_1.toUint8Array)(await withBlaxelOperationTimeout(this.sandbox.fs.readBinary(path), this.state.timeouts?.fileDownloadTimeoutMs, 'read binary file'));
|
|
392
|
+
}
|
|
393
|
+
async writeRemoteFile(path, content) {
|
|
394
|
+
const tempPath = remoteWriteTempPath(path);
|
|
395
|
+
if (typeof content === 'string') {
|
|
396
|
+
await this.writeRemoteTempFile(tempPath, this.sandbox.fs.write(tempPath, content), 'write file');
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
await this.writeRemoteTempFile(tempPath, this.sandbox.fs.writeBinary(tempPath, content), 'write binary file');
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const result = await this.sandbox.process.exec({
|
|
403
|
+
command: `mv -f -- ${(0, shared_1.shellQuote)(tempPath)} ${(0, shared_1.shellQuote)(path)}`,
|
|
404
|
+
workingDir: '/',
|
|
405
|
+
waitForCompletion: true,
|
|
406
|
+
timeout: this.state.timeouts?.fileUploadTimeoutMs,
|
|
407
|
+
});
|
|
408
|
+
if ((result.exitCode ?? 1) === 0) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient failed to commit uploaded file.', {
|
|
412
|
+
provider: 'blaxel',
|
|
413
|
+
operation: 'commit uploaded file',
|
|
414
|
+
path,
|
|
415
|
+
tempPath,
|
|
416
|
+
exitCode: result.exitCode ?? 1,
|
|
417
|
+
stdout: result.stdout ?? '',
|
|
418
|
+
stderr: result.stderr ?? '',
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
await this.sandbox.fs.rm(tempPath).catch(() => { });
|
|
423
|
+
throw error;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
async writeRemoteTempFile(tempPath, operation, operationName) {
|
|
427
|
+
await withBlaxelOperationTimeout(operation, this.state.timeouts?.fileUploadTimeoutMs, operationName, {
|
|
428
|
+
onTimeout: () => {
|
|
429
|
+
void operation.then(async () => {
|
|
430
|
+
await this.sandbox.fs.rm(tempPath).catch(() => { });
|
|
431
|
+
}, () => { });
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
async deleteRemotePath(path) {
|
|
436
|
+
await this.sandbox.fs.rm(path);
|
|
437
|
+
}
|
|
438
|
+
ensureMountArtifactScope() {
|
|
439
|
+
this.state.mountArtifactScope ??= (0, _shims_1.randomUUID)();
|
|
440
|
+
return this.state.mountArtifactScope;
|
|
441
|
+
}
|
|
442
|
+
timeoutForCommand(options) {
|
|
443
|
+
if (options.timeoutMs !== undefined) {
|
|
444
|
+
return options.timeoutMs;
|
|
445
|
+
}
|
|
446
|
+
if (options.kind === 'archive') {
|
|
447
|
+
return this.state.timeouts?.workspaceTarTimeoutMs ?? this.state.timeoutMs;
|
|
448
|
+
}
|
|
449
|
+
if (options.kind === 'exec') {
|
|
450
|
+
return this.state.timeouts?.execTimeoutMs ?? this.state.timeoutMs;
|
|
451
|
+
}
|
|
452
|
+
if (options.kind === 'path' || options.kind === 'running') {
|
|
453
|
+
return this.state.timeouts?.fastOperationTimeoutMs;
|
|
454
|
+
}
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
exports.BlaxelSandboxSession = BlaxelSandboxSession;
|
|
459
|
+
/**
|
|
460
|
+
* @see {@link https://docs.blaxel.ai/Sandboxes/Overview | Sandboxes overview}.
|
|
461
|
+
* @see {@link https://docs.blaxel.ai/Sandboxes/Filesystem | Filesystem operations}.
|
|
462
|
+
* @see {@link https://docs.blaxel.ai/Sandboxes/Sessions | Client-side sessions}.
|
|
463
|
+
*/
|
|
464
|
+
class BlaxelSandboxClient {
|
|
465
|
+
backendId = 'blaxel';
|
|
466
|
+
options;
|
|
467
|
+
constructor(options = {}) {
|
|
468
|
+
this.options = options;
|
|
469
|
+
}
|
|
470
|
+
async create(args, manifestOptions, internalOptions = {}) {
|
|
471
|
+
const createArgs = (0, sandbox_1.normalizeSandboxClientCreateArgs)(args, manifestOptions);
|
|
472
|
+
(0, shared_1.assertCoreSnapshotUnsupported)('BlaxelSandboxClient', createArgs.snapshot);
|
|
473
|
+
const manifest = createArgs.manifest;
|
|
474
|
+
const resolvedOptions = {
|
|
475
|
+
...this.options,
|
|
476
|
+
...createArgs.options,
|
|
477
|
+
};
|
|
478
|
+
const timeouts = resolveBlaxelTimeouts(resolvedOptions);
|
|
479
|
+
(0, shared_1.assertSandboxManifestMetadataSupported)('BlaxelSandboxClient', manifest, shared_1.SANDBOX_MANIFEST_METADATA_SUPPORT);
|
|
480
|
+
const SandboxInstance = await loadBlaxelSandboxClass();
|
|
481
|
+
return await (0, shared_1.withSandboxSpan)('sandbox.start', {
|
|
482
|
+
backend_id: this.backendId,
|
|
483
|
+
}, async () => {
|
|
484
|
+
const sandboxCreateParams = {
|
|
485
|
+
...(resolvedOptions.image ? { image: resolvedOptions.image } : {}),
|
|
486
|
+
...(typeof resolvedOptions.memory === 'number'
|
|
487
|
+
? { memory: resolvedOptions.memory }
|
|
488
|
+
: {}),
|
|
489
|
+
...(resolvedOptions.region ? { region: resolvedOptions.region } : {}),
|
|
490
|
+
...(resolvedOptions.ports ? { ports: resolvedOptions.ports } : {}),
|
|
491
|
+
...(typeof resolvedOptions.exposedPortPublic === 'boolean'
|
|
492
|
+
? { exposedPortPublic: resolvedOptions.exposedPortPublic }
|
|
493
|
+
: {}),
|
|
494
|
+
...(typeof resolvedOptions.exposedPortUrlTtlS === 'number'
|
|
495
|
+
? { exposedPortUrlTtlS: resolvedOptions.exposedPortUrlTtlS }
|
|
496
|
+
: {}),
|
|
497
|
+
...(typeof resolvedOptions.timeoutMs === 'number'
|
|
498
|
+
? { timeoutMs: resolvedOptions.timeoutMs }
|
|
499
|
+
: {}),
|
|
500
|
+
...(typeof timeouts.createTimeoutMs === 'number'
|
|
501
|
+
? { createTimeoutMs: timeouts.createTimeoutMs }
|
|
502
|
+
: {}),
|
|
503
|
+
...(resolvedOptions.labels ? { labels: resolvedOptions.labels } : {}),
|
|
504
|
+
...(resolvedOptions.ttl ? { ttl: resolvedOptions.ttl } : {}),
|
|
505
|
+
};
|
|
506
|
+
const { sandbox, ownsSandbox, sandboxName } = await (0, shared_1.withProviderError)('BlaxelSandboxClient', 'blaxel', 'create sandbox', async () => await createBlaxelSandboxWithOwnership({
|
|
507
|
+
SandboxInstance,
|
|
508
|
+
sandboxName: resolvedOptions.name,
|
|
509
|
+
allowExistingNamedSandbox: internalOptions.allowExistingNamedSandbox ?? true,
|
|
510
|
+
paramsForName: (sandboxName) => ({
|
|
511
|
+
name: sandboxName,
|
|
512
|
+
...sandboxCreateParams,
|
|
513
|
+
}),
|
|
514
|
+
}), { sandboxName: resolvedOptions.name });
|
|
515
|
+
let environment;
|
|
516
|
+
try {
|
|
517
|
+
environment = await (0, shared_1.materializeEnvironment)(manifest, resolvedOptions.env);
|
|
518
|
+
}
|
|
519
|
+
catch (error) {
|
|
520
|
+
if (ownsSandbox) {
|
|
521
|
+
try {
|
|
522
|
+
await sandbox.delete();
|
|
523
|
+
}
|
|
524
|
+
catch (deleteError) {
|
|
525
|
+
throw new agents_core_1.UserError(`Failed to materialize a Blaxel sandbox environment and delete the sandbox. Environment error: ${unknownErrorMessage(error)} Delete error: ${unknownErrorMessage(deleteError)}`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
const session = new BlaxelSandboxSession({
|
|
531
|
+
sandbox,
|
|
532
|
+
apiKey: resolvedOptions.apiKey ?? (0, _shims_1.loadEnv)().BL_API_KEY,
|
|
533
|
+
ownsSandbox,
|
|
534
|
+
concurrencyLimits: createArgs.concurrencyLimits,
|
|
535
|
+
state: {
|
|
536
|
+
manifest,
|
|
537
|
+
sandboxName,
|
|
538
|
+
image: resolvedOptions.image,
|
|
539
|
+
memory: resolvedOptions.memory,
|
|
540
|
+
region: resolvedOptions.region,
|
|
541
|
+
ports: resolvedOptions.ports,
|
|
542
|
+
exposedPortPublic: resolvedOptions.exposedPortPublic,
|
|
543
|
+
exposedPortUrlTtlS: resolvedOptions.exposedPortUrlTtlS,
|
|
544
|
+
timeoutMs: resolvedOptions.timeoutMs,
|
|
545
|
+
createTimeoutMs: timeouts.createTimeoutMs,
|
|
546
|
+
timeouts,
|
|
547
|
+
sandboxUrl: extractBlaxelSandboxUrl(sandbox),
|
|
548
|
+
sandboxIdentity: extractBlaxelSandboxIdentity(sandbox),
|
|
549
|
+
mountArtifactScope: (0, _shims_1.randomUUID)(),
|
|
550
|
+
labels: resolvedOptions.labels,
|
|
551
|
+
ttl: resolvedOptions.ttl,
|
|
552
|
+
pauseOnExit: resolvedOptions.pauseOnExit ?? false,
|
|
553
|
+
ownsSandbox,
|
|
554
|
+
environment,
|
|
555
|
+
},
|
|
556
|
+
});
|
|
557
|
+
try {
|
|
558
|
+
await session.prepareWorkspaceRoot();
|
|
559
|
+
await session.applyManifest(manifest);
|
|
560
|
+
}
|
|
561
|
+
catch (error) {
|
|
562
|
+
session.state.pauseOnExit = false;
|
|
563
|
+
await (0, shared_1.closeRemoteSessionOnManifestError)('Blaxel', session, error);
|
|
564
|
+
}
|
|
565
|
+
return session;
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
async serializeSessionState(state) {
|
|
569
|
+
return (0, shared_1.serializeRemoteSandboxSessionState)(state);
|
|
570
|
+
}
|
|
571
|
+
canPersistOwnedSessionState(state) {
|
|
572
|
+
return state.pauseOnExit && state.ownsSandbox && !!state.sandboxIdentity;
|
|
573
|
+
}
|
|
574
|
+
async deserializeSessionState(state) {
|
|
575
|
+
const baseState = (0, shared_1.deserializeRemoteSandboxSessionStateValues)(state, this.options.env);
|
|
576
|
+
return {
|
|
577
|
+
...state,
|
|
578
|
+
...baseState,
|
|
579
|
+
sandboxName: (0, shared_1.readString)(state, 'sandboxName'),
|
|
580
|
+
image: (0, shared_1.readOptionalString)(state, 'image'),
|
|
581
|
+
memory: (0, shared_1.readOptionalNumber)(state, 'memory'),
|
|
582
|
+
region: (0, shared_1.readOptionalString)(state, 'region'),
|
|
583
|
+
ports: (0, shared_1.readOptionalRecordArray)(state.ports),
|
|
584
|
+
exposedPortPublic: (0, shared_1.readOptionalBoolean)(state, 'exposedPortPublic'),
|
|
585
|
+
exposedPortUrlTtlS: (0, shared_1.readOptionalNumber)(state, 'exposedPortUrlTtlS'),
|
|
586
|
+
timeoutMs: (0, shared_1.readOptionalNumber)(state, 'timeoutMs'),
|
|
587
|
+
createTimeoutMs: (0, shared_1.readOptionalNumber)(state, 'createTimeoutMs'),
|
|
588
|
+
timeouts: resolveBlaxelTimeouts({
|
|
589
|
+
timeoutMs: (0, shared_1.readOptionalNumber)(state, 'timeoutMs'),
|
|
590
|
+
createTimeoutMs: (0, shared_1.readOptionalNumber)(state, 'createTimeoutMs'),
|
|
591
|
+
timeouts: (0, shared_1.isRecord)(state.timeouts)
|
|
592
|
+
? state.timeouts
|
|
593
|
+
: undefined,
|
|
594
|
+
}),
|
|
595
|
+
sandboxUrl: (0, shared_1.readOptionalString)(state, 'sandboxUrl'),
|
|
596
|
+
sandboxIdentity: (0, shared_1.readOptionalString)(state, 'sandboxIdentity'),
|
|
597
|
+
mountArtifactScope: (0, shared_1.readOptionalString)(state, 'mountArtifactScope') ?? (0, _shims_1.randomUUID)(),
|
|
598
|
+
labels: (0, shared_1.readOptionalStringRecord)(state.labels),
|
|
599
|
+
ttl: (0, shared_1.readOptionalString)(state, 'ttl'),
|
|
600
|
+
pauseOnExit: Boolean(state.pauseOnExit),
|
|
601
|
+
ownsSandbox: (0, shared_1.readOptionalBoolean)(state, 'ownsSandbox') ?? true,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
async resume(state) {
|
|
605
|
+
const SandboxInstance = await loadBlaxelSandboxClass();
|
|
606
|
+
let sandbox;
|
|
607
|
+
try {
|
|
608
|
+
sandbox = await SandboxInstance.get(state.sandboxName);
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
(0, shared_1.assertResumeRecreateAllowed)(error, {
|
|
612
|
+
providerName: 'BlaxelSandboxClient',
|
|
613
|
+
provider: 'blaxel',
|
|
614
|
+
details: { sandboxName: state.sandboxName },
|
|
615
|
+
});
|
|
616
|
+
return await this.recreateFromState(state);
|
|
617
|
+
}
|
|
618
|
+
if (isBlaxelSandboxNonResumable(sandbox)) {
|
|
619
|
+
return await this.recreateFromState(state);
|
|
620
|
+
}
|
|
621
|
+
if (state.ownsSandbox) {
|
|
622
|
+
assertBlaxelSandboxIdentityMatchesState(sandbox, state);
|
|
623
|
+
}
|
|
624
|
+
const sandboxUrl = extractBlaxelSandboxUrl(sandbox);
|
|
625
|
+
if (sandboxUrl) {
|
|
626
|
+
state.sandboxUrl = sandboxUrl;
|
|
627
|
+
}
|
|
628
|
+
const session = new BlaxelSandboxSession({
|
|
629
|
+
state,
|
|
630
|
+
sandbox,
|
|
631
|
+
apiKey: this.options.apiKey ?? (0, _shims_1.loadEnv)().BL_API_KEY,
|
|
632
|
+
ownsSandbox: state.ownsSandbox,
|
|
633
|
+
});
|
|
634
|
+
await session.rehydrateActiveMountPathsFromManifest();
|
|
635
|
+
return session;
|
|
636
|
+
}
|
|
637
|
+
async recreateFromState(state) {
|
|
638
|
+
const session = await this.create(state.manifest, {
|
|
639
|
+
image: state.image,
|
|
640
|
+
memory: state.memory,
|
|
641
|
+
region: state.region,
|
|
642
|
+
ports: state.ports,
|
|
643
|
+
exposedPortPublic: state.exposedPortPublic,
|
|
644
|
+
exposedPortUrlTtlS: state.exposedPortUrlTtlS,
|
|
645
|
+
timeoutMs: state.timeoutMs,
|
|
646
|
+
createTimeoutMs: state.createTimeoutMs,
|
|
647
|
+
timeouts: state.timeouts,
|
|
648
|
+
apiKey: this.options.apiKey,
|
|
649
|
+
labels: state.labels,
|
|
650
|
+
ttl: state.ttl,
|
|
651
|
+
name: state.sandboxName,
|
|
652
|
+
pauseOnExit: state.pauseOnExit,
|
|
653
|
+
env: state.environment,
|
|
654
|
+
}, {
|
|
655
|
+
allowExistingNamedSandbox: !state.ownsSandbox,
|
|
656
|
+
});
|
|
657
|
+
return session;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
exports.BlaxelSandboxClient = BlaxelSandboxClient;
|
|
661
|
+
async function loadBlaxelSandboxClass() {
|
|
662
|
+
try {
|
|
663
|
+
const { SandboxInstance } = await Promise.resolve().then(() => __importStar(require('@blaxel/core')));
|
|
664
|
+
if (!SandboxInstance) {
|
|
665
|
+
throw new Error('Missing SandboxInstance export from @blaxel/core.');
|
|
666
|
+
}
|
|
667
|
+
return adaptBlaxelSandboxClass(SandboxInstance);
|
|
668
|
+
}
|
|
669
|
+
catch (error) {
|
|
670
|
+
throw new agents_core_1.UserError(`Blaxel sandbox support requires the optional \`@blaxel/core\` package. Install it before using Blaxel-backed sandbox examples. ${error.message}`);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
async function createBlaxelSandboxWithOwnership(args) {
|
|
674
|
+
if (!args.sandboxName) {
|
|
675
|
+
return await createAutogeneratedBlaxelSandbox(args);
|
|
676
|
+
}
|
|
677
|
+
return await createNamedBlaxelSandboxWithOwnership({
|
|
678
|
+
SandboxInstance: args.SandboxInstance,
|
|
679
|
+
sandboxName: args.sandboxName,
|
|
680
|
+
allowExistingNamedSandbox: args.allowExistingNamedSandbox,
|
|
681
|
+
params: args.paramsForName(args.sandboxName),
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
async function createNamedBlaxelSandboxWithOwnership(args) {
|
|
685
|
+
try {
|
|
686
|
+
return {
|
|
687
|
+
sandbox: await args.SandboxInstance.create(args.params),
|
|
688
|
+
ownsSandbox: true,
|
|
689
|
+
sandboxName: args.sandboxName,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
if (!isBlaxelSandboxAlreadyExistsError(error)) {
|
|
694
|
+
throw error;
|
|
695
|
+
}
|
|
696
|
+
if (!args.allowExistingNamedSandbox) {
|
|
697
|
+
throw new agents_core_1.UserError(`Blaxel sandbox ${args.sandboxName} cannot be safely recreated because another sandbox already uses that name.`);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
const existing = await args.SandboxInstance.get(args.sandboxName);
|
|
701
|
+
if (!isBlaxelSandboxNonResumable(existing)) {
|
|
702
|
+
return {
|
|
703
|
+
sandbox: existing,
|
|
704
|
+
ownsSandbox: false,
|
|
705
|
+
sandboxName: args.sandboxName,
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
try {
|
|
709
|
+
return {
|
|
710
|
+
sandbox: await args.SandboxInstance.create(args.params),
|
|
711
|
+
ownsSandbox: true,
|
|
712
|
+
sandboxName: args.sandboxName,
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
catch (error) {
|
|
716
|
+
if (!isBlaxelSandboxAlreadyExistsError(error)) {
|
|
717
|
+
throw error;
|
|
718
|
+
}
|
|
719
|
+
if (!args.allowExistingNamedSandbox) {
|
|
720
|
+
throw new agents_core_1.UserError(`Blaxel sandbox ${args.sandboxName} cannot be safely recreated because another sandbox already uses that name.`);
|
|
721
|
+
}
|
|
722
|
+
const fallback = await args.SandboxInstance.get(args.sandboxName);
|
|
723
|
+
assertBlaxelSandboxReusable(fallback, args.sandboxName);
|
|
724
|
+
return {
|
|
725
|
+
sandbox: fallback,
|
|
726
|
+
ownsSandbox: false,
|
|
727
|
+
sandboxName: args.sandboxName,
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
async function createAutogeneratedBlaxelSandbox(args) {
|
|
732
|
+
let lastConflict;
|
|
733
|
+
for (let attempt = 0; attempt < BLAXEL_AUTOGENERATED_NAME_CREATE_ATTEMPTS; attempt += 1) {
|
|
734
|
+
const sandboxName = generateBlaxelSandboxName();
|
|
735
|
+
try {
|
|
736
|
+
return {
|
|
737
|
+
sandbox: await args.SandboxInstance.create(args.paramsForName(sandboxName)),
|
|
738
|
+
ownsSandbox: true,
|
|
739
|
+
sandboxName,
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
catch (error) {
|
|
743
|
+
if (!isBlaxelSandboxAlreadyExistsError(error)) {
|
|
744
|
+
throw error;
|
|
745
|
+
}
|
|
746
|
+
lastConflict = error;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
throw lastConflict;
|
|
750
|
+
}
|
|
751
|
+
function generateBlaxelSandboxName() {
|
|
752
|
+
return `openai-agents-${Math.random().toString(16).slice(2, 10)}`;
|
|
753
|
+
}
|
|
754
|
+
function isBlaxelSandboxNonResumable(sandbox) {
|
|
755
|
+
const status = sandbox.status?.trim().toUpperCase();
|
|
756
|
+
return status ? BLAXEL_NON_RESUMABLE_SANDBOX_STATUSES.has(status) : false;
|
|
757
|
+
}
|
|
758
|
+
function assertBlaxelSandboxReusable(sandbox, sandboxName) {
|
|
759
|
+
if (!isBlaxelSandboxNonResumable(sandbox)) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
throw new agents_core_1.UserError(`Blaxel sandbox ${sandboxName} cannot be safely reused because its status is ${sandbox.status ?? 'unknown'}.`);
|
|
763
|
+
}
|
|
764
|
+
function assertBlaxelSandboxIdentityMatchesState(sandbox, state) {
|
|
765
|
+
const identity = extractBlaxelSandboxIdentity(sandbox);
|
|
766
|
+
if (identity && identity === state.sandboxIdentity) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
throw new agents_core_1.UserError(`Blaxel sandbox ${state.sandboxName} cannot be safely resumed with ownership because its identity could not be verified.`);
|
|
770
|
+
}
|
|
771
|
+
function extractBlaxelSandboxIdentity(sandbox) {
|
|
772
|
+
const metadata = sandbox.metadata;
|
|
773
|
+
if (!(0, shared_1.isRecord)(metadata)) {
|
|
774
|
+
return undefined;
|
|
775
|
+
}
|
|
776
|
+
const name = readMetadataString(metadata, 'name');
|
|
777
|
+
const createdAt = readMetadataString(metadata, 'createdAt');
|
|
778
|
+
if (!name || !createdAt) {
|
|
779
|
+
return undefined;
|
|
780
|
+
}
|
|
781
|
+
return JSON.stringify({
|
|
782
|
+
name,
|
|
783
|
+
createdAt,
|
|
784
|
+
workspace: readMetadataString(metadata, 'workspace') ?? null,
|
|
785
|
+
createdBy: readMetadataString(metadata, 'createdBy') ?? null,
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
function readMetadataString(metadata, key) {
|
|
789
|
+
const value = metadata[key];
|
|
790
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
791
|
+
}
|
|
792
|
+
function isBlaxelSandboxAlreadyExistsError(error) {
|
|
793
|
+
if ((0, shared_1.isRecord)(error)) {
|
|
794
|
+
if (isConflictValue(error.code)) {
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
const response = error.response;
|
|
798
|
+
if ((0, shared_1.isRecord)(response) && isConflictValue(response.status)) {
|
|
799
|
+
return true;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return /\b(409|already exists|SANDBOX_ALREADY_EXISTS)\b/iu.test(unknownErrorMessage(error));
|
|
803
|
+
}
|
|
804
|
+
function isConflictValue(value) {
|
|
805
|
+
if (value === 409 || value === '409') {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
return (typeof value === 'string' &&
|
|
809
|
+
value.trim().toUpperCase() === 'SANDBOX_ALREADY_EXISTS');
|
|
810
|
+
}
|
|
811
|
+
function adaptBlaxelSandboxClass(SandboxInstance) {
|
|
812
|
+
return {
|
|
813
|
+
create: async (params) => adaptBlaxelSandbox(await SandboxInstance.create(params)),
|
|
814
|
+
get: async (name) => adaptBlaxelSandbox(await SandboxInstance.get(name)),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
function adaptBlaxelSandbox(sandbox) {
|
|
818
|
+
const sandboxUrl = extractBlaxelSandboxUrl(sandbox);
|
|
819
|
+
const previews = adaptBlaxelPreviewApi(sandbox.previews);
|
|
820
|
+
return {
|
|
821
|
+
metadata: sandbox.metadata,
|
|
822
|
+
url: sandboxUrl,
|
|
823
|
+
status: typeof sandbox.status === 'string' ? sandbox.status : undefined,
|
|
824
|
+
...(sandboxUrl ? { sandbox: { metadata: { url: sandboxUrl } } } : {}),
|
|
825
|
+
process: {
|
|
826
|
+
exec: async (params) => await sandbox.process.exec(params),
|
|
827
|
+
},
|
|
828
|
+
fs: {
|
|
829
|
+
mkdir: async (path) => {
|
|
830
|
+
await sandbox.fs.mkdir(path);
|
|
831
|
+
},
|
|
832
|
+
write: async (path, content) => {
|
|
833
|
+
await sandbox.fs.write(path, content);
|
|
834
|
+
},
|
|
835
|
+
writeBinary: async (path, content) => {
|
|
836
|
+
await sandbox.fs.writeBinary(path, content);
|
|
837
|
+
},
|
|
838
|
+
read: async (path) => await sandbox.fs.read(path),
|
|
839
|
+
readBinary: async (path) => await sandbox.fs.readBinary(path),
|
|
840
|
+
rm: async (path, recursive) => {
|
|
841
|
+
await sandbox.fs.rm(path, recursive);
|
|
842
|
+
},
|
|
843
|
+
},
|
|
844
|
+
...(previews ? { previews } : {}),
|
|
845
|
+
drives: adaptBlaxelDriveApi(sandbox.drives),
|
|
846
|
+
delete: async () => {
|
|
847
|
+
await sandbox.delete();
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function adaptBlaxelPreviewApi(previews) {
|
|
852
|
+
if (!(0, shared_1.isRecord)(previews)) {
|
|
853
|
+
return undefined;
|
|
854
|
+
}
|
|
855
|
+
const createIfNotExists = previews.createIfNotExists;
|
|
856
|
+
if (typeof createIfNotExists !== 'function') {
|
|
857
|
+
return undefined;
|
|
858
|
+
}
|
|
859
|
+
return {
|
|
860
|
+
createIfNotExists: async (params) => await createIfNotExists.call(previews, params),
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
function adaptBlaxelDriveApi(drives) {
|
|
864
|
+
if (!(0, shared_1.isRecord)(drives)) {
|
|
865
|
+
return undefined;
|
|
866
|
+
}
|
|
867
|
+
const mount = drives.mount;
|
|
868
|
+
if (typeof mount !== 'function') {
|
|
869
|
+
return undefined;
|
|
870
|
+
}
|
|
871
|
+
const unmount = drives.unmount;
|
|
872
|
+
if (!('list' in drives)) {
|
|
873
|
+
return {
|
|
874
|
+
mount: async (driveName, mountPath, drivePath, readOnly) => await mount.call(drives, driveName, mountPath, drivePath, readOnly),
|
|
875
|
+
unmount: async (mountPath) => typeof unmount === 'function'
|
|
876
|
+
? await unmount.call(drives, mountPath)
|
|
877
|
+
: undefined,
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
const sdkDrives = drives;
|
|
881
|
+
return {
|
|
882
|
+
mount: async (driveName, mountPath, drivePath, readOnly) => await mount.call(sdkDrives, {
|
|
883
|
+
driveName,
|
|
884
|
+
mountPath,
|
|
885
|
+
...(drivePath ? { drivePath } : {}),
|
|
886
|
+
readOnly,
|
|
887
|
+
}),
|
|
888
|
+
unmount: async (mountPath) => typeof unmount === 'function'
|
|
889
|
+
? await unmount.call(sdkDrives, mountPath)
|
|
890
|
+
: undefined,
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
function unknownErrorMessage(error) {
|
|
894
|
+
return error instanceof Error ? error.message : String(error);
|
|
895
|
+
}
|
|
896
|
+
function buildShellCommand(command, environment) {
|
|
897
|
+
const exports = Object.entries(environment).map(([key, value]) => {
|
|
898
|
+
(0, shared_1.assertShellEnvironmentName)(key);
|
|
899
|
+
return `export ${key}=${(0, shared_1.shellQuote)(value)}`;
|
|
900
|
+
});
|
|
901
|
+
if (exports.length === 0) {
|
|
902
|
+
return command;
|
|
903
|
+
}
|
|
904
|
+
return [...exports, command].join(' && ');
|
|
905
|
+
}
|
|
906
|
+
function remoteWriteTempPath(path) {
|
|
907
|
+
const dir = (0, shared_1.posixDirname)(path);
|
|
908
|
+
const prefix = dir === '/' ? '' : dir;
|
|
909
|
+
return `${prefix}/.openai-agents-write-${(0, _shims_1.randomUUID)()}`;
|
|
910
|
+
}
|
|
911
|
+
function resolveBlaxelTimeouts(options) {
|
|
912
|
+
return {
|
|
913
|
+
...options.timeouts,
|
|
914
|
+
execTimeoutMs: options.timeouts?.execTimeoutMs ?? options.timeoutMs,
|
|
915
|
+
createTimeoutMs: options.timeouts?.createTimeoutMs ?? options.createTimeoutMs,
|
|
916
|
+
workspaceTarTimeoutMs: options.timeouts?.workspaceTarTimeoutMs ?? options.timeoutMs,
|
|
917
|
+
fastOperationTimeoutMs: options.timeouts?.fastOperationTimeoutMs ?? options.timeoutMs,
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
async function withBlaxelOperationTimeout(operation, timeoutMs, operationName, options = {}) {
|
|
921
|
+
if (typeof timeoutMs !== 'number') {
|
|
922
|
+
return await operation;
|
|
923
|
+
}
|
|
924
|
+
let timeoutId;
|
|
925
|
+
const timeout = new Promise((_, reject) => {
|
|
926
|
+
timeoutId = setTimeout(() => {
|
|
927
|
+
options.onTimeout?.();
|
|
928
|
+
reject(new sandbox_1.SandboxProviderError(`BlaxelSandboxClient ${operationName} timed out after ${timeoutMs}ms.`, {
|
|
929
|
+
provider: 'blaxel',
|
|
930
|
+
operation: operationName,
|
|
931
|
+
timeoutMs,
|
|
932
|
+
}));
|
|
933
|
+
}, timeoutMs);
|
|
934
|
+
});
|
|
935
|
+
try {
|
|
936
|
+
return await Promise.race([operation, timeout]);
|
|
937
|
+
}
|
|
938
|
+
finally {
|
|
939
|
+
if (timeoutId) {
|
|
940
|
+
clearTimeout(timeoutId);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
function extractBlaxelSandboxUrl(sandbox) {
|
|
945
|
+
if (!(0, shared_1.isRecord)(sandbox)) {
|
|
946
|
+
return undefined;
|
|
947
|
+
}
|
|
948
|
+
const directUrl = sandbox.url;
|
|
949
|
+
if (typeof directUrl === 'string') {
|
|
950
|
+
return directUrl;
|
|
951
|
+
}
|
|
952
|
+
const nestedSandbox = sandbox.sandbox;
|
|
953
|
+
if (!(0, shared_1.isRecord)(nestedSandbox)) {
|
|
954
|
+
return undefined;
|
|
955
|
+
}
|
|
956
|
+
const metadata = nestedSandbox.metadata;
|
|
957
|
+
if (!(0, shared_1.isRecord)(metadata) || typeof metadata.url !== 'string') {
|
|
958
|
+
return undefined;
|
|
959
|
+
}
|
|
960
|
+
return metadata.url;
|
|
961
|
+
}
|
|
962
|
+
function buildBlaxelPtyWebSocketUrl(args) {
|
|
963
|
+
const base = args.sandboxUrl.replace(/\/$/u, '');
|
|
964
|
+
const wsBase = base.replace(/^https:/u, 'wss:').replace(/^http:/u, 'ws:');
|
|
965
|
+
const params = new URLSearchParams({
|
|
966
|
+
token: args.token,
|
|
967
|
+
cols: String(args.cols ?? 80),
|
|
968
|
+
rows: String(args.rows ?? 24),
|
|
969
|
+
sessionId: args.sessionId,
|
|
970
|
+
workingDir: args.cwd,
|
|
971
|
+
});
|
|
972
|
+
return `${wsBase}/terminal/ws?${params.toString()}`;
|
|
973
|
+
}
|
|
974
|
+
function handleBlaxelPtyMessage(entry, event) {
|
|
975
|
+
const text = webSocketEventText(event);
|
|
976
|
+
if (!text) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
let payload;
|
|
980
|
+
try {
|
|
981
|
+
payload = JSON.parse(text);
|
|
982
|
+
}
|
|
983
|
+
catch {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
if (!(0, shared_1.isRecord)(payload)) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const type = payload.type ?? payload.Type;
|
|
990
|
+
if (type === 'output') {
|
|
991
|
+
const data = payload.data ?? payload.Data;
|
|
992
|
+
if (typeof data === 'string') {
|
|
993
|
+
(0, shared_1.appendPtyOutput)(entry, data);
|
|
994
|
+
}
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (type === 'error') {
|
|
998
|
+
const data = payload.data ?? payload.Data;
|
|
999
|
+
if (typeof data === 'string') {
|
|
1000
|
+
(0, shared_1.appendPtyOutput)(entry, data);
|
|
1001
|
+
}
|
|
1002
|
+
(0, shared_1.markPtyDone)(entry, 1);
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
function blaxelPtyCloseExitCode(entry, event) {
|
|
1006
|
+
if (entry.exitCode !== null) {
|
|
1007
|
+
return entry.exitCode;
|
|
1008
|
+
}
|
|
1009
|
+
return webSocketCloseCode(event) === 1000 ? 0 : 1;
|
|
1010
|
+
}
|
|
1011
|
+
function webSocketCloseCode(event) {
|
|
1012
|
+
if (typeof event === 'number') {
|
|
1013
|
+
return event;
|
|
1014
|
+
}
|
|
1015
|
+
if (!(0, shared_1.isRecord)(event)) {
|
|
1016
|
+
return undefined;
|
|
1017
|
+
}
|
|
1018
|
+
const code = event.code ?? event.data;
|
|
1019
|
+
return typeof code === 'number' ? code : undefined;
|
|
1020
|
+
}
|
|
1021
|
+
function extractBlaxelPreviewUrl(preview) {
|
|
1022
|
+
if (!(0, shared_1.isRecord)(preview)) {
|
|
1023
|
+
return undefined;
|
|
1024
|
+
}
|
|
1025
|
+
for (const nested of ['spec', 'status']) {
|
|
1026
|
+
const value = preview[nested];
|
|
1027
|
+
if ((0, shared_1.isRecord)(value) && typeof value.url === 'string' && value.url) {
|
|
1028
|
+
return value.url;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
for (const key of ['url', 'endpoint']) {
|
|
1032
|
+
const value = preview[key];
|
|
1033
|
+
if (typeof value === 'string' && value) {
|
|
1034
|
+
return value;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return extractBlaxelPreviewUrl(preview.preview);
|
|
1038
|
+
}
|
|
1039
|
+
async function createBlaxelPreviewTokenQuery(preview, ttlSeconds, port) {
|
|
1040
|
+
const tokens = findBlaxelPreviewTokens(preview);
|
|
1041
|
+
if (!tokens) {
|
|
1042
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient private previews require a preview token API.', {
|
|
1043
|
+
provider: 'blaxel',
|
|
1044
|
+
port,
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
const createToken = tokens.create;
|
|
1048
|
+
if (typeof createToken !== 'function') {
|
|
1049
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient private previews require tokens.create().', {
|
|
1050
|
+
provider: 'blaxel',
|
|
1051
|
+
port,
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
let token;
|
|
1055
|
+
try {
|
|
1056
|
+
token = await createToken.call(tokens, new Date(Date.now() + Math.max(1, ttlSeconds) * 1000));
|
|
1057
|
+
}
|
|
1058
|
+
catch (error) {
|
|
1059
|
+
throw new sandbox_1.SandboxProviderError(`BlaxelSandboxClient failed to create a private preview token for port ${port}.`, {
|
|
1060
|
+
provider: 'blaxel',
|
|
1061
|
+
port,
|
|
1062
|
+
cause: error instanceof Error ? error.message : String(error),
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
const tokenValue = typeof token === 'string'
|
|
1066
|
+
? token
|
|
1067
|
+
: (0, shared_1.isRecord)(token) && typeof token.value === 'string'
|
|
1068
|
+
? token.value
|
|
1069
|
+
: (0, shared_1.isRecord)(token) && typeof token.token === 'string'
|
|
1070
|
+
? token.token
|
|
1071
|
+
: undefined;
|
|
1072
|
+
if (!tokenValue) {
|
|
1073
|
+
throw new sandbox_1.SandboxProviderError('BlaxelSandboxClient private preview token response did not include a token value.', {
|
|
1074
|
+
provider: 'blaxel',
|
|
1075
|
+
port,
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
return new URLSearchParams({
|
|
1079
|
+
bl_preview_token: tokenValue,
|
|
1080
|
+
}).toString();
|
|
1081
|
+
}
|
|
1082
|
+
function findBlaxelPreviewTokens(preview, seen = new Set()) {
|
|
1083
|
+
if (!(0, shared_1.isRecord)(preview)) {
|
|
1084
|
+
return undefined;
|
|
1085
|
+
}
|
|
1086
|
+
if (seen.has(preview)) {
|
|
1087
|
+
return undefined;
|
|
1088
|
+
}
|
|
1089
|
+
seen.add(preview);
|
|
1090
|
+
if ((0, shared_1.isRecord)(preview.tokens)) {
|
|
1091
|
+
return preview.tokens;
|
|
1092
|
+
}
|
|
1093
|
+
return findBlaxelPreviewTokens(preview.preview, seen);
|
|
1094
|
+
}
|
|
1095
|
+
function webSocketEventText(event) {
|
|
1096
|
+
const data = event && typeof event === 'object' && 'data' in event
|
|
1097
|
+
? event.data
|
|
1098
|
+
: event;
|
|
1099
|
+
if (typeof data === 'string') {
|
|
1100
|
+
return data;
|
|
1101
|
+
}
|
|
1102
|
+
if (data instanceof ArrayBuffer) {
|
|
1103
|
+
return new TextDecoder().decode(data);
|
|
1104
|
+
}
|
|
1105
|
+
if (ArrayBuffer.isView(data)) {
|
|
1106
|
+
return new TextDecoder().decode(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
1107
|
+
}
|
|
1108
|
+
return undefined;
|
|
1109
|
+
}
|
|
1110
|
+
//# sourceMappingURL=sandbox.js.map
|