@watasu/sdk 0.1.40 → 0.1.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/codeInterpreter.d.ts +124 -25
- package/dist/codeInterpreter.js +62 -24
- package/dist/commands.d.ts +11 -2
- package/dist/commands.js +11 -10
- package/dist/connectionConfig.d.ts +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +54 -4
- package/dist/filesystem.d.ts +13 -1
- package/dist/filesystem.js +51 -8
- package/dist/git.d.ts +5 -2
- package/dist/index.d.ts +22 -10
- package/dist/index.js +7 -5
- package/dist/process.js +8 -4
- package/dist/processSocket.d.ts +15 -3
- package/dist/processSocket.js +108 -6
- package/dist/pty.js +1 -1
- package/dist/sandbox.d.ts +34 -5
- package/dist/sandbox.js +48 -14
- package/dist/template.d.ts +36 -7
- package/dist/template.js +104 -29
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +5 -1
- package/dist/volume.d.ts +15 -4
- package/dist/volume.js +8 -0
- package/package.json +2 -2
package/dist/filesystem.d.ts
CHANGED
|
@@ -8,6 +8,13 @@ export declare enum FileType {
|
|
|
8
8
|
/** Symbolic link. */
|
|
9
9
|
SYMLINK = "symlink"
|
|
10
10
|
}
|
|
11
|
+
export declare enum FilesystemEventType {
|
|
12
|
+
CHMOD = "chmod",
|
|
13
|
+
CREATE = "create",
|
|
14
|
+
REMOVE = "remove",
|
|
15
|
+
RENAME = "rename",
|
|
16
|
+
WRITE = "write"
|
|
17
|
+
}
|
|
11
18
|
/** Metadata for one sandbox filesystem entry. */
|
|
12
19
|
export interface EntryInfo {
|
|
13
20
|
name: string;
|
|
@@ -27,7 +34,8 @@ export interface WriteEntry {
|
|
|
27
34
|
data: WriteData;
|
|
28
35
|
}
|
|
29
36
|
export interface FilesystemEvent {
|
|
30
|
-
|
|
37
|
+
name: string;
|
|
38
|
+
type: FilesystemEventType | string;
|
|
31
39
|
path: string;
|
|
32
40
|
entry?: EntryInfo;
|
|
33
41
|
raw: Record<string, unknown>;
|
|
@@ -35,7 +43,10 @@ export interface FilesystemEvent {
|
|
|
35
43
|
export interface WatchOpts {
|
|
36
44
|
recursive?: boolean;
|
|
37
45
|
includeEntry?: boolean;
|
|
46
|
+
allowNetworkMounts?: boolean;
|
|
38
47
|
requestTimeoutMs?: number;
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
user?: string;
|
|
39
50
|
onExit?: (error?: Error) => void | Promise<void>;
|
|
40
51
|
}
|
|
41
52
|
export interface FilesystemRequestOpts {
|
|
@@ -48,6 +59,7 @@ export interface FilesystemReadOpts extends FilesystemRequestOpts {
|
|
|
48
59
|
}
|
|
49
60
|
export interface FilesystemWriteOpts extends FilesystemRequestOpts {
|
|
50
61
|
gzip?: boolean;
|
|
62
|
+
useOctetStream?: boolean;
|
|
51
63
|
metadata?: Record<string, string>;
|
|
52
64
|
}
|
|
53
65
|
/** Live filesystem watcher. Call `stop()` to close the local watch stream. */
|
package/dist/filesystem.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { gzipSync } from 'node:zlib';
|
|
1
2
|
import { withQuery } from './transport.js';
|
|
2
3
|
import { FileNotFoundError, InvalidArgumentError } from './errors.js';
|
|
3
4
|
import { ProcessSocket, base64Encode } from './processSocket.js';
|
|
@@ -10,6 +11,14 @@ export var FileType;
|
|
|
10
11
|
/** Symbolic link. */
|
|
11
12
|
FileType["SYMLINK"] = "symlink";
|
|
12
13
|
})(FileType || (FileType = {}));
|
|
14
|
+
export var FilesystemEventType;
|
|
15
|
+
(function (FilesystemEventType) {
|
|
16
|
+
FilesystemEventType["CHMOD"] = "chmod";
|
|
17
|
+
FilesystemEventType["CREATE"] = "create";
|
|
18
|
+
FilesystemEventType["REMOVE"] = "remove";
|
|
19
|
+
FilesystemEventType["RENAME"] = "rename";
|
|
20
|
+
FilesystemEventType["WRITE"] = "write";
|
|
21
|
+
})(FilesystemEventType || (FilesystemEventType = {}));
|
|
13
22
|
/** Live filesystem watcher. Call `stop()` to close the local watch stream. */
|
|
14
23
|
export class WatchHandle {
|
|
15
24
|
socket;
|
|
@@ -62,7 +71,12 @@ export class FilesystemWatcher {
|
|
|
62
71
|
if (this.handle)
|
|
63
72
|
return;
|
|
64
73
|
const nextOpts = { ...this.opts, ...opts };
|
|
65
|
-
const socket = await new ProcessSocket(this.dataPlane.baseUrl, this.dataPlane.token, withQuery('/runtime/v1/files/watch', {
|
|
74
|
+
const socket = await new ProcessSocket(this.dataPlane.baseUrl, this.dataPlane.token, withQuery('/runtime/v1/files/watch', {
|
|
75
|
+
path: this.path,
|
|
76
|
+
recursive: nextOpts.recursive ?? false,
|
|
77
|
+
include_entry: nextOpts.includeEntry,
|
|
78
|
+
allow_network_mounts: nextOpts.allowNetworkMounts,
|
|
79
|
+
}), nextOpts.requestTimeoutMs, this.dataPlane.headers).connect();
|
|
66
80
|
this.handle = new WatchHandle(socket, socket, async (event) => {
|
|
67
81
|
for (const listener of this.listeners)
|
|
68
82
|
await listener(event);
|
|
@@ -109,8 +123,8 @@ export class Filesystem {
|
|
|
109
123
|
if (Array.isArray(pathOrFiles)) {
|
|
110
124
|
return this.writeFiles(pathOrFiles, dataOrOpts);
|
|
111
125
|
}
|
|
112
|
-
const body = await writeDataToBytes(dataOrOpts);
|
|
113
|
-
const payload = await this.dataPlane.putJson(withQuery('/runtime/v1/files', { path: pathOrFiles, gzip: opts.gzip }), body, opts);
|
|
126
|
+
const body = maybeGzip(await writeDataToBytes(dataOrOpts), opts.gzip);
|
|
127
|
+
const payload = await this.dataPlane.putJson(withQuery('/runtime/v1/files', { path: pathOrFiles, gzip: opts.gzip }), body, requestOpts(opts, opts.gzip ? { 'content-encoding': 'gzip' } : undefined));
|
|
114
128
|
return entryInfo(payload.file ?? payload);
|
|
115
129
|
}
|
|
116
130
|
/** Write raw bytes to a file. */
|
|
@@ -122,11 +136,12 @@ export class Filesystem {
|
|
|
122
136
|
if (files.length === 0)
|
|
123
137
|
return [];
|
|
124
138
|
const payload = await this.dataPlane.postJson('/runtime/v1/files/write_files', {
|
|
125
|
-
...opts,
|
|
139
|
+
...requestOpts(opts),
|
|
126
140
|
json: {
|
|
127
141
|
files: await Promise.all(files.map(async (file) => ({
|
|
128
142
|
path: file.path,
|
|
129
|
-
data_base64: base64Encode(await writeDataToBytes(file.data)),
|
|
143
|
+
data_base64: base64Encode(maybeGzip(await writeDataToBytes(file.data), opts.gzip)),
|
|
144
|
+
...(opts.gzip ? { gzip: true } : {}),
|
|
130
145
|
}))),
|
|
131
146
|
},
|
|
132
147
|
});
|
|
@@ -194,6 +209,19 @@ async function writeDataToBytes(data) {
|
|
|
194
209
|
return readStreamToBytes(data);
|
|
195
210
|
throw new InvalidArgumentError(`Unsupported file data type: ${Object.prototype.toString.call(data)}`);
|
|
196
211
|
}
|
|
212
|
+
function requestOpts(opts, headers) {
|
|
213
|
+
const out = {};
|
|
214
|
+
if (opts.requestTimeoutMs !== undefined)
|
|
215
|
+
out.requestTimeoutMs = opts.requestTimeoutMs;
|
|
216
|
+
if (opts.signal !== undefined)
|
|
217
|
+
out.signal = opts.signal;
|
|
218
|
+
if (headers !== undefined)
|
|
219
|
+
out.headers = headers;
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
function maybeGzip(bytes, enabled) {
|
|
223
|
+
return enabled ? new Uint8Array(gzipSync(bytes)) : bytes;
|
|
224
|
+
}
|
|
197
225
|
function toArrayBuffer(bytes) {
|
|
198
226
|
const buffer = new ArrayBuffer(bytes.byteLength);
|
|
199
227
|
new Uint8Array(buffer).set(bytes);
|
|
@@ -253,17 +281,32 @@ function recordOfStrings(value) {
|
|
|
253
281
|
}
|
|
254
282
|
function filesystemEvent(value) {
|
|
255
283
|
const item = value && typeof value === 'object' ? value : {};
|
|
284
|
+
const path = String(item.path ?? '');
|
|
256
285
|
return {
|
|
257
286
|
type: normalizeEventType(String(item.type ?? 'modify')),
|
|
258
|
-
|
|
287
|
+
name: String(item.name ?? relativeName(path)),
|
|
288
|
+
path,
|
|
259
289
|
entry: item.file && typeof item.file === 'object' ? entryInfo(item.file) : undefined,
|
|
260
290
|
raw: item,
|
|
261
291
|
};
|
|
262
292
|
}
|
|
263
293
|
function normalizeEventType(value) {
|
|
264
294
|
if (value === 'delete')
|
|
265
|
-
return
|
|
295
|
+
return FilesystemEventType.REMOVE;
|
|
266
296
|
if (value === 'modify')
|
|
267
|
-
return
|
|
297
|
+
return FilesystemEventType.WRITE;
|
|
298
|
+
if (value === 'chmod')
|
|
299
|
+
return FilesystemEventType.CHMOD;
|
|
300
|
+
if (value === 'create')
|
|
301
|
+
return FilesystemEventType.CREATE;
|
|
302
|
+
if (value === 'remove')
|
|
303
|
+
return FilesystemEventType.REMOVE;
|
|
304
|
+
if (value === 'rename')
|
|
305
|
+
return FilesystemEventType.RENAME;
|
|
306
|
+
if (value === 'write')
|
|
307
|
+
return FilesystemEventType.WRITE;
|
|
268
308
|
return value;
|
|
269
309
|
}
|
|
310
|
+
function relativeName(path) {
|
|
311
|
+
return path.split('/').filter(Boolean).pop() ?? '';
|
|
312
|
+
}
|
package/dist/git.d.ts
CHANGED
|
@@ -50,13 +50,15 @@ export interface GitCredentialOpts extends GitRequestOpts {
|
|
|
50
50
|
host?: string;
|
|
51
51
|
protocol?: string;
|
|
52
52
|
}
|
|
53
|
+
export type GitDangerouslyAuthenticateOpts = GitCredentialOpts;
|
|
53
54
|
export interface GitConfigureUserOpts extends GitRequestOpts {
|
|
54
|
-
scope?:
|
|
55
|
+
scope?: GitConfigScope;
|
|
55
56
|
path?: string;
|
|
56
57
|
}
|
|
57
58
|
export interface GitBranchOpts extends GitRequestOpts {
|
|
58
59
|
force?: boolean;
|
|
59
60
|
}
|
|
61
|
+
export type GitDeleteBranchOpts = GitBranchOpts;
|
|
60
62
|
export interface GitAddOpts extends GitRequestOpts {
|
|
61
63
|
files?: string[];
|
|
62
64
|
all?: boolean;
|
|
@@ -83,9 +85,10 @@ export interface GitRemoteAddOpts extends GitRequestOpts {
|
|
|
83
85
|
overwrite?: boolean;
|
|
84
86
|
}
|
|
85
87
|
export interface GitConfigOpts extends GitRequestOpts {
|
|
86
|
-
scope?:
|
|
88
|
+
scope?: GitConfigScope;
|
|
87
89
|
path?: string;
|
|
88
90
|
}
|
|
91
|
+
export type GitConfigScope = 'global' | 'local' | 'system';
|
|
89
92
|
export interface GitBranches {
|
|
90
93
|
path?: string;
|
|
91
94
|
branches: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
|
-
export { ApiError, AuthenticationError, ConflictError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
|
|
1
|
+
export { ApiError, AuthenticationError, BuildError, ConflictError, FileNotFoundError, FileUploadError, GitAuthError, GitUpstreamError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, SandboxNotFoundError, TemplateError, TimeoutError, VolumeError, } from './errors.js';
|
|
2
2
|
export { ConnectionConfig, KEEPALIVE_PING_INTERVAL_SEC } from './connectionConfig.js';
|
|
3
|
-
export {
|
|
3
|
+
export type { ConnectionOpts, Username } from './connectionConfig.js';
|
|
4
|
+
export { ControlClient as ApiClient } from './transport.js';
|
|
5
|
+
export { ALL_TRAFFIC, Sandbox, SandboxPaginator, SnapshotPaginator, getSignature, } from './sandbox.js';
|
|
4
6
|
export { Sandbox as CodeInterpreterSandbox } from './codeInterpreter.js';
|
|
5
|
-
export type { CreateSnapshotOpts, RestoreSnapshotOpts, SandboxCreateOpts, SandboxConnectOpts, SandboxInfo, SandboxInfoLifecycle, SandboxLifecycle, SandboxListOpts, SandboxMetrics, SandboxMetricsOpts, McpServer, McpServerName, SandboxNetworkSelector, SandboxNetworkUpdate, SandboxNetworkUpdateOpts, SandboxUrlOpts, SnapshotInfo, FileUrlInfo, } from './sandbox.js';
|
|
7
|
+
export type { CreateSnapshotOpts, RestoreSnapshotOpts, SandboxApiOpts, SandboxCreateOpts, SandboxConnectOpts, SandboxInfo, SandboxInfoLifecycle, SandboxLifecycle, SandboxListOpts, SandboxMetrics, SandboxMetricsOpts, McpServer, McpServerName, SandboxNetworkInfo, SandboxNetworkOpts, SandboxNetworkRule, SandboxNetworkRuleInfo, SandboxNetworkRules, SandboxNetworkSelector, SandboxNetworkSelectorContext, SandboxNetworkTransform, SandboxNetworkUpdate, SandboxNetworkUpdateOpts, SandboxOpts, SandboxState, SandboxUrlOpts, SignatureOpts, SnapshotInfo, SnapshotListOpts, FileUrlInfo, } from './sandbox.js';
|
|
6
8
|
export type { CreateCodeContextOpts, RunCodeLanguage, RunCodeOpts, } from './codeInterpreter.js';
|
|
7
9
|
export { Context as CodeInterpreterContext, Execution as CodeInterpreterExecution, ExecutionError as CodeInterpreterExecutionError, OutputMessage as CodeInterpreterOutputMessage, Result as CodeInterpreterResult, } from './codeInterpreter.js';
|
|
8
10
|
export { CommandExitError, CommandHandle, Commands } from './commands.js';
|
|
9
|
-
export type { CommandResult, CommandStartOpts, ProcessInfo } from './commands.js';
|
|
11
|
+
export type { CommandConnectOpts, CommandRequestOpts, CommandResult, CommandStartOpts, ProcessInfo, PtyOutput, Stderr, Stdout, } from './commands.js';
|
|
10
12
|
export { Process, ProcessManager, ProcessMessage, ProcessOutput } from './process.js';
|
|
11
13
|
export type { ProcessOpts } from './process.js';
|
|
12
|
-
export { FileType, Filesystem, FilesystemWatcher, WatchHandle } from './filesystem.js';
|
|
14
|
+
export { FileType, Filesystem, FilesystemEventType, FilesystemWatcher, WatchHandle, } from './filesystem.js';
|
|
13
15
|
export type { EntryInfo, FilesystemEvent, FilesystemReadOpts, FilesystemRequestOpts, FilesystemWriteOpts, WatchOpts, WriteData, WriteEntry, WriteInfo, } from './filesystem.js';
|
|
14
16
|
export { Git } from './git.js';
|
|
15
|
-
export type { GitAddOpts, GitAuthOpts, GitBranches, GitBranchOpts, GitCloneOpts, GitCommandResult, GitConfigOpts, GitConfigureUserOpts, GitCredentialOpts, GitCommitOpts, GitFileStatus, GitInitOpts, GitPullOpts, GitPushOpts, GitRemoteAddOpts, GitResetMode, GitResetOpts, GitRestoreOpts, GitRequestOpts, GitStatus, } from './git.js';
|
|
17
|
+
export type { GitAddOpts, GitAuthOpts, GitBranches, GitBranchOpts, GitCloneOpts, GitCommandResult, GitConfigScope, GitConfigOpts, GitConfigureUserOpts, GitCredentialOpts, GitCommitOpts, GitDangerouslyAuthenticateOpts, GitDeleteBranchOpts, GitFileStatus, GitInitOpts, GitPullOpts, GitPushOpts, GitRemoteAddOpts, GitResetMode, GitResetOpts, GitRestoreOpts, GitRequestOpts, GitStatus, } from './git.js';
|
|
16
18
|
export { Pty } from './pty.js';
|
|
17
19
|
export type { PtyConnectOpts, PtyCreateOpts, PtySize } from './pty.js';
|
|
18
20
|
export { Terminal, TerminalManager, TerminalOutput } from './terminal.js';
|
|
19
21
|
export type { TerminalOpts } from './terminal.js';
|
|
20
|
-
export { Volume } from './volume.js';
|
|
21
|
-
export type { VolumeApiParams,
|
|
22
|
+
export { Volume, VolumeConnectionConfig, VolumeFileType } from './volume.js';
|
|
23
|
+
export type { VolumeAndToken, VolumeApiParams, VolumeApiOpts, VolumeEntryStat, VolumeInfo, VolumeListFilesOpts, VolumeListOpts, VolumeMetadataOpts, VolumeMetadataOptions, VolumeReadFileOpts, VolumeReadFormat, VolumeWriteData, VolumeWriteFileOpts, VolumeWriteOptions, } from './volume.js';
|
|
22
24
|
export { ProcessSocket, base64DecodeBytes, base64DecodeText, base64Encode } from './processSocket.js';
|
|
23
|
-
export { ReadyCmd, Template, TemplateBase, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, } from './template.js';
|
|
24
|
-
export type { BuildInfo, BuildOptions, BuildStatusReason, CopyItem, GetBuildStatusOptions,
|
|
25
|
+
export { ReadyCmd, Template, TemplateBase, LogEntry, LogEntryEnd, LogEntryStart, defaultBuildLogger, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, } from './template.js';
|
|
26
|
+
export type { BuildInfo, BuildOptions, BuildStatusReason, CopyItem, GetBuildStatusOptions, LogEntryLevel, Logger, ReadyCommand, TemplateBuildStatus, TemplateBuildStatusResponse, TemplateBuilder, TemplateClass, TemplateFactory, TemplateFinal, TemplateFromImage, TemplateOptions, TemplateTag, TemplateTagInfo, } from './template.js';
|
|
27
|
+
export interface components {
|
|
28
|
+
schemas: Record<string, unknown>;
|
|
29
|
+
responses: Record<string, unknown>;
|
|
30
|
+
parameters: Record<string, unknown>;
|
|
31
|
+
requestBodies: Record<string, unknown>;
|
|
32
|
+
headers: Record<string, unknown>;
|
|
33
|
+
pathItems: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export type paths = Record<string, unknown>;
|
|
36
|
+
export { Sandbox as default } from './sandbox.js';
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export { ApiError, AuthenticationError, ConflictError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
|
|
1
|
+
export { ApiError, AuthenticationError, BuildError, ConflictError, FileNotFoundError, FileUploadError, GitAuthError, GitUpstreamError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, SandboxNotFoundError, TemplateError, TimeoutError, VolumeError, } from './errors.js';
|
|
2
2
|
export { ConnectionConfig, KEEPALIVE_PING_INTERVAL_SEC } from './connectionConfig.js';
|
|
3
|
-
export {
|
|
3
|
+
export { ControlClient as ApiClient } from './transport.js';
|
|
4
|
+
export { ALL_TRAFFIC, Sandbox, SandboxPaginator, SnapshotPaginator, getSignature, } from './sandbox.js';
|
|
4
5
|
export { Sandbox as CodeInterpreterSandbox } from './codeInterpreter.js';
|
|
5
6
|
export { Context as CodeInterpreterContext, Execution as CodeInterpreterExecution, ExecutionError as CodeInterpreterExecutionError, OutputMessage as CodeInterpreterOutputMessage, Result as CodeInterpreterResult, } from './codeInterpreter.js';
|
|
6
7
|
export { CommandExitError, CommandHandle, Commands } from './commands.js';
|
|
7
8
|
export { Process, ProcessManager, ProcessMessage, ProcessOutput } from './process.js';
|
|
8
|
-
export { FileType, Filesystem, FilesystemWatcher, WatchHandle } from './filesystem.js';
|
|
9
|
+
export { FileType, Filesystem, FilesystemEventType, FilesystemWatcher, WatchHandle, } from './filesystem.js';
|
|
9
10
|
export { Git } from './git.js';
|
|
10
11
|
export { Pty } from './pty.js';
|
|
11
12
|
export { Terminal, TerminalManager, TerminalOutput } from './terminal.js';
|
|
12
|
-
export { Volume } from './volume.js';
|
|
13
|
+
export { Volume, VolumeConnectionConfig, VolumeFileType } from './volume.js';
|
|
13
14
|
export { ProcessSocket, base64DecodeBytes, base64DecodeText, base64Encode } from './processSocket.js';
|
|
14
|
-
export { ReadyCmd, Template, TemplateBase, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, } from './template.js';
|
|
15
|
+
export { ReadyCmd, Template, TemplateBase, LogEntry, LogEntryEnd, LogEntryStart, defaultBuildLogger, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, } from './template.js';
|
|
16
|
+
export { Sandbox as default } from './sandbox.js';
|
package/dist/process.js
CHANGED
|
@@ -40,11 +40,15 @@ export class ProcessOutput {
|
|
|
40
40
|
this._error = true;
|
|
41
41
|
}
|
|
42
42
|
replace(result) {
|
|
43
|
+
const streamedStdout = this.stdout;
|
|
44
|
+
const streamedStderr = this.stderr;
|
|
43
45
|
this.messages = [];
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
this.
|
|
46
|
+
const stdout = result.stdout || streamedStdout;
|
|
47
|
+
const stderr = result.stderr || streamedStderr;
|
|
48
|
+
if (stdout)
|
|
49
|
+
this.addStdout(processMessage(stdout, false));
|
|
50
|
+
if (stderr)
|
|
51
|
+
this.addStderr(processMessage(stderr, true));
|
|
48
52
|
this.setExitCode(result.exitCode);
|
|
49
53
|
}
|
|
50
54
|
}
|
package/dist/processSocket.d.ts
CHANGED
|
@@ -9,19 +9,31 @@ export declare class ProcessSocket implements AsyncIterable<ProcessFrame> {
|
|
|
9
9
|
private ws?;
|
|
10
10
|
private queue;
|
|
11
11
|
private waiters;
|
|
12
|
+
private ackWaiters;
|
|
12
13
|
private closed;
|
|
13
14
|
private keepalive?;
|
|
14
15
|
constructor(baseUrl: string, token: string, path: string, requestTimeoutMs?: number, headers?: Record<string, string>);
|
|
15
16
|
connect(): Promise<this>;
|
|
16
|
-
sendJson(payload: ProcessFrame): void
|
|
17
|
-
sendStdin(data: string | Uint8Array
|
|
18
|
-
|
|
17
|
+
sendJson(payload: ProcessFrame): Promise<void>;
|
|
18
|
+
sendStdin(data: string | Uint8Array, opts?: {
|
|
19
|
+
requestTimeoutMs?: number;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
closeStdin(opts?: {
|
|
23
|
+
requestTimeoutMs?: number;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
}): Promise<void>;
|
|
19
26
|
close(): void;
|
|
20
27
|
[Symbol.asyncIterator](): AsyncIterator<ProcessFrame>;
|
|
21
28
|
private next;
|
|
22
29
|
private onMessage;
|
|
23
30
|
private finish;
|
|
24
31
|
private flushDone;
|
|
32
|
+
private waitForControlAck;
|
|
33
|
+
private resolveControlAck;
|
|
34
|
+
private rejectControlAcks;
|
|
35
|
+
private removeControlAck;
|
|
36
|
+
private removeSignalListener;
|
|
25
37
|
}
|
|
26
38
|
export declare function base64Encode(bytes: Uint8Array): string;
|
|
27
39
|
export declare function base64DecodeText(value: unknown): string;
|
package/dist/processSocket.js
CHANGED
|
@@ -12,6 +12,7 @@ export class ProcessSocket {
|
|
|
12
12
|
ws;
|
|
13
13
|
queue = [];
|
|
14
14
|
waiters = [];
|
|
15
|
+
ackWaiters = new Map();
|
|
15
16
|
closed = false;
|
|
16
17
|
keepalive;
|
|
17
18
|
constructor(baseUrl, token, path, requestTimeoutMs = 60_000, headers = {}) {
|
|
@@ -47,18 +48,41 @@ export class ProcessSocket {
|
|
|
47
48
|
}, KEEPALIVE_PING_INTERVAL_SEC * 1000);
|
|
48
49
|
return this;
|
|
49
50
|
}
|
|
50
|
-
sendJson(payload) {
|
|
51
|
+
async sendJson(payload) {
|
|
51
52
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
52
53
|
throw new SandboxError('process websocket is not connected');
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
await new Promise((resolve, reject) => {
|
|
56
|
+
this.ws.send(JSON.stringify(payload), (error) => {
|
|
57
|
+
if (error)
|
|
58
|
+
reject(error);
|
|
59
|
+
else
|
|
60
|
+
resolve();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
55
63
|
}
|
|
56
|
-
sendStdin(data) {
|
|
64
|
+
async sendStdin(data, opts = {}) {
|
|
57
65
|
const raw = typeof data === 'string' ? new TextEncoder().encode(data) : data;
|
|
58
|
-
this.
|
|
66
|
+
const ack = this.waitForControlAck('stdin_ack', opts);
|
|
67
|
+
try {
|
|
68
|
+
await this.sendJson({ type: 'stdin', data: base64Encode(raw) });
|
|
69
|
+
await ack.promise;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
ack.cancel();
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
59
75
|
}
|
|
60
|
-
closeStdin() {
|
|
61
|
-
this.
|
|
76
|
+
async closeStdin(opts = {}) {
|
|
77
|
+
const ack = this.waitForControlAck('close_stdin_ack', opts);
|
|
78
|
+
try {
|
|
79
|
+
await this.sendJson({ type: 'close_stdin' });
|
|
80
|
+
await ack.promise;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
ack.cancel();
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
62
86
|
}
|
|
63
87
|
close() {
|
|
64
88
|
this.closed = true;
|
|
@@ -86,6 +110,10 @@ export class ProcessSocket {
|
|
|
86
110
|
const frame = JSON.parse(text);
|
|
87
111
|
if (frame.type === 'pong' || frame.type === 'ready')
|
|
88
112
|
return;
|
|
113
|
+
if (frame.type === 'stdin_ack' || frame.type === 'close_stdin_ack') {
|
|
114
|
+
this.resolveControlAck(String(frame.type));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
89
117
|
if (frame.type === 'error') {
|
|
90
118
|
this.finish(new SandboxError(String(frame.message ?? frame.code ?? 'process error')));
|
|
91
119
|
return;
|
|
@@ -112,6 +140,7 @@ export class ProcessSocket {
|
|
|
112
140
|
else
|
|
113
141
|
this.queue.push(frame);
|
|
114
142
|
}
|
|
143
|
+
this.rejectControlAcks(error ?? new SandboxError('process websocket closed before acknowledgement'));
|
|
115
144
|
this.flushDone();
|
|
116
145
|
}
|
|
117
146
|
flushDone() {
|
|
@@ -119,6 +148,79 @@ export class ProcessSocket {
|
|
|
119
148
|
waiter({ done: true, value: undefined });
|
|
120
149
|
}
|
|
121
150
|
}
|
|
151
|
+
waitForControlAck(type, opts = {}) {
|
|
152
|
+
if (opts.signal?.aborted) {
|
|
153
|
+
return {
|
|
154
|
+
promise: Promise.reject(new SandboxError('process control acknowledgement aborted')),
|
|
155
|
+
cancel: () => { },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
let entry;
|
|
159
|
+
const promise = new Promise((resolve, reject) => {
|
|
160
|
+
const rejectWithAbort = () => {
|
|
161
|
+
this.removeControlAck(type, entry);
|
|
162
|
+
clearTimeout(entry.timer);
|
|
163
|
+
reject(new SandboxError('process control acknowledgement aborted'));
|
|
164
|
+
};
|
|
165
|
+
const timer = setTimeout(() => {
|
|
166
|
+
this.removeControlAck(type, entry);
|
|
167
|
+
this.removeSignalListener(entry);
|
|
168
|
+
reject(new TimeoutError());
|
|
169
|
+
}, opts.requestTimeoutMs ?? this.requestTimeoutMs);
|
|
170
|
+
entry = { resolve, reject, timer, signal: opts.signal };
|
|
171
|
+
if (opts.signal) {
|
|
172
|
+
entry.abort = rejectWithAbort;
|
|
173
|
+
opts.signal.addEventListener('abort', rejectWithAbort, { once: true });
|
|
174
|
+
}
|
|
175
|
+
const waiters = this.ackWaiters.get(type) ?? [];
|
|
176
|
+
waiters.push(entry);
|
|
177
|
+
this.ackWaiters.set(type, waiters);
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
promise,
|
|
181
|
+
cancel: () => {
|
|
182
|
+
this.removeControlAck(type, entry);
|
|
183
|
+
clearTimeout(entry.timer);
|
|
184
|
+
if (entry.abort)
|
|
185
|
+
opts.signal?.removeEventListener('abort', entry.abort);
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
resolveControlAck(type) {
|
|
190
|
+
const entry = this.ackWaiters.get(type)?.shift();
|
|
191
|
+
if (!entry)
|
|
192
|
+
return;
|
|
193
|
+
clearTimeout(entry.timer);
|
|
194
|
+
if (entry.abort)
|
|
195
|
+
this.removeSignalListener(entry);
|
|
196
|
+
entry.resolve();
|
|
197
|
+
}
|
|
198
|
+
rejectControlAcks(error) {
|
|
199
|
+
for (const waiters of this.ackWaiters.values()) {
|
|
200
|
+
for (const entry of waiters.splice(0)) {
|
|
201
|
+
clearTimeout(entry.timer);
|
|
202
|
+
if (entry.abort)
|
|
203
|
+
this.removeSignalListener(entry);
|
|
204
|
+
entry.reject(error);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
this.ackWaiters.clear();
|
|
208
|
+
}
|
|
209
|
+
removeControlAck(type, entry) {
|
|
210
|
+
const waiters = this.ackWaiters.get(type);
|
|
211
|
+
if (!waiters)
|
|
212
|
+
return;
|
|
213
|
+
const index = waiters.indexOf(entry);
|
|
214
|
+
if (index !== -1)
|
|
215
|
+
waiters.splice(index, 1);
|
|
216
|
+
if (waiters.length === 0)
|
|
217
|
+
this.ackWaiters.delete(type);
|
|
218
|
+
}
|
|
219
|
+
removeSignalListener(entry) {
|
|
220
|
+
if (entry.abort)
|
|
221
|
+
entry.signal?.removeEventListener('abort', entry.abort);
|
|
222
|
+
entry.abort = undefined;
|
|
223
|
+
}
|
|
122
224
|
}
|
|
123
225
|
export function base64Encode(bytes) {
|
|
124
226
|
return Buffer.from(bytes).toString('base64');
|
package/dist/pty.js
CHANGED
|
@@ -15,7 +15,7 @@ export class Pty {
|
|
|
15
15
|
const envs = { TERM: 'xterm-256color', LANG: 'C.UTF-8', LC_ALL: 'C.UTF-8', ...(opts.envs ?? {}) };
|
|
16
16
|
const size = opts.size ?? { cols: opts.cols ?? 80, rows: opts.rows ?? 24 };
|
|
17
17
|
const args = opts.cmd === undefined ? ['-i', '-l'] : ['-l', '-c', opts.cmd];
|
|
18
|
-
socket.sendJson({
|
|
18
|
+
await socket.sendJson({
|
|
19
19
|
type: 'start',
|
|
20
20
|
cmd: '/bin/bash',
|
|
21
21
|
args,
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { Pty } from './pty.js';
|
|
|
7
7
|
import { ProcessManager } from './process.js';
|
|
8
8
|
import { TerminalManager } from './terminal.js';
|
|
9
9
|
import type { Volume } from './volume.js';
|
|
10
|
+
export declare const ALL_TRAFFIC = "0.0.0.0/0";
|
|
10
11
|
export interface SandboxCreateOpts extends ConnectionOpts {
|
|
11
12
|
/** Template slug to create. Defaults to "base". */
|
|
12
13
|
template?: string;
|
|
@@ -31,7 +32,18 @@ export interface SandboxLifecycle {
|
|
|
31
32
|
onTimeout: 'kill' | 'pause';
|
|
32
33
|
autoResume?: boolean;
|
|
33
34
|
}
|
|
34
|
-
export type
|
|
35
|
+
export type SandboxNetworkTransform = {
|
|
36
|
+
headers?: Record<string, string>;
|
|
37
|
+
};
|
|
38
|
+
export type SandboxNetworkRule = {
|
|
39
|
+
transform?: SandboxNetworkTransform;
|
|
40
|
+
};
|
|
41
|
+
export type SandboxNetworkRules = Record<string, SandboxNetworkRule[]> | Map<string, SandboxNetworkRule[]>;
|
|
42
|
+
export interface SandboxNetworkSelectorContext {
|
|
43
|
+
allTraffic: string;
|
|
44
|
+
rules: Map<string, SandboxNetworkRule[]>;
|
|
45
|
+
}
|
|
46
|
+
export type SandboxNetworkSelector = string | string[] | ((ctx: SandboxNetworkSelectorContext) => string[]);
|
|
35
47
|
export interface SandboxNetworkUpdate {
|
|
36
48
|
allowOut?: SandboxNetworkSelector;
|
|
37
49
|
denyOut?: SandboxNetworkSelector;
|
|
@@ -41,9 +53,15 @@ export interface SandboxNetworkUpdate {
|
|
|
41
53
|
egressProfile?: string;
|
|
42
54
|
egressProfiles?: string[];
|
|
43
55
|
networkClass?: string;
|
|
44
|
-
rules?:
|
|
56
|
+
rules?: SandboxNetworkRules;
|
|
45
57
|
maskRequestHost?: string;
|
|
46
58
|
}
|
|
59
|
+
export type SandboxNetworkOpts = SandboxNetworkUpdate;
|
|
60
|
+
export type SandboxNetworkInfo = SandboxNetworkUpdate;
|
|
61
|
+
export type SandboxNetworkRuleInfo = Record<string, unknown>;
|
|
62
|
+
export type SandboxOpts = SandboxCreateOpts;
|
|
63
|
+
export type SandboxApiOpts = ConnectionOpts;
|
|
64
|
+
export type SandboxState = string;
|
|
47
65
|
export interface SandboxNetworkUpdateOpts extends ConnectionOpts {
|
|
48
66
|
}
|
|
49
67
|
export interface SandboxConnectOpts extends ConnectionOpts {
|
|
@@ -142,6 +160,17 @@ export interface RestoreSnapshotOpts extends ConnectionOpts {
|
|
|
142
160
|
snapshotId?: string | number;
|
|
143
161
|
timeoutMs?: number;
|
|
144
162
|
}
|
|
163
|
+
export interface SignatureOpts {
|
|
164
|
+
path: string;
|
|
165
|
+
operation: 'read' | 'write';
|
|
166
|
+
user?: string;
|
|
167
|
+
expirationInSeconds?: number;
|
|
168
|
+
envdAccessToken?: string;
|
|
169
|
+
}
|
|
170
|
+
export declare function getSignature({ path, operation, user, expirationInSeconds, envdAccessToken, }: SignatureOpts): Promise<{
|
|
171
|
+
signature: string;
|
|
172
|
+
expiration: number | null;
|
|
173
|
+
}>;
|
|
145
174
|
/** Paginator for listing sandbox snapshots. */
|
|
146
175
|
export declare class SnapshotPaginator {
|
|
147
176
|
private readonly opts;
|
|
@@ -195,7 +224,7 @@ export declare class Sandbox {
|
|
|
195
224
|
sandbox?: Record<string, unknown>;
|
|
196
225
|
envs?: Record<string, string>;
|
|
197
226
|
});
|
|
198
|
-
/**
|
|
227
|
+
/** Unique sandbox identifier. */
|
|
199
228
|
get id(): string;
|
|
200
229
|
static create(opts?: SandboxCreateOpts): Promise<Sandbox>;
|
|
201
230
|
static create(template: string, opts?: SandboxCreateOpts): Promise<Sandbox>;
|
|
@@ -232,6 +261,8 @@ export declare class Sandbox {
|
|
|
232
261
|
setTimeout(timeoutMs: number, opts?: SandboxRequestOpts): Promise<void>;
|
|
233
262
|
/** Fetch control-plane metadata for a sandbox by id. */
|
|
234
263
|
static getInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
|
|
264
|
+
/** Fetch full control-plane metadata for a sandbox by id. */
|
|
265
|
+
static getFullInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
|
|
235
266
|
/** Fetch the latest control-plane metadata for this sandbox. */
|
|
236
267
|
getInfo(opts?: SandboxRequestOpts): Promise<SandboxInfo>;
|
|
237
268
|
/** Fetch latest sandbox metrics. */
|
|
@@ -240,8 +271,6 @@ export declare class Sandbox {
|
|
|
240
271
|
createSnapshot(opts?: CreateSnapshotOpts): Promise<SnapshotInfo>;
|
|
241
272
|
/** Delete a snapshot by id. */
|
|
242
273
|
deleteSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<boolean>;
|
|
243
|
-
/** Watasu-native alias for `createSnapshot`. */
|
|
244
|
-
checkpoint(opts?: CreateSnapshotOpts): Promise<SnapshotInfo>;
|
|
245
274
|
/** List checkpoints for this sandbox using snapshot naming. */
|
|
246
275
|
listSnapshots(opts?: Omit<SnapshotListOpts, 'sandboxId'>): SnapshotPaginator;
|
|
247
276
|
/** Restore a checkpoint into a new sandbox and return its control-plane info. */
|