@cloudflare/sandbox 0.9.0 → 0.9.2
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/bridge/index.js +3 -3
- package/dist/{contexts-D6kt6WyG.d.ts → contexts-D_shbnJs.d.ts} +32 -2
- package/dist/contexts-D_shbnJs.d.ts.map +1 -0
- package/dist/{dist-Ilf8VjmX.js → dist-B_eXrP83.js} +35 -48
- package/dist/dist-B_eXrP83.js.map +1 -0
- package/dist/errors-CBi-O-pF.js +227 -0
- package/dist/errors-CBi-O-pF.js.map +1 -0
- package/dist/index.d.ts +27 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.js +1 -1
- package/dist/opencode/index.d.ts +2 -2
- package/dist/opencode/index.js +2 -2
- package/dist/{sandbox-Cf_Wjrzq.js → sandbox-CReFGUtF.js} +734 -64
- package/dist/sandbox-CReFGUtF.js.map +1 -0
- package/dist/{sandbox-Chr1Ebo-.d.ts → sandbox-YMrVC62F.d.ts} +453 -20
- package/dist/sandbox-YMrVC62F.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/contexts-D6kt6WyG.d.ts.map +0 -1
- package/dist/dist-Ilf8VjmX.js.map +0 -1
- package/dist/errors-Dk2rApYI.js +0 -162
- package/dist/errors-Dk2rApYI.js.map +0 -1
- package/dist/sandbox-Cf_Wjrzq.js.map +0 -1
- package/dist/sandbox-Chr1Ebo-.d.ts.map +0 -1
|
@@ -1,7 +1,65 @@
|
|
|
1
1
|
import { Container } from "@cloudflare/containers";
|
|
2
|
+
import "capnweb";
|
|
2
3
|
|
|
3
|
-
//#region ../shared/dist/
|
|
4
|
+
//#region ../shared/dist/desktop-types.d.ts
|
|
4
5
|
|
|
6
|
+
interface DesktopStartResult {
|
|
7
|
+
success: boolean;
|
|
8
|
+
resolution: [number, number];
|
|
9
|
+
dpi: number;
|
|
10
|
+
}
|
|
11
|
+
interface DesktopStopResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface DesktopStatusResult {
|
|
15
|
+
success: boolean;
|
|
16
|
+
status: 'active' | 'partial' | 'inactive';
|
|
17
|
+
processes: Record<string, DesktopProcessHealth>;
|
|
18
|
+
resolution: [number, number] | null;
|
|
19
|
+
dpi: number | null;
|
|
20
|
+
}
|
|
21
|
+
interface DesktopProcessHealth {
|
|
22
|
+
running: boolean;
|
|
23
|
+
pid?: number;
|
|
24
|
+
uptime?: number;
|
|
25
|
+
}
|
|
26
|
+
type DesktopImageFormat = 'png' | 'jpeg' | 'webp';
|
|
27
|
+
interface DesktopScreenshotRequest {
|
|
28
|
+
format?: 'base64';
|
|
29
|
+
imageFormat?: DesktopImageFormat;
|
|
30
|
+
quality?: number;
|
|
31
|
+
showCursor?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface DesktopScreenshotRegionRequest extends DesktopScreenshotRequest {
|
|
34
|
+
region: DesktopScreenshotRegion;
|
|
35
|
+
}
|
|
36
|
+
interface DesktopScreenshotRegion {
|
|
37
|
+
x: number;
|
|
38
|
+
y: number;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
}
|
|
42
|
+
interface DesktopScreenshotResult {
|
|
43
|
+
success: boolean;
|
|
44
|
+
data: string;
|
|
45
|
+
imageFormat: DesktopImageFormat;
|
|
46
|
+
width: number;
|
|
47
|
+
height: number;
|
|
48
|
+
}
|
|
49
|
+
type DesktopMouseButton = 'left' | 'right' | 'middle';
|
|
50
|
+
type DesktopScrollDirection = 'up' | 'down' | 'left' | 'right';
|
|
51
|
+
interface DesktopCursorPosition {
|
|
52
|
+
success: boolean;
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
}
|
|
56
|
+
interface DesktopScreenSize {
|
|
57
|
+
success: boolean;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region ../shared/dist/logger/types.d.ts
|
|
5
63
|
type LogComponent = 'container' | 'sandbox-do' | 'executor';
|
|
6
64
|
/**
|
|
7
65
|
* Context metadata included in every log entry
|
|
@@ -826,6 +884,8 @@ interface SandboxOptions {
|
|
|
826
884
|
* - `"http"` (default): Standard HTTP request/response. Works everywhere.
|
|
827
885
|
* - `"websocket"`: Multiplexes requests over a single WebSocket connection,
|
|
828
886
|
* avoiding sub-request limits in Workers and Durable Objects.
|
|
887
|
+
* - `"capnweb"`: Direct RPC over a single WebSocket using the capnweb protocol.
|
|
888
|
+
* Lowest latency; automatically disconnects when idle to respect `sleepAfter`.
|
|
829
889
|
*
|
|
830
890
|
* When set via `getSandbox()` options, this overrides the `SANDBOX_TRANSPORT` env var.
|
|
831
891
|
*
|
|
@@ -836,7 +896,7 @@ interface SandboxOptions {
|
|
|
836
896
|
*
|
|
837
897
|
* @default "http"
|
|
838
898
|
*/
|
|
839
|
-
transport?: 'http' | 'websocket';
|
|
899
|
+
transport?: 'http' | 'websocket' | 'rpc';
|
|
840
900
|
}
|
|
841
901
|
/**
|
|
842
902
|
* Execution session - isolated execution context within a sandbox
|
|
@@ -1166,7 +1226,7 @@ interface ExecutionSession {
|
|
|
1166
1226
|
streamProcessLogs(processId: string, options?: {
|
|
1167
1227
|
signal?: AbortSignal;
|
|
1168
1228
|
}): Promise<ReadableStream<Uint8Array>>;
|
|
1169
|
-
writeFile(path: string, content: string
|
|
1229
|
+
writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
|
|
1170
1230
|
encoding?: string;
|
|
1171
1231
|
}): Promise<WriteFileResult>;
|
|
1172
1232
|
readFile(path: string, options?: {
|
|
@@ -1371,7 +1431,7 @@ interface ISandbox {
|
|
|
1371
1431
|
stderr: string;
|
|
1372
1432
|
processId: string;
|
|
1373
1433
|
}>;
|
|
1374
|
-
writeFile(path: string, content: string
|
|
1434
|
+
writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
|
|
1375
1435
|
encoding?: string;
|
|
1376
1436
|
}): Promise<WriteFileResult>;
|
|
1377
1437
|
readFile(path: string, options?: {
|
|
@@ -1402,6 +1462,13 @@ interface ISandbox {
|
|
|
1402
1462
|
unmountBucket(mountPath: string): Promise<void>;
|
|
1403
1463
|
createSession(options?: SessionOptions): Promise<ExecutionSession>;
|
|
1404
1464
|
deleteSession(sessionId: string): Promise<SessionDeleteResult>;
|
|
1465
|
+
/**
|
|
1466
|
+
* Returns the Cloudflare placement ID observed during the most recent
|
|
1467
|
+
* session-create handshake with the container. `null` when the container
|
|
1468
|
+
* does not expose `CLOUDFLARE_PLACEMENT_ID` (local development). `undefined`
|
|
1469
|
+
* when no handshake has been observed yet on this sandbox.
|
|
1470
|
+
*/
|
|
1471
|
+
getContainerPlacementId(): Promise<string | null | undefined>;
|
|
1405
1472
|
createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
|
|
1406
1473
|
runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
|
|
1407
1474
|
runCodeStream(code: string, options?: RunCodeOptions): Promise<ReadableStream>;
|
|
@@ -1415,6 +1482,162 @@ declare function isExecResult(value: any): value is ExecResult;
|
|
|
1415
1482
|
declare function isProcess(value: any): value is Process;
|
|
1416
1483
|
declare function isProcessStatus(value: string): value is ProcessStatus;
|
|
1417
1484
|
//#endregion
|
|
1485
|
+
//#region ../shared/dist/rpc-types.d.ts
|
|
1486
|
+
interface SandboxCommandsAPI {
|
|
1487
|
+
execute(command: string, sessionId: string, options?: {
|
|
1488
|
+
timeoutMs?: number;
|
|
1489
|
+
env?: Record<string, string | undefined>;
|
|
1490
|
+
cwd?: string;
|
|
1491
|
+
}): Promise<{
|
|
1492
|
+
success: boolean;
|
|
1493
|
+
exitCode: number;
|
|
1494
|
+
stdout: string;
|
|
1495
|
+
stderr: string;
|
|
1496
|
+
command: string;
|
|
1497
|
+
timestamp: string;
|
|
1498
|
+
}>;
|
|
1499
|
+
executeStream(command: string, sessionId: string, options?: {
|
|
1500
|
+
timeoutMs?: number;
|
|
1501
|
+
env?: Record<string, string | undefined>;
|
|
1502
|
+
cwd?: string;
|
|
1503
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
1504
|
+
}
|
|
1505
|
+
interface SandboxFilesAPI {
|
|
1506
|
+
readFile(path: string, sessionId: string, options?: {
|
|
1507
|
+
encoding?: string;
|
|
1508
|
+
}): Promise<ReadFileResult>;
|
|
1509
|
+
readFileStream(path: string, sessionId: string): Promise<ReadableStream<Uint8Array>>;
|
|
1510
|
+
writeFile(path: string, content: string, sessionId: string, options?: {
|
|
1511
|
+
encoding?: string;
|
|
1512
|
+
permissions?: string;
|
|
1513
|
+
}): Promise<WriteFileResult>;
|
|
1514
|
+
writeFileStream(path: string, stream: ReadableStream<Uint8Array>, sessionId: string): Promise<{
|
|
1515
|
+
success: boolean;
|
|
1516
|
+
path: string;
|
|
1517
|
+
bytesWritten: number;
|
|
1518
|
+
timestamp: string;
|
|
1519
|
+
}>;
|
|
1520
|
+
deleteFile(path: string, sessionId: string): Promise<DeleteFileResult>;
|
|
1521
|
+
renameFile(oldPath: string, newPath: string, sessionId: string): Promise<RenameFileResult>;
|
|
1522
|
+
moveFile(sourcePath: string, destinationPath: string, sessionId: string): Promise<MoveFileResult>;
|
|
1523
|
+
mkdir(path: string, sessionId: string, options?: {
|
|
1524
|
+
recursive?: boolean;
|
|
1525
|
+
}): Promise<MkdirResult>;
|
|
1526
|
+
listFiles(path: string, sessionId: string, options?: ListFilesOptions): Promise<ListFilesResult>;
|
|
1527
|
+
exists(path: string, sessionId: string): Promise<FileExistsResult>;
|
|
1528
|
+
}
|
|
1529
|
+
interface SandboxProcessesAPI {
|
|
1530
|
+
startProcess(command: string, sessionId: string, options?: {
|
|
1531
|
+
processId?: string;
|
|
1532
|
+
timeoutMs?: number;
|
|
1533
|
+
}): Promise<ProcessStartResult>;
|
|
1534
|
+
listProcesses(): Promise<ProcessListResult>;
|
|
1535
|
+
getProcess(id: string): Promise<ProcessInfoResult>;
|
|
1536
|
+
killProcess(id: string): Promise<ProcessKillResult>;
|
|
1537
|
+
killAllProcesses(): Promise<ProcessCleanupResult>;
|
|
1538
|
+
getProcessLogs(id: string): Promise<ProcessLogsResult>;
|
|
1539
|
+
streamProcessLogs(id: string): Promise<ReadableStream<Uint8Array>>;
|
|
1540
|
+
}
|
|
1541
|
+
interface SandboxPortsAPI {
|
|
1542
|
+
exposePort(port: number, sessionId: string, name?: string): Promise<PortExposeResult>;
|
|
1543
|
+
getExposedPorts(sessionId: string): Promise<PortListResult>;
|
|
1544
|
+
unexposePort(port: number, sessionId: string): Promise<PortCloseResult>;
|
|
1545
|
+
watchPort(request: PortWatchRequest): Promise<ReadableStream<Uint8Array>>;
|
|
1546
|
+
}
|
|
1547
|
+
interface SandboxGitAPI {
|
|
1548
|
+
checkout(repoUrl: string, sessionId: string, options?: {
|
|
1549
|
+
branch?: string;
|
|
1550
|
+
targetDir?: string;
|
|
1551
|
+
depth?: number;
|
|
1552
|
+
timeoutMs?: number;
|
|
1553
|
+
}): Promise<GitCheckoutResult>;
|
|
1554
|
+
}
|
|
1555
|
+
interface SandboxInterpreterAPI {
|
|
1556
|
+
createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
|
|
1557
|
+
streamCode(contextId: string, code: string, language?: string): Promise<ReadableStream<Uint8Array>>;
|
|
1558
|
+
runCodeStream(contextId: string | undefined, code: string, language: string | undefined, callbacks: {
|
|
1559
|
+
onStdout?: (output: OutputMessage) => void | Promise<void>;
|
|
1560
|
+
onStderr?: (output: OutputMessage) => void | Promise<void>;
|
|
1561
|
+
onResult?: (result: Result) => void | Promise<void>;
|
|
1562
|
+
onError?: (error: ExecutionError) => void | Promise<void>;
|
|
1563
|
+
}, timeoutMs?: number): Promise<void>;
|
|
1564
|
+
listCodeContexts(): Promise<CodeContext[]>;
|
|
1565
|
+
deleteCodeContext(contextId: string): Promise<void>;
|
|
1566
|
+
}
|
|
1567
|
+
interface SandboxUtilsAPI {
|
|
1568
|
+
ping(): Promise<string>;
|
|
1569
|
+
getVersion(): Promise<string>;
|
|
1570
|
+
getCommands(): Promise<string[]>;
|
|
1571
|
+
createSession(options: {
|
|
1572
|
+
id: string;
|
|
1573
|
+
env?: Record<string, string | undefined>;
|
|
1574
|
+
cwd?: string;
|
|
1575
|
+
}): Promise<{
|
|
1576
|
+
success: boolean;
|
|
1577
|
+
id: string;
|
|
1578
|
+
message: string;
|
|
1579
|
+
timestamp: string;
|
|
1580
|
+
containerPlacementId?: string | null;
|
|
1581
|
+
}>;
|
|
1582
|
+
deleteSession(sessionId: string): Promise<{
|
|
1583
|
+
success: boolean;
|
|
1584
|
+
sessionId: string;
|
|
1585
|
+
timestamp: string;
|
|
1586
|
+
}>;
|
|
1587
|
+
listSessions(): Promise<{
|
|
1588
|
+
sessions: string[];
|
|
1589
|
+
}>;
|
|
1590
|
+
}
|
|
1591
|
+
interface SandboxBackupAPI {
|
|
1592
|
+
createArchive(dir: string, archivePath: string, sessionId: string, options?: {
|
|
1593
|
+
excludes?: string[];
|
|
1594
|
+
gitignore?: boolean;
|
|
1595
|
+
}): Promise<CreateBackupResponse>;
|
|
1596
|
+
restoreArchive(dir: string, archivePath: string, sessionId: string): Promise<RestoreBackupResponse>;
|
|
1597
|
+
}
|
|
1598
|
+
interface SandboxDesktopAPI {
|
|
1599
|
+
start(options?: {
|
|
1600
|
+
resolution?: [number, number];
|
|
1601
|
+
dpi?: number;
|
|
1602
|
+
}): Promise<DesktopStartResult>;
|
|
1603
|
+
stop(): Promise<DesktopStopResult>;
|
|
1604
|
+
status(): Promise<DesktopStatusResult>;
|
|
1605
|
+
screenshot(options?: DesktopScreenshotRequest): Promise<DesktopScreenshotResult>;
|
|
1606
|
+
screenshotRegion(request: DesktopScreenshotRegionRequest): Promise<DesktopScreenshotResult>;
|
|
1607
|
+
click(x: number, y: number, options?: {
|
|
1608
|
+
button?: DesktopMouseButton;
|
|
1609
|
+
clickCount?: number;
|
|
1610
|
+
}): Promise<void>;
|
|
1611
|
+
doubleClick(x: number, y: number): Promise<void>;
|
|
1612
|
+
tripleClick(x: number, y: number): Promise<void>;
|
|
1613
|
+
rightClick(x: number, y: number): Promise<void>;
|
|
1614
|
+
middleClick(x: number, y: number): Promise<void>;
|
|
1615
|
+
mouseDown(x?: number, y?: number, options?: {
|
|
1616
|
+
button?: DesktopMouseButton;
|
|
1617
|
+
}): Promise<void>;
|
|
1618
|
+
mouseUp(x?: number, y?: number, options?: {
|
|
1619
|
+
button?: DesktopMouseButton;
|
|
1620
|
+
}): Promise<void>;
|
|
1621
|
+
moveMouse(x: number, y: number): Promise<void>;
|
|
1622
|
+
drag(startX: number, startY: number, endX: number, endY: number, options?: {
|
|
1623
|
+
button?: DesktopMouseButton;
|
|
1624
|
+
}): Promise<void>;
|
|
1625
|
+
scroll(x: number, y: number, direction: DesktopScrollDirection, amount?: number): Promise<void>;
|
|
1626
|
+
getCursorPosition(): Promise<DesktopCursorPosition>;
|
|
1627
|
+
type(text: string, options?: {
|
|
1628
|
+
delay?: number;
|
|
1629
|
+
}): Promise<void>;
|
|
1630
|
+
press(key: string): Promise<void>;
|
|
1631
|
+
keyDown(key: string): Promise<void>;
|
|
1632
|
+
keyUp(key: string): Promise<void>;
|
|
1633
|
+
getScreenSize(): Promise<DesktopScreenSize>;
|
|
1634
|
+
getProcessStatus(name: string): Promise<DesktopStatusResult>;
|
|
1635
|
+
}
|
|
1636
|
+
interface SandboxWatchAPI {
|
|
1637
|
+
watch(request: WatchRequest): Promise<ReadableStream<Uint8Array>>;
|
|
1638
|
+
checkChanges(request: CheckChangesRequest): Promise<CheckChangesResult>;
|
|
1639
|
+
}
|
|
1640
|
+
//#endregion
|
|
1418
1641
|
//#region src/clients/types.d.ts
|
|
1419
1642
|
/**
|
|
1420
1643
|
* Minimal interface for container fetch functionality
|
|
@@ -1502,7 +1725,7 @@ interface SessionRequest {
|
|
|
1502
1725
|
/**
|
|
1503
1726
|
* Transport mode for SDK communication
|
|
1504
1727
|
*/
|
|
1505
|
-
type TransportMode = 'http' | 'websocket';
|
|
1728
|
+
type TransportMode = 'http' | 'websocket' | 'rpc';
|
|
1506
1729
|
interface TransportRequestInit extends RequestInit {
|
|
1507
1730
|
/** Override the non-streaming request timeout for this single request. */
|
|
1508
1731
|
requestTimeoutMs?: number;
|
|
@@ -1627,7 +1850,10 @@ declare class BackupClient extends BaseHttpClient {
|
|
|
1627
1850
|
* @param archivePath - Where the container should write the archive
|
|
1628
1851
|
* @param sessionId - Session context
|
|
1629
1852
|
*/
|
|
1630
|
-
createArchive(dir: string, archivePath: string, sessionId: string,
|
|
1853
|
+
createArchive(dir: string, archivePath: string, sessionId: string, options?: {
|
|
1854
|
+
excludes?: string[];
|
|
1855
|
+
gitignore?: boolean;
|
|
1856
|
+
}): Promise<CreateBackupResponse>;
|
|
1631
1857
|
/**
|
|
1632
1858
|
* Tell the container to restore a squashfs archive into a directory.
|
|
1633
1859
|
* @param dir - Target directory
|
|
@@ -2178,11 +2404,16 @@ interface CreateSessionRequest {
|
|
|
2178
2404
|
commandTimeoutMs?: number;
|
|
2179
2405
|
}
|
|
2180
2406
|
/**
|
|
2181
|
-
* Response interface for creating sessions
|
|
2407
|
+
* Response interface for creating sessions.
|
|
2408
|
+
*
|
|
2409
|
+
* `containerPlacementId` carries the container's `CLOUDFLARE_PLACEMENT_ID` at session
|
|
2410
|
+
* creation time so the DO can capture it without a separate request. It is
|
|
2411
|
+
* `null` when the environment variable is not set, such as in local dev.
|
|
2182
2412
|
*/
|
|
2183
2413
|
interface CreateSessionResponse extends BaseApiResponse {
|
|
2184
2414
|
id: string;
|
|
2185
2415
|
message: string;
|
|
2416
|
+
containerPlacementId?: string | null;
|
|
2186
2417
|
}
|
|
2187
2418
|
/**
|
|
2188
2419
|
* Request interface for deleting sessions
|
|
@@ -2258,14 +2489,13 @@ declare class WatchClient extends BaseHttpClient {
|
|
|
2258
2489
|
//#endregion
|
|
2259
2490
|
//#region src/clients/sandbox-client.d.ts
|
|
2260
2491
|
/**
|
|
2261
|
-
* Main sandbox client that composes all domain-specific clients
|
|
2262
|
-
* Provides organized access to all sandbox functionality
|
|
2492
|
+
* Main sandbox client that composes all domain-specific clients.
|
|
2493
|
+
* Provides organized access to all sandbox functionality.
|
|
2263
2494
|
*
|
|
2264
2495
|
* Supports two transport modes:
|
|
2265
2496
|
* - HTTP (default): Each request is a separate HTTP call
|
|
2266
|
-
* - WebSocket: All requests multiplexed over a single connection
|
|
2267
|
-
*
|
|
2268
|
-
* WebSocket mode reduces sub-request count when running inside Workers/Durable Objects.
|
|
2497
|
+
* - WebSocket: All requests multiplexed over a single connection,
|
|
2498
|
+
* reducing sub-request count inside Workers/Durable Objects
|
|
2269
2499
|
*/
|
|
2270
2500
|
declare class SandboxClient {
|
|
2271
2501
|
readonly backup: BackupClient;
|
|
@@ -2296,6 +2526,19 @@ declare class SandboxClient {
|
|
|
2296
2526
|
* Check if WebSocket is connected (only relevant in WebSocket mode)
|
|
2297
2527
|
*/
|
|
2298
2528
|
isWebSocketConnected(): boolean;
|
|
2529
|
+
/**
|
|
2530
|
+
* Stream a file directly to the container over a binary RPC channel.
|
|
2531
|
+
*
|
|
2532
|
+
* Requires the capnweb transport (`useWebSocket: 'rpc'`). Calling this
|
|
2533
|
+
* method with the HTTP or WebSocket transports throws an error because those
|
|
2534
|
+
* transports do not support binary streaming.
|
|
2535
|
+
*/
|
|
2536
|
+
writeFileStream(_path: string, _content: ReadableStream<Uint8Array>, _sessionId: string): Promise<{
|
|
2537
|
+
success: boolean;
|
|
2538
|
+
path: string;
|
|
2539
|
+
bytesWritten: number;
|
|
2540
|
+
timestamp: string;
|
|
2541
|
+
}>;
|
|
2299
2542
|
/**
|
|
2300
2543
|
* Connect WebSocket transport (no-op in HTTP mode)
|
|
2301
2544
|
* Called automatically on first request, but can be called explicitly
|
|
@@ -2309,6 +2552,132 @@ declare class SandboxClient {
|
|
|
2309
2552
|
disconnect(): void;
|
|
2310
2553
|
}
|
|
2311
2554
|
//#endregion
|
|
2555
|
+
//#region src/container-connection.d.ts
|
|
2556
|
+
/** Stub that can issue a WebSocket-upgrade fetch through the DO's Container base class. */
|
|
2557
|
+
interface ContainerFetchStub {
|
|
2558
|
+
fetch(request: Request): Promise<Response>;
|
|
2559
|
+
}
|
|
2560
|
+
interface ContainerConnectionOptions {
|
|
2561
|
+
stub: ContainerFetchStub;
|
|
2562
|
+
port?: number;
|
|
2563
|
+
logger?: Logger;
|
|
2564
|
+
}
|
|
2565
|
+
//#endregion
|
|
2566
|
+
//#region src/clients/rpc-sandbox-client.d.ts
|
|
2567
|
+
interface RPCSandboxClientOptions extends ContainerConnectionOptions {
|
|
2568
|
+
/** Idle timeout before disconnecting the WebSocket (ms). Defaults to 1 000. */
|
|
2569
|
+
idleDisconnectMs?: number;
|
|
2570
|
+
/** Busy/idle poll interval (ms). Defaults to 1 000. */
|
|
2571
|
+
busyPollIntervalMs?: number;
|
|
2572
|
+
/**
|
|
2573
|
+
* Renew the DO's activity timeout. Fires at the start of every RPC call
|
|
2574
|
+
* and on every busy-poll tick while the session has work in flight.
|
|
2575
|
+
* Mirrors what `containerFetch()` does at the top of each HTTP request.
|
|
2576
|
+
*/
|
|
2577
|
+
onActivity?: () => void;
|
|
2578
|
+
/**
|
|
2579
|
+
* Fires once when the capnweb session transitions from idle to busy
|
|
2580
|
+
* (an RPC call was started or a stream return is now in flight). The
|
|
2581
|
+
* Sandbox DO wires this to `inflightRequests++`, which makes
|
|
2582
|
+
* `isActivityExpired()` skip the sleepAfter comparison.
|
|
2583
|
+
*/
|
|
2584
|
+
onSessionBusy?: () => void;
|
|
2585
|
+
/**
|
|
2586
|
+
* Fires once when the session transitions from busy back to idle
|
|
2587
|
+
* (all RPC promises settled and all stream exports released). The
|
|
2588
|
+
* Sandbox DO wires this to `inflightRequests = max(0, n-1)` and a
|
|
2589
|
+
* final `renewActivityTimeout()`, matching containerFetch's finally
|
|
2590
|
+
* block.
|
|
2591
|
+
*/
|
|
2592
|
+
onSessionIdle?: () => void;
|
|
2593
|
+
}
|
|
2594
|
+
/**
|
|
2595
|
+
* SandboxClient backed by direct capnweb RPC.
|
|
2596
|
+
*
|
|
2597
|
+
* Drop-in replacement for SandboxClient when the capnweb transport is active.
|
|
2598
|
+
* All operations call the container's SandboxRPCAPI directly over capnweb,
|
|
2599
|
+
* bypassing the HTTP handler/router layer entirely.
|
|
2600
|
+
*
|
|
2601
|
+
* Manages its own WebSocket lifecycle: a fresh `ContainerConnection` is
|
|
2602
|
+
* created on demand and torn down after `idleDisconnectMs` of inactivity.
|
|
2603
|
+
* Busy/idle detection relies on `RpcSession.getStats()` which tracks all
|
|
2604
|
+
* in-flight RPC calls and stream exports — including long-lived streaming
|
|
2605
|
+
* RPCs that would be invisible to a simple per-call request counter (see
|
|
2606
|
+
* the file-level comment for the full rationale).
|
|
2607
|
+
*/
|
|
2608
|
+
declare class RPCSandboxClient {
|
|
2609
|
+
private readonly connOptions;
|
|
2610
|
+
private readonly idleDisconnectMs;
|
|
2611
|
+
private readonly busyPollIntervalMs;
|
|
2612
|
+
private readonly logger;
|
|
2613
|
+
private readonly onActivity;
|
|
2614
|
+
private readonly onSessionBusy;
|
|
2615
|
+
private readonly onSessionIdle;
|
|
2616
|
+
private conn;
|
|
2617
|
+
private idleTimer;
|
|
2618
|
+
private busyPollTimer;
|
|
2619
|
+
/** Tracks whether we currently believe the session is busy. */
|
|
2620
|
+
private busy;
|
|
2621
|
+
/**
|
|
2622
|
+
* Set the first time the poller observes `conn.isConnected() === true`,
|
|
2623
|
+
* cleared in `destroyConnection()`. Lets us distinguish "the WebSocket
|
|
2624
|
+
* upgrade is still in progress" (don't tear down) from "we were
|
|
2625
|
+
* connected and the peer went away" (do tear down).
|
|
2626
|
+
*/
|
|
2627
|
+
private wasEverConnected;
|
|
2628
|
+
constructor(options: RPCSandboxClientOptions);
|
|
2629
|
+
/**
|
|
2630
|
+
* Return the current connection, creating a new one if none exists or the
|
|
2631
|
+
* previous one was torn down by an idle disconnect. Starts the busy-poll
|
|
2632
|
+
* timer the first time a connection is materialized.
|
|
2633
|
+
*/
|
|
2634
|
+
private getConnection;
|
|
2635
|
+
/**
|
|
2636
|
+
* Called synchronously at the start of each RPC method invocation.
|
|
2637
|
+
* Renews the DO activity timeout so the sleepAfter alarm is pushed
|
|
2638
|
+
* forward before the container processes the call.
|
|
2639
|
+
*/
|
|
2640
|
+
private renewActivity;
|
|
2641
|
+
/**
|
|
2642
|
+
* Sample `getStats()` and update busy/idle state. While busy, renews the
|
|
2643
|
+
* activity timeout each tick so an in-flight stream keeps pushing the
|
|
2644
|
+
* sleepAfter deadline forward. On the busy → idle edge, fires
|
|
2645
|
+
* `onSessionIdle` and schedules the WebSocket disconnect.
|
|
2646
|
+
*
|
|
2647
|
+
* If the WebSocket has dropped underneath us (container crash, network
|
|
2648
|
+
* blip) we tear the connection down here. `destroyConnection()` fires
|
|
2649
|
+
* `onSessionIdle` if we were busy, so the DO's inflight counter doesn't
|
|
2650
|
+
* stay pinned forever waiting for a peer that's never going to reply.
|
|
2651
|
+
*/
|
|
2652
|
+
private pollBusyState;
|
|
2653
|
+
private startBusyPoll;
|
|
2654
|
+
private stopBusyPoll;
|
|
2655
|
+
private scheduleIdleDisconnect;
|
|
2656
|
+
private clearIdleTimer;
|
|
2657
|
+
private destroyConnection;
|
|
2658
|
+
get commands(): SandboxCommandsAPI;
|
|
2659
|
+
get files(): SandboxFilesAPI;
|
|
2660
|
+
get processes(): SandboxProcessesAPI;
|
|
2661
|
+
get ports(): SandboxPortsAPI;
|
|
2662
|
+
get git(): SandboxGitAPI;
|
|
2663
|
+
get utils(): SandboxUtilsAPI;
|
|
2664
|
+
get backup(): SandboxBackupAPI;
|
|
2665
|
+
get desktop(): SandboxDesktopAPI;
|
|
2666
|
+
get watch(): SandboxWatchAPI;
|
|
2667
|
+
get interpreter(): SandboxInterpreterAPI;
|
|
2668
|
+
setRetryTimeoutMs(_ms: number): void;
|
|
2669
|
+
getTransportMode(): TransportMode;
|
|
2670
|
+
isWebSocketConnected(): boolean;
|
|
2671
|
+
connect(): Promise<void>;
|
|
2672
|
+
disconnect(): void;
|
|
2673
|
+
writeFileStream(path: string, stream: ReadableStream<Uint8Array>, sessionId: string): Promise<{
|
|
2674
|
+
success: boolean;
|
|
2675
|
+
path: string;
|
|
2676
|
+
bytesWritten: number;
|
|
2677
|
+
timestamp: string;
|
|
2678
|
+
}>;
|
|
2679
|
+
}
|
|
2680
|
+
//#endregion
|
|
2312
2681
|
//#region src/sandbox.d.ts
|
|
2313
2682
|
type SandboxConfiguration = {
|
|
2314
2683
|
sandboxName?: {
|
|
@@ -2318,13 +2687,13 @@ type SandboxConfiguration = {
|
|
|
2318
2687
|
sleepAfter?: string | number;
|
|
2319
2688
|
keepAlive?: boolean;
|
|
2320
2689
|
containerTimeouts?: NonNullable<SandboxOptions['containerTimeouts']>;
|
|
2321
|
-
transport?: 'http' | 'websocket';
|
|
2690
|
+
transport?: 'http' | 'websocket' | 'rpc';
|
|
2322
2691
|
};
|
|
2323
2692
|
declare function getSandbox<T extends Sandbox<any>>(ns: DurableObjectNamespace<T>, id: string, options?: SandboxOptions): T;
|
|
2324
2693
|
declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox {
|
|
2325
2694
|
defaultPort: number;
|
|
2326
2695
|
sleepAfter: string | number;
|
|
2327
|
-
client: SandboxClient;
|
|
2696
|
+
client: SandboxClient | RPCSandboxClient;
|
|
2328
2697
|
private codeInterpreter;
|
|
2329
2698
|
private sandboxName;
|
|
2330
2699
|
private normalizeId;
|
|
@@ -2412,6 +2781,10 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2412
2781
|
* Create a SandboxClient with current transport settings
|
|
2413
2782
|
*/
|
|
2414
2783
|
private createSandboxClient;
|
|
2784
|
+
/**
|
|
2785
|
+
* Create the appropriate client for a given transport protocol.
|
|
2786
|
+
*/
|
|
2787
|
+
private createClientForTransport;
|
|
2415
2788
|
constructor(ctx: DurableObjectState<{}>, env: Env);
|
|
2416
2789
|
setSandboxName(name: string, normalizeId?: boolean): Promise<void>;
|
|
2417
2790
|
configure(configuration: SandboxConfiguration): Promise<void>;
|
|
@@ -2431,7 +2804,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2431
2804
|
* has been persisted: re-applying the same transport is a no-op.
|
|
2432
2805
|
* Storage is written before the in-memory state and client are updated.
|
|
2433
2806
|
*/
|
|
2434
|
-
setTransport(transport: 'http' | 'websocket'): Promise<void>;
|
|
2807
|
+
setTransport(transport: 'http' | 'websocket' | 'rpc'): Promise<void>;
|
|
2435
2808
|
/**
|
|
2436
2809
|
* Validate a timeout value is within acceptable range
|
|
2437
2810
|
* Throws error if invalid - used for user-provided values
|
|
@@ -2493,9 +2866,30 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2493
2866
|
*/
|
|
2494
2867
|
private executeS3FSMount;
|
|
2495
2868
|
/**
|
|
2496
|
-
*
|
|
2869
|
+
* In-flight `destroy()` promise. While set, concurrent callers coalesce
|
|
2870
|
+
* onto the same teardown instead of triggering a second one. Cleared when
|
|
2871
|
+
* the underlying work settles, so a later call that genuinely needs to
|
|
2872
|
+
* recreate a destroyed sandbox still runs.
|
|
2873
|
+
*
|
|
2874
|
+
* If the underlying teardown hangs (e.g. `super.destroy()` never resolves
|
|
2875
|
+
* because the Containers control plane is unresponsive), every coalesced
|
|
2876
|
+
* caller hangs on the same promise until the Durable Object is evicted.
|
|
2877
|
+
* This is deliberate: a second concurrent teardown would not make a stuck
|
|
2878
|
+
* control plane unstuck, and spawning one would defeat the point of
|
|
2879
|
+
* coalescing. Callers that need bounded waits must apply their own
|
|
2880
|
+
* timeout around `destroy()`.
|
|
2881
|
+
*/
|
|
2882
|
+
private inflightDestroy;
|
|
2883
|
+
/**
|
|
2884
|
+
* Cleanup and destroy the sandbox container.
|
|
2885
|
+
*
|
|
2886
|
+
* Concurrent calls coalesce: if a previous `destroy()` is still in flight,
|
|
2887
|
+
* subsequent calls await the same underlying work instead of starting a
|
|
2888
|
+
* second teardown. A canonical `sandbox.destroy.coalesced` event is logged
|
|
2889
|
+
* per coalesced call so repeated destroy traffic is observable.
|
|
2497
2890
|
*/
|
|
2498
2891
|
destroy(): Promise<void>;
|
|
2892
|
+
private doDestroy;
|
|
2499
2893
|
onStart(): Promise<void>;
|
|
2500
2894
|
/**
|
|
2501
2895
|
* Re-expose ports on the container runtime using tokens persisted in DO
|
|
@@ -2581,6 +2975,21 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2581
2975
|
*/
|
|
2582
2976
|
private ensureDefaultSession;
|
|
2583
2977
|
private initializeDefaultSession;
|
|
2978
|
+
/**
|
|
2979
|
+
* Persist the container's placement ID in DO storage.
|
|
2980
|
+
*
|
|
2981
|
+
* Called from the session-create handshake so subsequent reads via
|
|
2982
|
+
* `getContainerPlacementId()` do not require a round-trip to the container. The value
|
|
2983
|
+
* is overwritten on every handshake so that container replacements (which
|
|
2984
|
+
* assign a new placement ID) are reflected on the next session-create.
|
|
2985
|
+
*
|
|
2986
|
+
* A value of `undefined` means the handshake response omitted the field
|
|
2987
|
+
* (older container, unexpected error shape) and the stored value is left
|
|
2988
|
+
* untouched. `null` means the env var is not set in the container and is
|
|
2989
|
+
* stored as-is so callers can distinguish "observed and absent" from "not
|
|
2990
|
+
* yet observed."
|
|
2991
|
+
*/
|
|
2992
|
+
private capturePlacementId;
|
|
2584
2993
|
exec(command: string, options?: ExecOptions): Promise<ExecResult>;
|
|
2585
2994
|
/**
|
|
2586
2995
|
* Execute an infrastructure command (backup, mount, env setup, etc.)
|
|
@@ -2669,10 +3078,15 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2669
3078
|
recursive?: boolean;
|
|
2670
3079
|
sessionId?: string;
|
|
2671
3080
|
}): Promise<MkdirResult>;
|
|
2672
|
-
writeFile(path: string, content: string
|
|
3081
|
+
writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
|
|
2673
3082
|
encoding?: string;
|
|
2674
3083
|
sessionId?: string;
|
|
2675
|
-
}): Promise<
|
|
3084
|
+
}): Promise<{
|
|
3085
|
+
success: boolean;
|
|
3086
|
+
path: string;
|
|
3087
|
+
bytesWritten: number;
|
|
3088
|
+
timestamp: string;
|
|
3089
|
+
} | WriteFileResult>;
|
|
2676
3090
|
deleteFile(path: string, sessionId?: string): Promise<DeleteFileResult>;
|
|
2677
3091
|
renameFile(oldPath: string, newPath: string, sessionId?: string): Promise<RenameFileResult>;
|
|
2678
3092
|
moveFile(sourcePath: string, destinationPath: string, sessionId?: string): Promise<MoveFileResult>;
|
|
@@ -2813,6 +3227,24 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2813
3227
|
* @throws Error if attempting to delete the default session
|
|
2814
3228
|
*/
|
|
2815
3229
|
deleteSession(sessionId: string): Promise<SessionDeleteResult>;
|
|
3230
|
+
/**
|
|
3231
|
+
* Get the Cloudflare placement ID observed for the underlying container.
|
|
3232
|
+
*
|
|
3233
|
+
* The placement ID is captured during the first session-create handshake
|
|
3234
|
+
* after a container start and stored in Durable Object storage, so this
|
|
3235
|
+
* method returns the cached value without contacting the container. A new
|
|
3236
|
+
* placement ID is captured on each subsequent session-create handshake,
|
|
3237
|
+
* which occurs whenever the container has been replaced.
|
|
3238
|
+
*
|
|
3239
|
+
* Returns `null` when a handshake has completed but the container's
|
|
3240
|
+
* `CLOUDFLARE_PLACEMENT_ID` environment variable is not set (for example,
|
|
3241
|
+
* in local development).
|
|
3242
|
+
*
|
|
3243
|
+
* Returns `undefined` when no handshake has been observed yet on this
|
|
3244
|
+
* sandbox. Call any method that triggers session creation (such as
|
|
3245
|
+
* `exec()`) to populate the value.
|
|
3246
|
+
*/
|
|
3247
|
+
getContainerPlacementId(): Promise<string | null | undefined>;
|
|
2816
3248
|
private getSessionWrapper;
|
|
2817
3249
|
createCodeContext(options?: CreateContextOptions): Promise<CodeContext>;
|
|
2818
3250
|
runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>;
|
|
@@ -2830,6 +3262,7 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2830
3262
|
* Returns the R2 bucket or throws if backup is not configured.
|
|
2831
3263
|
*/
|
|
2832
3264
|
private requireBackupBucket;
|
|
3265
|
+
private normalizeBackupExcludes;
|
|
2833
3266
|
private static readonly PRESIGNED_URL_EXPIRY_SECONDS;
|
|
2834
3267
|
/**
|
|
2835
3268
|
* Create a unique, dedicated session for a single backup operation.
|
|
@@ -2936,5 +3369,5 @@ declare class Sandbox<Env = unknown> extends Container<Env> implements ISandbox
|
|
|
2936
3369
|
private doRestoreBackupLocal;
|
|
2937
3370
|
}
|
|
2938
3371
|
//#endregion
|
|
2939
|
-
export {
|
|
2940
|
-
//# sourceMappingURL=sandbox-
|
|
3372
|
+
export { BucketProvider as $, DesktopStopResponse as A, RestoreBackupResult as At, ExecuteResponse as B, ExecuteRequest as Bt, ClickOptions as C, ProcessKillResult as Ct, DesktopStartOptions as D, ProcessStartResult as Dt, DesktopClient as E, ProcessOptions as Et, ScreenshotRegion as F, WaitForPortOptions as Ft, HttpClientOptions as G, CreateContextOptions as Gt, BaseApiResponse as H, StartProcessRequest as Ht, ScreenshotResponse as I, WatchOptions as It, SessionRequest as J, RunCodeOptions as Jt, RequestConfig as K, Execution as Kt, ScrollDirection as L, isExecResult as Lt, ScreenSizeResponse as M, SessionOptions as Mt, ScreenshotBytesResponse as N, StreamOptions as Nt, DesktopStartResponse as O, ProcessStatus as Ot, ScreenshotOptions as P, WaitForLogResult as Pt, BucketCredentials as Q, TypeOptions as R, isProcess as Rt, WriteFileRequest as S, ProcessInfoResult as St, Desktop as T, ProcessLogsResult as Tt, ContainerStub as U, PtyOptions as Ut, BackupClient as V, ExposePortRequest as Vt, ErrorResponse as W, CodeContext as Wt, BackupOptions as X, SandboxInterpreterAPI as Y, BaseExecOptions as Z, GitClient as _, PortCloseResult as _t, CreateSessionRequest as a, ExecResult as at, MkdirRequest as b, Process as bt, DeleteSessionResponse as c, FileMetadata as ct, ProcessClient as d, GitCheckoutResult as dt, CheckChangesOptions as et, PortClient as f, ISandbox as ft, GitCheckoutRequest as g, MountBucketOptions as gt, InterpreterClient as h, LogEvent as ht, CommandsResponse as i, ExecOptions as it, KeyInput as j, SandboxOptions as jt, DesktopStatusResponse as k, RemoteMountBucketOptions as kt, PingResponse as l, FileStreamEvent as lt, ExecutionCallbacks as m, LocalMountBucketOptions as mt, getSandbox as n, DirectoryBackup as nt, CreateSessionResponse as o, ExecutionSession as ot, UnexposePortRequest as p, ListFilesOptions as pt, ResponseHandler as q, ExecutionResult as qt, SandboxClient as r, ExecEvent as rt, DeleteSessionRequest as s, FileChunk as st, Sandbox as t, CheckChangesResult as tt, UtilityClient as u, FileWatchSSEEvent as ut, FileClient as v, PortExposeResult as vt, CursorPositionResponse as w, ProcessListResult as wt, ReadFileRequest as x, ProcessCleanupResult as xt, FileOperationRequest as y, PortListResult as yt, CommandClient as z, isProcessStatus as zt };
|
|
3373
|
+
//# sourceMappingURL=sandbox-YMrVC62F.d.ts.map
|