@ai-sdk/sandbox-vercel 0.0.0 → 1.0.0-beta.14
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/CHANGELOG.md +109 -0
- package/LICENSE +13 -0
- package/README.md +76 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +474 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -1
- package/src/index.ts +5 -0
- package/src/vercel-network-sandbox-session.ts +132 -0
- package/src/vercel-sandbox-session.ts +299 -0
- package/src/vercel-sandbox.ts +288 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
// src/vercel-sandbox.ts
|
|
2
|
+
import { Sandbox } from "@vercel/sandbox";
|
|
3
|
+
|
|
4
|
+
// src/vercel-network-sandbox-session.ts
|
|
5
|
+
import {
|
|
6
|
+
HarnessCapabilityUnsupportedError
|
|
7
|
+
} from "@ai-sdk/harness";
|
|
8
|
+
|
|
9
|
+
// src/vercel-sandbox-session.ts
|
|
10
|
+
import { posix } from "path";
|
|
11
|
+
import {
|
|
12
|
+
extractLines
|
|
13
|
+
} from "@ai-sdk/provider-utils";
|
|
14
|
+
var VercelSandboxSession = class {
|
|
15
|
+
constructor(sandbox) {
|
|
16
|
+
this.sandbox = sandbox;
|
|
17
|
+
}
|
|
18
|
+
get description() {
|
|
19
|
+
return [
|
|
20
|
+
`Vercel Sandbox (name: ${this.sandbox.name}).`,
|
|
21
|
+
"Filesystem changes persist for the lifetime of the sandbox."
|
|
22
|
+
].join("\n");
|
|
23
|
+
}
|
|
24
|
+
async run({
|
|
25
|
+
command,
|
|
26
|
+
workingDirectory,
|
|
27
|
+
env,
|
|
28
|
+
abortSignal
|
|
29
|
+
}) {
|
|
30
|
+
abortSignal == null ? void 0 : abortSignal.throwIfAborted();
|
|
31
|
+
const finished = await this.sandbox.runCommand({
|
|
32
|
+
cmd: "bash",
|
|
33
|
+
args: ["-c", command],
|
|
34
|
+
...workingDirectory !== void 0 ? { cwd: workingDirectory } : {},
|
|
35
|
+
...env !== void 0 ? { env } : {},
|
|
36
|
+
...abortSignal !== void 0 ? { signal: abortSignal } : {}
|
|
37
|
+
});
|
|
38
|
+
const [stdout, stderr] = await Promise.all([
|
|
39
|
+
finished.stdout(),
|
|
40
|
+
finished.stderr()
|
|
41
|
+
]);
|
|
42
|
+
return {
|
|
43
|
+
exitCode: finished.exitCode,
|
|
44
|
+
stdout,
|
|
45
|
+
stderr
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async spawn({
|
|
49
|
+
command,
|
|
50
|
+
workingDirectory,
|
|
51
|
+
env,
|
|
52
|
+
abortSignal
|
|
53
|
+
}) {
|
|
54
|
+
abortSignal == null ? void 0 : abortSignal.throwIfAborted();
|
|
55
|
+
const live = await this.sandbox.runCommand({
|
|
56
|
+
cmd: "bash",
|
|
57
|
+
args: ["-c", command],
|
|
58
|
+
detached: true,
|
|
59
|
+
...workingDirectory !== void 0 ? { cwd: workingDirectory } : {},
|
|
60
|
+
...env !== void 0 ? { env } : {},
|
|
61
|
+
...abortSignal !== void 0 ? { signal: abortSignal } : {}
|
|
62
|
+
});
|
|
63
|
+
return createSandboxProcess(live, abortSignal);
|
|
64
|
+
}
|
|
65
|
+
async readFile({
|
|
66
|
+
path,
|
|
67
|
+
abortSignal
|
|
68
|
+
}) {
|
|
69
|
+
const bytes = await this.readBinaryFile({ path, abortSignal });
|
|
70
|
+
if (bytes == null) return null;
|
|
71
|
+
return bytesToStream(bytes);
|
|
72
|
+
}
|
|
73
|
+
async readBinaryFile({
|
|
74
|
+
path,
|
|
75
|
+
abortSignal
|
|
76
|
+
}) {
|
|
77
|
+
abortSignal == null ? void 0 : abortSignal.throwIfAborted();
|
|
78
|
+
try {
|
|
79
|
+
const buffer = await this.sandbox.readFileToBuffer(
|
|
80
|
+
{ path },
|
|
81
|
+
abortSignal ? { signal: abortSignal } : void 0
|
|
82
|
+
);
|
|
83
|
+
if (buffer == null) return null;
|
|
84
|
+
return new Uint8Array(
|
|
85
|
+
buffer.buffer,
|
|
86
|
+
buffer.byteOffset,
|
|
87
|
+
buffer.byteLength
|
|
88
|
+
);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (isFileNotFoundError(error)) return null;
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async readTextFile({
|
|
95
|
+
path,
|
|
96
|
+
encoding = "utf-8",
|
|
97
|
+
startLine,
|
|
98
|
+
endLine,
|
|
99
|
+
abortSignal
|
|
100
|
+
}) {
|
|
101
|
+
const bytes = await this.readBinaryFile({ path, abortSignal });
|
|
102
|
+
if (bytes == null) return null;
|
|
103
|
+
const text = Buffer.from(bytes).toString(encoding);
|
|
104
|
+
return extractLines({ text, startLine, endLine });
|
|
105
|
+
}
|
|
106
|
+
async writeFile({
|
|
107
|
+
path,
|
|
108
|
+
content,
|
|
109
|
+
abortSignal
|
|
110
|
+
}) {
|
|
111
|
+
const bytes = await collectStream(content);
|
|
112
|
+
await this.writeBinaryFile({ path, content: bytes, abortSignal });
|
|
113
|
+
}
|
|
114
|
+
async writeBinaryFile({
|
|
115
|
+
path,
|
|
116
|
+
content,
|
|
117
|
+
abortSignal
|
|
118
|
+
}) {
|
|
119
|
+
abortSignal == null ? void 0 : abortSignal.throwIfAborted();
|
|
120
|
+
const parent = posix.dirname(path);
|
|
121
|
+
if (parent && parent !== "." && parent !== "/") {
|
|
122
|
+
await this.sandbox.runCommand({
|
|
123
|
+
cmd: "mkdir",
|
|
124
|
+
args: ["-p", parent],
|
|
125
|
+
...abortSignal !== void 0 ? { signal: abortSignal } : {}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
await this.sandbox.writeFiles(
|
|
129
|
+
[{ path, content }],
|
|
130
|
+
abortSignal ? { signal: abortSignal } : void 0
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
async writeTextFile({
|
|
134
|
+
path,
|
|
135
|
+
content,
|
|
136
|
+
encoding = "utf-8",
|
|
137
|
+
abortSignal
|
|
138
|
+
}) {
|
|
139
|
+
const buffer = Buffer.from(content, encoding);
|
|
140
|
+
await this.writeBinaryFile({
|
|
141
|
+
path,
|
|
142
|
+
content: new Uint8Array(
|
|
143
|
+
buffer.buffer,
|
|
144
|
+
buffer.byteOffset,
|
|
145
|
+
buffer.byteLength
|
|
146
|
+
),
|
|
147
|
+
abortSignal
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
function createSandboxProcess(command, abortSignal) {
|
|
152
|
+
const encoder = new TextEncoder();
|
|
153
|
+
const controllers = {};
|
|
154
|
+
const stdout = new ReadableStream({
|
|
155
|
+
start(controller) {
|
|
156
|
+
controllers.stdout = controller;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
const stderr = new ReadableStream({
|
|
160
|
+
start(controller) {
|
|
161
|
+
controllers.stderr = controller;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const drained = (async () => {
|
|
165
|
+
var _a, _b, _c, _d;
|
|
166
|
+
try {
|
|
167
|
+
const iterator = abortSignal ? command.logs({ signal: abortSignal }) : command.logs();
|
|
168
|
+
for await (const message of iterator) {
|
|
169
|
+
const target = message.stream === "stdout" ? controllers.stdout : controllers.stderr;
|
|
170
|
+
target == null ? void 0 : target.enqueue(encoder.encode(message.data));
|
|
171
|
+
}
|
|
172
|
+
(_a = controllers.stdout) == null ? void 0 : _a.close();
|
|
173
|
+
(_b = controllers.stderr) == null ? void 0 : _b.close();
|
|
174
|
+
} catch (error) {
|
|
175
|
+
(_c = controllers.stdout) == null ? void 0 : _c.error(error);
|
|
176
|
+
(_d = controllers.stderr) == null ? void 0 : _d.error(error);
|
|
177
|
+
}
|
|
178
|
+
})();
|
|
179
|
+
return {
|
|
180
|
+
stdout,
|
|
181
|
+
stderr,
|
|
182
|
+
async wait() {
|
|
183
|
+
var _a;
|
|
184
|
+
const finished = await command.wait();
|
|
185
|
+
await drained;
|
|
186
|
+
if (abortSignal == null ? void 0 : abortSignal.aborted) {
|
|
187
|
+
throw (_a = abortSignal.reason) != null ? _a : new DOMException("Aborted", "AbortError");
|
|
188
|
+
}
|
|
189
|
+
return { exitCode: finished.exitCode };
|
|
190
|
+
},
|
|
191
|
+
async kill() {
|
|
192
|
+
await command.kill();
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function bytesToStream(bytes) {
|
|
197
|
+
return new ReadableStream({
|
|
198
|
+
start(controller) {
|
|
199
|
+
controller.enqueue(bytes);
|
|
200
|
+
controller.close();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function collectStream(stream) {
|
|
205
|
+
const reader = stream.getReader();
|
|
206
|
+
const chunks = [];
|
|
207
|
+
let total = 0;
|
|
208
|
+
while (true) {
|
|
209
|
+
const { value, done } = await reader.read();
|
|
210
|
+
if (done) break;
|
|
211
|
+
if (value) {
|
|
212
|
+
chunks.push(value);
|
|
213
|
+
total += value.byteLength;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const out = new Uint8Array(total);
|
|
217
|
+
let offset = 0;
|
|
218
|
+
for (const chunk of chunks) {
|
|
219
|
+
out.set(chunk, offset);
|
|
220
|
+
offset += chunk.byteLength;
|
|
221
|
+
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
function isFileNotFoundError(error) {
|
|
225
|
+
if (error == null || typeof error !== "object") return false;
|
|
226
|
+
const code = error.code;
|
|
227
|
+
if (code === "ENOENT") return true;
|
|
228
|
+
const message = error.message;
|
|
229
|
+
return typeof message === "string" && /no such file|not found|does not exist|ENOENT/i.test(message);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/vercel-network-sandbox-session.ts
|
|
233
|
+
var VERCEL_PROVIDER_ID = "vercel-sandbox";
|
|
234
|
+
var VercelNetworkSandboxSession = class extends VercelSandboxSession {
|
|
235
|
+
constructor(input) {
|
|
236
|
+
super(input.sandbox);
|
|
237
|
+
this.getPortUrl = async (options) => {
|
|
238
|
+
var _a;
|
|
239
|
+
const exposedPorts = this.ports;
|
|
240
|
+
if (!exposedPorts.includes(options.port)) {
|
|
241
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
242
|
+
harnessId: VERCEL_PROVIDER_ID,
|
|
243
|
+
message: `Port ${options.port} is not exposed on this sandbox. Exposed ports: [${exposedPorts.join(", ")}].`
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const protocol = (_a = options.protocol) != null ? _a : "https";
|
|
247
|
+
const url = new URL(this.sandbox.domain(options.port));
|
|
248
|
+
const isSecure = url.protocol === "https:";
|
|
249
|
+
switch (protocol) {
|
|
250
|
+
case "http":
|
|
251
|
+
url.protocol = isSecure ? "https:" : "http:";
|
|
252
|
+
break;
|
|
253
|
+
case "https":
|
|
254
|
+
url.protocol = "https:";
|
|
255
|
+
break;
|
|
256
|
+
case "ws":
|
|
257
|
+
url.protocol = isSecure ? "wss:" : "ws:";
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
return url.toString();
|
|
261
|
+
};
|
|
262
|
+
this.setNetworkPolicy = async (policy) => {
|
|
263
|
+
await this.sandbox.update({ networkPolicy: toVercelPolicy(policy) });
|
|
264
|
+
};
|
|
265
|
+
this.setPorts = async (ports, options) => {
|
|
266
|
+
await this.sandbox.update(
|
|
267
|
+
{ ports: [...ports] },
|
|
268
|
+
(options == null ? void 0 : options.abortSignal) ? { signal: options.abortSignal } : void 0
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
this.stop = async () => {
|
|
272
|
+
if (!this.ownsLifecycle) return;
|
|
273
|
+
await this.sandbox.stop();
|
|
274
|
+
};
|
|
275
|
+
this.destroy = async () => {
|
|
276
|
+
if (!this.ownsLifecycle) return;
|
|
277
|
+
await this.sandbox.stop().catch(() => {
|
|
278
|
+
});
|
|
279
|
+
await this.sandbox.delete();
|
|
280
|
+
};
|
|
281
|
+
this.ownsLifecycle = input.ownsLifecycle;
|
|
282
|
+
this.id = input.sandbox.name;
|
|
283
|
+
this.defaultWorkingDirectory = input.sandbox.currentSession().cwd;
|
|
284
|
+
}
|
|
285
|
+
get ports() {
|
|
286
|
+
return this.sandbox.routes.map((route) => route.port);
|
|
287
|
+
}
|
|
288
|
+
restricted() {
|
|
289
|
+
return new VercelSandboxSession(this.sandbox);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
function toVercelPolicy(policy) {
|
|
293
|
+
switch (policy.mode) {
|
|
294
|
+
case "allow-all":
|
|
295
|
+
return "allow-all";
|
|
296
|
+
case "deny-all":
|
|
297
|
+
return "deny-all";
|
|
298
|
+
case "custom": {
|
|
299
|
+
const result = {};
|
|
300
|
+
const { allowedHosts, allowedCIDRs, deniedCIDRs } = policy;
|
|
301
|
+
if (allowedHosts != null && allowedHosts.length > 0) {
|
|
302
|
+
result.allow = [...allowedHosts];
|
|
303
|
+
}
|
|
304
|
+
if (allowedCIDRs != null && allowedCIDRs.length > 0 || deniedCIDRs != null && deniedCIDRs.length > 0) {
|
|
305
|
+
result.subnets = {
|
|
306
|
+
...allowedCIDRs != null && allowedCIDRs.length > 0 ? { allow: [...allowedCIDRs] } : {},
|
|
307
|
+
...deniedCIDRs != null && deniedCIDRs.length > 0 ? { deny: [...deniedCIDRs] } : {}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (result.allow == null && result.subnets == null) {
|
|
311
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
312
|
+
harnessId: VERCEL_PROVIDER_ID,
|
|
313
|
+
message: "Custom network policy requires at least one of allowedHosts or allowedCIDRs to be non-empty."
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// src/vercel-sandbox.ts
|
|
322
|
+
var DEFAULT_SANDBOX_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
323
|
+
var VERCEL_PROVIDER_ID2 = "vercel-sandbox";
|
|
324
|
+
var TEMPLATE_NAME_PREFIX = "ai-sdk-harness";
|
|
325
|
+
var SESSION_NAME_PREFIX = "ai-sdk-harness-session";
|
|
326
|
+
var SNAPSHOT_POLL_INTERVAL_MS = 500;
|
|
327
|
+
var SNAPSHOT_POLL_TIMEOUT_MS = 3e4;
|
|
328
|
+
function sessionSandboxName(sessionId) {
|
|
329
|
+
return `${SESSION_NAME_PREFIX}-${sessionId}`;
|
|
330
|
+
}
|
|
331
|
+
function createVercelSandbox(settings = {}) {
|
|
332
|
+
return new VercelSandboxProvider(settings);
|
|
333
|
+
}
|
|
334
|
+
var VercelSandboxProvider = class {
|
|
335
|
+
constructor(settings) {
|
|
336
|
+
this.settings = settings;
|
|
337
|
+
this.specificationVersion = "harness-sandbox-v1";
|
|
338
|
+
this.providerId = VERCEL_PROVIDER_ID2;
|
|
339
|
+
this.createSession = async (options) => {
|
|
340
|
+
var _a, _b, _c, _d;
|
|
341
|
+
(_a = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
342
|
+
if ("sandbox" in this.settings && this.settings.sandbox != null) {
|
|
343
|
+
return new VercelNetworkSandboxSession({
|
|
344
|
+
sandbox: this.settings.sandbox,
|
|
345
|
+
ownsLifecycle: false
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
const settings = this.settings;
|
|
349
|
+
const {
|
|
350
|
+
sandbox: _ignoredSandbox,
|
|
351
|
+
name: explicitName,
|
|
352
|
+
...createParams
|
|
353
|
+
} = settings;
|
|
354
|
+
const baseParams = {
|
|
355
|
+
...createParams,
|
|
356
|
+
timeout: (_b = createParams.timeout) != null ? _b : DEFAULT_SANDBOX_TIMEOUT_MS
|
|
357
|
+
};
|
|
358
|
+
const identity = options == null ? void 0 : options.identity;
|
|
359
|
+
const onFirstCreate = options == null ? void 0 : options.onFirstCreate;
|
|
360
|
+
const sessionNameOverride = (options == null ? void 0 : options.sessionId) ? { name: sessionSandboxName(options.sessionId) } : {};
|
|
361
|
+
if (identity == null || onFirstCreate == null) {
|
|
362
|
+
const sandbox = await Sandbox.create({
|
|
363
|
+
...baseParams,
|
|
364
|
+
...sessionNameOverride,
|
|
365
|
+
...(options == null ? void 0 : options.abortSignal) ? { signal: options.abortSignal } : {}
|
|
366
|
+
});
|
|
367
|
+
return new VercelNetworkSandboxSession({ sandbox, ownsLifecycle: true });
|
|
368
|
+
}
|
|
369
|
+
const templateName = explicitName != null ? explicitName : `${TEMPLATE_NAME_PREFIX}-${identity}`;
|
|
370
|
+
const cache = getSnapshotCache();
|
|
371
|
+
let snapshotId = cache.get(templateName);
|
|
372
|
+
if (snapshotId == null) {
|
|
373
|
+
const template = await Sandbox.getOrCreate({
|
|
374
|
+
...baseParams,
|
|
375
|
+
name: templateName,
|
|
376
|
+
persistent: true,
|
|
377
|
+
snapshotExpiration: (_c = baseParams.snapshotExpiration) != null ? _c : 0,
|
|
378
|
+
onCreate: async (sbx) => {
|
|
379
|
+
await onFirstCreate(new VercelSandboxSession(sbx), {
|
|
380
|
+
abortSignal: options == null ? void 0 : options.abortSignal
|
|
381
|
+
});
|
|
382
|
+
},
|
|
383
|
+
...(options == null ? void 0 : options.abortSignal) ? { signal: options.abortSignal } : {}
|
|
384
|
+
});
|
|
385
|
+
let resolvedId = template.currentSnapshotId;
|
|
386
|
+
if (resolvedId == null) {
|
|
387
|
+
const stopResult = await template.stop(
|
|
388
|
+
(options == null ? void 0 : options.abortSignal) ? { signal: options.abortSignal } : void 0
|
|
389
|
+
);
|
|
390
|
+
resolvedId = (_d = stopResult.snapshot) == null ? void 0 : _d.id;
|
|
391
|
+
if (resolvedId == null) {
|
|
392
|
+
resolvedId = await pollForTemplateSnapshot(
|
|
393
|
+
templateName,
|
|
394
|
+
options == null ? void 0 : options.abortSignal
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
cache.set(templateName, resolvedId);
|
|
399
|
+
snapshotId = resolvedId;
|
|
400
|
+
}
|
|
401
|
+
const {
|
|
402
|
+
runtime: _ignoredRuntime,
|
|
403
|
+
source: _ignoredSource,
|
|
404
|
+
persistent: _ignoredPersistent,
|
|
405
|
+
...forkParams
|
|
406
|
+
} = baseParams;
|
|
407
|
+
const fork = await Sandbox.create({
|
|
408
|
+
...forkParams,
|
|
409
|
+
source: { type: "snapshot", snapshotId },
|
|
410
|
+
...sessionNameOverride,
|
|
411
|
+
...(options == null ? void 0 : options.abortSignal) ? { signal: options.abortSignal } : {}
|
|
412
|
+
});
|
|
413
|
+
return new VercelNetworkSandboxSession({
|
|
414
|
+
sandbox: fork,
|
|
415
|
+
ownsLifecycle: true
|
|
416
|
+
});
|
|
417
|
+
};
|
|
418
|
+
this.resumeSession = async (options) => {
|
|
419
|
+
var _a;
|
|
420
|
+
(_a = options.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
421
|
+
if ("sandbox" in this.settings && this.settings.sandbox != null) {
|
|
422
|
+
return new VercelNetworkSandboxSession({
|
|
423
|
+
sandbox: this.settings.sandbox,
|
|
424
|
+
ownsLifecycle: false
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
const sandbox = await Sandbox.get({
|
|
428
|
+
name: sessionSandboxName(options.sessionId),
|
|
429
|
+
...options.abortSignal ? { signal: options.abortSignal } : {}
|
|
430
|
+
});
|
|
431
|
+
return new VercelNetworkSandboxSession({ sandbox, ownsLifecycle: true });
|
|
432
|
+
};
|
|
433
|
+
if ("sandbox" in settings && settings.sandbox != null && settings.bridgePorts != null && settings.bridgePorts.length > 0) {
|
|
434
|
+
this.bridgePorts = [...settings.bridgePorts];
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
var SNAPSHOT_CACHE_KEY = /* @__PURE__ */ Symbol.for(
|
|
439
|
+
"ai-sdk.harness.vercel-template-snapshots"
|
|
440
|
+
);
|
|
441
|
+
function getSnapshotCache() {
|
|
442
|
+
const globals = globalThis;
|
|
443
|
+
let cache = globals[SNAPSHOT_CACHE_KEY];
|
|
444
|
+
if (cache == null) {
|
|
445
|
+
cache = /* @__PURE__ */ new Map();
|
|
446
|
+
globals[SNAPSHOT_CACHE_KEY] = cache;
|
|
447
|
+
}
|
|
448
|
+
return cache;
|
|
449
|
+
}
|
|
450
|
+
async function pollForTemplateSnapshot(name, abortSignal) {
|
|
451
|
+
const deadline = Date.now() + SNAPSHOT_POLL_TIMEOUT_MS;
|
|
452
|
+
while (Date.now() < deadline) {
|
|
453
|
+
abortSignal == null ? void 0 : abortSignal.throwIfAborted();
|
|
454
|
+
const refreshed = await Sandbox.get({
|
|
455
|
+
name,
|
|
456
|
+
resume: false,
|
|
457
|
+
...abortSignal ? { signal: abortSignal } : {}
|
|
458
|
+
});
|
|
459
|
+
if (refreshed.currentSnapshotId) {
|
|
460
|
+
return refreshed.currentSnapshotId;
|
|
461
|
+
}
|
|
462
|
+
await new Promise(
|
|
463
|
+
(resolve) => setTimeout(resolve, SNAPSHOT_POLL_INTERVAL_MS)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
throw new Error(
|
|
467
|
+
`Timed out waiting for snapshot of template "${name}" to publish.`
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
export {
|
|
471
|
+
VercelSandboxProvider,
|
|
472
|
+
createVercelSandbox
|
|
473
|
+
};
|
|
474
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vercel-sandbox.ts","../src/vercel-network-sandbox-session.ts","../src/vercel-sandbox-session.ts"],"sourcesContent":["import type {\n HarnessV1NetworkSandboxSession,\n HarnessV1SandboxProvider,\n} from '@ai-sdk/harness';\nimport type { Experimental_SandboxSession as SandboxSession } from '@ai-sdk/provider-utils';\nimport { Sandbox } from '@vercel/sandbox';\nimport { VercelNetworkSandboxSession } from './vercel-network-sandbox-session';\nimport { VercelSandboxSession } from './vercel-sandbox-session';\n\n/**\n * Flattens an intersection of object types into a single object type so the\n * resolved shape displays as its named properties rather than a chain of\n * `A & B & C`.\n */\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\n/**\n * Distributes `Omit` across each member of a union instead of collapsing the\n * union to its common keys. `Sandbox.create`'s parameter is a union (a\n * git/tarball/no-source create variant and a snapshot-source create variant),\n * so a plain `Omit` would discard keys absent from any one member (e.g.\n * `runtime`, which the snapshot variant lacks) and merge the `source` shapes.\n * Applying `Omit` per-member preserves every variant intact; the `Prettify`\n * wrapper collapses each member's intersections into a readable object shape.\n */\ntype DistributiveOmit<T, K extends keyof any> = T extends unknown\n ? Prettify<Omit<T, K>>\n : never;\n\n/**\n * Parameters forwarded to `@vercel/sandbox`'s `Sandbox.create` when creating\n * a sandbox from scratch. Aliased directly from the underlying SDK so the\n * full surface — every option Vercel supports, including its native\n * `NetworkPolicy` — is available without us re-declaring it.\n */\ntype VercelSandboxCreateParams = DistributiveOmit<\n NonNullable<Parameters<typeof Sandbox.create>[0]>,\n 'onResume'\n>;\n\n/**\n * Settings for {@link createVercelSandbox}. Two mutually-exclusive shapes:\n *\n * - `{ sandbox }` — wrap an already-created `@vercel/sandbox` `Sandbox`. The\n * caller owns its lifecycle; the provider's `stop()` and `destroy()` are\n * no-ops. Optionally declare `bridgePorts` to give the harness a port pool to\n * lease from for concurrent sessions on the same provided sandbox.\n * - {@link VercelSandboxCreateParams} fields — provider creates the underlying\n * sandbox. When the adapter declares a bootstrap recipe the provider uses\n * `Sandbox.getOrCreate` to maintain a persistent named template snapshot\n * keyed by the recipe identity, and forks an ephemeral sandbox per session\n * from the snapshot. Use `name` to override the auto-derived template name.\n */\nexport type VercelSandboxSettings =\n | {\n sandbox: Sandbox;\n bridgePorts?: ReadonlyArray<number>;\n }\n | (VercelSandboxCreateParams & {\n sandbox?: never;\n name?: string;\n });\n\n/**\n * 30 minutes. The `@vercel/sandbox` SDK defaults to 5 minutes which is\n * too short for multi-step workflows — the VM expires between steps.\n */\nconst DEFAULT_SANDBOX_TIMEOUT_MS = 30 * 60 * 1_000;\n\nconst VERCEL_PROVIDER_ID = 'vercel-sandbox';\nconst TEMPLATE_NAME_PREFIX = 'ai-sdk-harness';\nconst SESSION_NAME_PREFIX = 'ai-sdk-harness-session';\nconst SNAPSHOT_POLL_INTERVAL_MS = 500;\nconst SNAPSHOT_POLL_TIMEOUT_MS = 30_000;\n\nfunction sessionSandboxName(sessionId: string): string {\n return `${SESSION_NAME_PREFIX}-${sessionId}`;\n}\n\nexport function createVercelSandbox(\n settings: VercelSandboxSettings = {} as VercelSandboxSettings,\n): HarnessV1SandboxProvider {\n return new VercelSandboxProvider(settings);\n}\n\n/**\n * `HarnessV1SandboxProvider` implementation backed by `@vercel/sandbox`.\n * Construct one via {@link createVercelSandbox} at module scope and pass it\n * to a `HarnessAgent` (or call `createSession()` directly if you want raw\n * access to a network sandbox session).\n */\nexport class VercelSandboxProvider implements HarnessV1SandboxProvider {\n readonly specificationVersion = 'harness-sandbox-v1' as const;\n readonly providerId = VERCEL_PROVIDER_ID;\n readonly bridgePorts?: ReadonlyArray<number>;\n\n constructor(private readonly settings: VercelSandboxSettings) {\n if (\n 'sandbox' in settings &&\n settings.sandbox != null &&\n settings.bridgePorts != null &&\n settings.bridgePorts.length > 0\n ) {\n this.bridgePorts = [...settings.bridgePorts];\n }\n }\n\n createSession = async (options?: {\n sessionId?: string;\n abortSignal?: AbortSignal;\n identity?: string;\n onFirstCreate?: (\n session: SandboxSession,\n opts: { abortSignal?: AbortSignal },\n ) => Promise<void>;\n }): Promise<HarnessV1NetworkSandboxSession> => {\n options?.abortSignal?.throwIfAborted();\n\n if ('sandbox' in this.settings && this.settings.sandbox != null) {\n return new VercelNetworkSandboxSession({\n sandbox: this.settings.sandbox,\n ownsLifecycle: false,\n });\n }\n\n type CreateNewBranch = BaseCreateSandboxParams & {\n sandbox?: never;\n name?: string;\n };\n const settings = this.settings as CreateNewBranch;\n const {\n sandbox: _ignoredSandbox,\n name: explicitName,\n ...createParams\n } = settings;\n const baseParams: BaseCreateSandboxParams = {\n ...createParams,\n timeout: createParams.timeout ?? DEFAULT_SANDBOX_TIMEOUT_MS,\n };\n\n const identity = options?.identity;\n const onFirstCreate = options?.onFirstCreate;\n\n // When sessionId is supplied, name the per-session sandbox deterministically\n // so a future `resumeSession({ sessionId })` can locate it via\n // `Sandbox.get({ name })`. Absent sessionId (e.g. prewarm), fall back to\n // Vercel's auto-naming.\n const sessionNameOverride = options?.sessionId\n ? { name: sessionSandboxName(options.sessionId) }\n : {};\n\n if (identity == null || onFirstCreate == null) {\n const sandbox = await Sandbox.create({\n ...baseParams,\n ...sessionNameOverride,\n ...(options?.abortSignal ? { signal: options.abortSignal } : {}),\n });\n return new VercelNetworkSandboxSession({ sandbox, ownsLifecycle: true });\n }\n\n const templateName = explicitName ?? `${TEMPLATE_NAME_PREFIX}-${identity}`;\n const cache = getSnapshotCache();\n let snapshotId = cache.get(templateName);\n\n if (snapshotId == null) {\n const template = await Sandbox.getOrCreate({\n ...baseParams,\n name: templateName,\n persistent: true,\n snapshotExpiration: baseParams.snapshotExpiration ?? 0,\n onCreate: async sbx => {\n await onFirstCreate(new VercelSandboxSession(sbx), {\n abortSignal: options?.abortSignal,\n });\n },\n ...(options?.abortSignal ? { signal: options.abortSignal } : {}),\n });\n\n let resolvedId: string | undefined = template.currentSnapshotId;\n if (resolvedId == null) {\n const stopResult = await template.stop(\n options?.abortSignal ? { signal: options.abortSignal } : undefined,\n );\n resolvedId = stopResult.snapshot?.id;\n if (resolvedId == null) {\n resolvedId = await pollForTemplateSnapshot(\n templateName,\n options?.abortSignal,\n );\n }\n }\n\n cache.set(templateName, resolvedId);\n snapshotId = resolvedId;\n }\n\n const {\n runtime: _ignoredRuntime,\n source: _ignoredSource,\n persistent: _ignoredPersistent,\n ...forkParams\n } = baseParams;\n\n const fork = await Sandbox.create({\n ...forkParams,\n source: { type: 'snapshot', snapshotId },\n ...sessionNameOverride,\n ...(options?.abortSignal ? { signal: options.abortSignal } : {}),\n });\n return new VercelNetworkSandboxSession({\n sandbox: fork,\n ownsLifecycle: true,\n });\n };\n\n resumeSession = async (options: {\n sessionId: string;\n abortSignal?: AbortSignal;\n }): Promise<HarnessV1NetworkSandboxSession> => {\n options.abortSignal?.throwIfAborted();\n\n // Wrap-existing case: caller owns the sandbox. Same session as createSession.\n if ('sandbox' in this.settings && this.settings.sandbox != null) {\n return new VercelNetworkSandboxSession({\n sandbox: this.settings.sandbox,\n ownsLifecycle: false,\n });\n }\n\n const sandbox = await Sandbox.get({\n name: sessionSandboxName(options.sessionId),\n ...(options.abortSignal ? { signal: options.abortSignal } : {}),\n });\n return new VercelNetworkSandboxSession({ sandbox, ownsLifecycle: true });\n };\n}\n\n/**\n * Base shape of `Sandbox.create` params extracted from the union (excludes\n * the `source: { type: 'snapshot' }` variant) so all create-time fields\n * are typed as present.\n */\ntype BaseCreateSandboxParams = Exclude<\n VercelSandboxCreateParams,\n { source: { type: 'snapshot'; snapshotId: string } }\n>;\n\nconst SNAPSHOT_CACHE_KEY = Symbol.for(\n 'ai-sdk.harness.vercel-template-snapshots',\n);\n\ntype SnapshotCache = Map<string, string>;\n\nfunction getSnapshotCache(): SnapshotCache {\n const globals = globalThis as {\n [SNAPSHOT_CACHE_KEY]?: SnapshotCache;\n };\n let cache = globals[SNAPSHOT_CACHE_KEY];\n if (cache == null) {\n cache = new Map();\n globals[SNAPSHOT_CACHE_KEY] = cache;\n }\n return cache;\n}\n\nasync function pollForTemplateSnapshot(\n name: string,\n abortSignal: AbortSignal | undefined,\n): Promise<string> {\n const deadline = Date.now() + SNAPSHOT_POLL_TIMEOUT_MS;\n while (Date.now() < deadline) {\n abortSignal?.throwIfAborted();\n const refreshed = await Sandbox.get({\n name,\n resume: false,\n ...(abortSignal ? { signal: abortSignal } : {}),\n });\n if (refreshed.currentSnapshotId) {\n return refreshed.currentSnapshotId;\n }\n await new Promise<void>(resolve =>\n setTimeout(resolve, SNAPSHOT_POLL_INTERVAL_MS),\n );\n }\n throw new Error(\n `Timed out waiting for snapshot of template \"${name}\" to publish.`,\n );\n}\n","import {\n HarnessCapabilityUnsupportedError,\n type HarnessV1NetworkPolicy,\n type HarnessV1NetworkSandboxSession,\n} from '@ai-sdk/harness';\nimport type { Experimental_SandboxSession as SandboxSession } from '@ai-sdk/provider-utils';\nimport type { Sandbox, NetworkPolicy } from '@vercel/sandbox';\nimport { VercelSandboxSession } from './vercel-sandbox-session';\n\nconst VERCEL_PROVIDER_ID = 'vercel-sandbox';\n\n/**\n * `HarnessV1NetworkSandboxSession` backed by a `@vercel/sandbox` `Sandbox`. The\n * provider's `create()` returns one of these. It extends\n * {@link VercelSandboxSession} with the infra surface (ports, lifecycle,\n * network policy). It owns the sandbox's lifecycle only when the provider\n * created it; when the provider was given an existing sandbox, `stop()` and\n * `destroy()` are no-ops (caller retains ownership).\n */\nexport class VercelNetworkSandboxSession\n extends VercelSandboxSession\n implements HarnessV1NetworkSandboxSession\n{\n readonly id: string;\n readonly defaultWorkingDirectory: string;\n private readonly ownsLifecycle: boolean;\n\n constructor(input: { sandbox: Sandbox; ownsLifecycle: boolean }) {\n super(input.sandbox);\n this.ownsLifecycle = input.ownsLifecycle;\n this.id = input.sandbox.name;\n this.defaultWorkingDirectory = input.sandbox.currentSession().cwd;\n }\n\n get ports(): ReadonlyArray<number> {\n return this.sandbox.routes.map(route => route.port);\n }\n\n restricted(): SandboxSession {\n return new VercelSandboxSession(this.sandbox);\n }\n\n getPortUrl = async (options: {\n port: number;\n protocol?: 'http' | 'https' | 'ws';\n }): Promise<string> => {\n const exposedPorts = this.ports;\n if (!exposedPorts.includes(options.port)) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: VERCEL_PROVIDER_ID,\n message: `Port ${options.port} is not exposed on this sandbox. Exposed ports: [${exposedPorts.join(', ')}].`,\n });\n }\n const protocol = options.protocol ?? 'https';\n const url = new URL(this.sandbox.domain(options.port));\n const isSecure = url.protocol === 'https:';\n switch (protocol) {\n case 'http':\n url.protocol = isSecure ? 'https:' : 'http:';\n break;\n case 'https':\n url.protocol = 'https:';\n break;\n case 'ws':\n url.protocol = isSecure ? 'wss:' : 'ws:';\n break;\n }\n return url.toString();\n };\n\n setNetworkPolicy = async (policy: HarnessV1NetworkPolicy): Promise<void> => {\n await this.sandbox.update({ networkPolicy: toVercelPolicy(policy) });\n };\n\n setPorts = async (\n ports: ReadonlyArray<number>,\n options?: { abortSignal?: AbortSignal },\n ): Promise<void> => {\n await this.sandbox.update(\n { ports: [...ports] },\n options?.abortSignal ? { signal: options.abortSignal } : undefined,\n );\n };\n\n stop = async (): Promise<void> => {\n if (!this.ownsLifecycle) return;\n await this.sandbox.stop();\n };\n\n destroy = async (): Promise<void> => {\n if (!this.ownsLifecycle) return;\n await this.sandbox.stop().catch(() => {});\n await this.sandbox.delete();\n };\n}\n\nexport function toVercelPolicy(policy: HarnessV1NetworkPolicy): NetworkPolicy {\n switch (policy.mode) {\n case 'allow-all':\n return 'allow-all';\n case 'deny-all':\n return 'deny-all';\n case 'custom': {\n const result: Extract<NetworkPolicy, { allow?: unknown }> = {};\n const { allowedHosts, allowedCIDRs, deniedCIDRs } = policy;\n if (allowedHosts != null && allowedHosts.length > 0) {\n result.allow = [...allowedHosts];\n }\n if (\n (allowedCIDRs != null && allowedCIDRs.length > 0) ||\n (deniedCIDRs != null && deniedCIDRs.length > 0)\n ) {\n result.subnets = {\n ...(allowedCIDRs != null && allowedCIDRs.length > 0\n ? { allow: [...allowedCIDRs] }\n : {}),\n ...(deniedCIDRs != null && deniedCIDRs.length > 0\n ? { deny: [...deniedCIDRs] }\n : {}),\n };\n }\n if (result.allow == null && result.subnets == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: VERCEL_PROVIDER_ID,\n message:\n 'Custom network policy requires at least one of allowedHosts or allowedCIDRs to be non-empty.',\n });\n }\n return result;\n }\n }\n}\n","import { posix } from 'node:path';\nimport {\n extractLines,\n type Experimental_SandboxSession,\n type Experimental_SandboxProcess,\n} from '@ai-sdk/provider-utils';\nimport type { Sandbox, Command } from '@vercel/sandbox';\n\n/**\n * `Experimental_SandboxSession` implementation backed by a `@vercel/sandbox`\n * `Sandbox` instance. This is the tool-safe surface (file I/O, exec, spawn);\n * it is what `VercelNetworkSandboxSession.restricted()` returns and is not\n * constructed directly by consumers. The network sandbox session owns the\n * lifetime of the underlying sandbox.\n */\nexport class VercelSandboxSession implements Experimental_SandboxSession {\n constructor(protected readonly sandbox: Sandbox) {}\n\n get description(): string {\n return [\n `Vercel Sandbox (name: ${this.sandbox.name}).`,\n 'Filesystem changes persist for the lifetime of the sandbox.',\n ].join('\\n');\n }\n\n async run({\n command,\n workingDirectory,\n env,\n abortSignal,\n }: {\n command: string;\n workingDirectory?: string;\n env?: Record<string, string>;\n abortSignal?: AbortSignal;\n }): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n abortSignal?.throwIfAborted();\n\n const finished = await this.sandbox.runCommand({\n cmd: 'bash',\n args: ['-c', command],\n ...(workingDirectory !== undefined ? { cwd: workingDirectory } : {}),\n ...(env !== undefined ? { env } : {}),\n ...(abortSignal !== undefined ? { signal: abortSignal } : {}),\n });\n\n const [stdout, stderr] = await Promise.all([\n finished.stdout(),\n finished.stderr(),\n ]);\n\n return {\n exitCode: finished.exitCode,\n stdout,\n stderr,\n };\n }\n\n async spawn({\n command,\n workingDirectory,\n env,\n abortSignal,\n }: {\n command: string;\n workingDirectory?: string;\n env?: Record<string, string>;\n abortSignal?: AbortSignal;\n }): Promise<Experimental_SandboxProcess> {\n abortSignal?.throwIfAborted();\n\n const live = await this.sandbox.runCommand({\n cmd: 'bash',\n args: ['-c', command],\n detached: true,\n ...(workingDirectory !== undefined ? { cwd: workingDirectory } : {}),\n ...(env !== undefined ? { env } : {}),\n ...(abortSignal !== undefined ? { signal: abortSignal } : {}),\n });\n\n return createSandboxProcess(live, abortSignal);\n }\n\n async readFile({\n path,\n abortSignal,\n }: {\n path: string;\n abortSignal?: AbortSignal;\n }): Promise<ReadableStream<Uint8Array> | null> {\n const bytes = await this.readBinaryFile({ path, abortSignal });\n if (bytes == null) return null;\n return bytesToStream(bytes);\n }\n\n async readBinaryFile({\n path,\n abortSignal,\n }: {\n path: string;\n abortSignal?: AbortSignal;\n }): Promise<Uint8Array | null> {\n abortSignal?.throwIfAborted();\n try {\n const buffer = await this.sandbox.readFileToBuffer(\n { path },\n abortSignal ? { signal: abortSignal } : undefined,\n );\n if (buffer == null) return null;\n return new Uint8Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength,\n );\n } catch (error) {\n if (isFileNotFoundError(error)) return null;\n throw error;\n }\n }\n\n async readTextFile({\n path,\n encoding = 'utf-8',\n startLine,\n endLine,\n abortSignal,\n }: {\n path: string;\n encoding?: string;\n startLine?: number;\n endLine?: number;\n abortSignal?: AbortSignal;\n }): Promise<string | null> {\n const bytes = await this.readBinaryFile({ path, abortSignal });\n if (bytes == null) return null;\n const text = Buffer.from(bytes).toString(encoding as BufferEncoding);\n return extractLines({ text, startLine, endLine });\n }\n\n async writeFile({\n path,\n content,\n abortSignal,\n }: {\n path: string;\n content: ReadableStream<Uint8Array>;\n abortSignal?: AbortSignal;\n }): Promise<void> {\n const bytes = await collectStream(content);\n await this.writeBinaryFile({ path, content: bytes, abortSignal });\n }\n\n async writeBinaryFile({\n path,\n content,\n abortSignal,\n }: {\n path: string;\n content: Uint8Array;\n abortSignal?: AbortSignal;\n }): Promise<void> {\n abortSignal?.throwIfAborted();\n const parent = posix.dirname(path);\n if (parent && parent !== '.' && parent !== '/') {\n await this.sandbox.runCommand({\n cmd: 'mkdir',\n args: ['-p', parent],\n ...(abortSignal !== undefined ? { signal: abortSignal } : {}),\n });\n }\n await this.sandbox.writeFiles(\n [{ path, content }],\n abortSignal ? { signal: abortSignal } : undefined,\n );\n }\n\n async writeTextFile({\n path,\n content,\n encoding = 'utf-8',\n abortSignal,\n }: {\n path: string;\n content: string;\n encoding?: string;\n abortSignal?: AbortSignal;\n }): Promise<void> {\n const buffer = Buffer.from(content, encoding as BufferEncoding);\n await this.writeBinaryFile({\n path,\n content: new Uint8Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength,\n ),\n abortSignal,\n });\n }\n}\n\nfunction createSandboxProcess(\n command: Command,\n abortSignal: AbortSignal | undefined,\n): Experimental_SandboxProcess {\n const encoder = new TextEncoder();\n const controllers: {\n stdout?: ReadableStreamDefaultController<Uint8Array>;\n stderr?: ReadableStreamDefaultController<Uint8Array>;\n } = {};\n\n const stdout = new ReadableStream<Uint8Array>({\n start(controller) {\n controllers.stdout = controller;\n },\n });\n\n const stderr = new ReadableStream<Uint8Array>({\n start(controller) {\n controllers.stderr = controller;\n },\n });\n\n const drained = (async () => {\n try {\n const iterator = abortSignal\n ? command.logs({ signal: abortSignal })\n : command.logs();\n for await (const message of iterator) {\n const target =\n message.stream === 'stdout' ? controllers.stdout : controllers.stderr;\n target?.enqueue(encoder.encode(message.data));\n }\n controllers.stdout?.close();\n controllers.stderr?.close();\n } catch (error) {\n controllers.stdout?.error(error);\n controllers.stderr?.error(error);\n }\n })();\n\n return {\n stdout,\n stderr,\n async wait(): Promise<{ exitCode: number }> {\n const finished = await command.wait();\n await drained;\n if (abortSignal?.aborted) {\n throw abortSignal.reason ?? new DOMException('Aborted', 'AbortError');\n }\n return { exitCode: finished.exitCode };\n },\n async kill(): Promise<void> {\n await command.kill();\n },\n };\n}\n\nfunction bytesToStream(bytes: Uint8Array): ReadableStream<Uint8Array> {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(bytes);\n controller.close();\n },\n });\n}\n\nasync function collectStream(\n stream: ReadableStream<Uint8Array>,\n): Promise<Uint8Array> {\n const reader = stream.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value) {\n chunks.push(value);\n total += value.byteLength;\n }\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return out;\n}\n\nfunction isFileNotFoundError(error: unknown): boolean {\n if (error == null || typeof error !== 'object') return false;\n const code = (error as { code?: unknown }).code;\n if (code === 'ENOENT') return true;\n const message = (error as { message?: unknown }).message;\n return (\n typeof message === 'string' &&\n /no such file|not found|does not exist|ENOENT/i.test(message)\n );\n}\n"],"mappings":"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","names":["VERCEL_PROVIDER_ID"]}
|
package/package.json
CHANGED
|
@@ -1 +1,69 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-sdk/sandbox-vercel",
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"source": "./src/index.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**/*",
|
|
12
|
+
"src",
|
|
13
|
+
"!src/**/*.test.ts",
|
|
14
|
+
"!src/**/*.test-d.ts",
|
|
15
|
+
"!src/**/__snapshots__",
|
|
16
|
+
"!src/**/__fixtures__",
|
|
17
|
+
"CHANGELOG.md",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"exports": {
|
|
21
|
+
"./package.json": "./package.json",
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@vercel/sandbox": "^2.0.1",
|
|
30
|
+
"@ai-sdk/harness": "1.0.0-beta.14",
|
|
31
|
+
"@ai-sdk/provider-utils": "5.0.0-beta.49"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "22.19.19",
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
|
+
"typescript": "5.8.3",
|
|
37
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=22"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"provenance": true
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://ai-sdk.dev/docs",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/vercel/ai",
|
|
50
|
+
"directory": "packages/sandbox-vercel"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/vercel/ai/issues"
|
|
54
|
+
},
|
|
55
|
+
"keywords": [
|
|
56
|
+
"ai",
|
|
57
|
+
"sandbox",
|
|
58
|
+
"vercel"
|
|
59
|
+
],
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
|
|
62
|
+
"build:watch": "pnpm clean && tsup --watch",
|
|
63
|
+
"clean": "del-cli dist *.tsbuildinfo",
|
|
64
|
+
"type-check": "tsc --build",
|
|
65
|
+
"test": "pnpm test:node",
|
|
66
|
+
"test:watch": "vitest --config vitest.node.config.js",
|
|
67
|
+
"test:node": "vitest --config vitest.node.config.js --run"
|
|
68
|
+
}
|
|
69
|
+
}
|