@watasu/sdk 0.1.5 → 0.1.24

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/index.d.ts CHANGED
@@ -1,9 +1,19 @@
1
- export { ApiError, AuthenticationError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
1
+ export { ApiError, AuthenticationError, ConflictError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
2
2
  export { ConnectionConfig, KEEPALIVE_PING_INTERVAL_SEC } from './connectionConfig.js';
3
- export { Sandbox, SnapshotPaginator } from './sandbox.js';
4
- export type { CreateSnapshotOpts, RestoreSnapshotOpts, SandboxCreateOpts, SandboxConnectOpts, SandboxInfo, SandboxMetrics, SnapshotInfo, } from './sandbox.js';
3
+ export { Sandbox, SandboxPaginator, SnapshotPaginator } from './sandbox.js';
4
+ export type { CreateSnapshotOpts, RestoreSnapshotOpts, SandboxCreateOpts, SandboxConnectOpts, SandboxInfo, SandboxListOpts, SandboxMetrics, McpServer, McpServerName, SandboxNetworkSelector, SandboxNetworkUpdate, SandboxNetworkUpdateOpts, SandboxUrlOpts, SnapshotInfo, FileUrlInfo, } from './sandbox.js';
5
5
  export { CommandExitError, CommandHandle, Commands } from './commands.js';
6
6
  export type { CommandResult, CommandStartOpts, ProcessInfo } from './commands.js';
7
- export { FileType, Filesystem } from './filesystem.js';
8
- export type { EntryInfo, WriteInfo } from './filesystem.js';
9
- export { ProcessSocket, base64DecodeText, base64Encode } from './processSocket.js';
7
+ export { Process, ProcessManager, ProcessMessage, ProcessOutput } from './process.js';
8
+ export type { ProcessOpts } from './process.js';
9
+ export { FileType, Filesystem, FilesystemWatcher, WatchHandle } from './filesystem.js';
10
+ export type { EntryInfo, FilesystemEvent, FilesystemReadOpts, FilesystemRequestOpts, FilesystemWriteOpts, WatchOpts, WriteData, WriteEntry, WriteInfo, } from './filesystem.js';
11
+ export { Git } from './git.js';
12
+ 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';
13
+ export { Pty } from './pty.js';
14
+ export type { PtyConnectOpts, PtyCreateOpts, PtySize } from './pty.js';
15
+ export { Terminal, TerminalManager, TerminalOutput } from './terminal.js';
16
+ export type { TerminalOpts } from './terminal.js';
17
+ export { ProcessSocket, base64DecodeBytes, base64DecodeText, base64Encode } from './processSocket.js';
18
+ export { ReadyCmd, Template, TemplateBase, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, waitForUrl, } from './template.js';
19
+ export type { BuildInfo, BuildOptions, BuildStatusReason, CopyItem, GetBuildStatusOptions, LogEntry, ReadyCommand, TemplateBuildStatus, TemplateBuildStatusResponse, TemplateBuilder, TemplateClass, TemplateFactory, TemplateFinal, TemplateFromImage, TemplateOptions, TemplateTag, TemplateTagInfo, } from './template.js';
package/dist/index.js CHANGED
@@ -1,6 +1,11 @@
1
- export { ApiError, AuthenticationError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
1
+ export { ApiError, AuthenticationError, ConflictError, FileNotFoundError, InvalidArgumentError, NotEnoughSpaceError, NotFoundError, NotImplementedError, RateLimitError, SandboxError, TimeoutError, } from './errors.js';
2
2
  export { ConnectionConfig, KEEPALIVE_PING_INTERVAL_SEC } from './connectionConfig.js';
3
- export { Sandbox, SnapshotPaginator } from './sandbox.js';
3
+ export { Sandbox, SandboxPaginator, SnapshotPaginator } from './sandbox.js';
4
4
  export { CommandExitError, CommandHandle, Commands } from './commands.js';
5
- export { FileType, Filesystem } from './filesystem.js';
6
- export { ProcessSocket, base64DecodeText, base64Encode } from './processSocket.js';
5
+ export { Process, ProcessManager, ProcessMessage, ProcessOutput } from './process.js';
6
+ export { FileType, Filesystem, FilesystemWatcher, WatchHandle } from './filesystem.js';
7
+ export { Git } from './git.js';
8
+ export { Pty } from './pty.js';
9
+ export { Terminal, TerminalManager, TerminalOutput } from './terminal.js';
10
+ export { ProcessSocket, base64DecodeBytes, base64DecodeText, base64Encode } from './processSocket.js';
11
+ export { ReadyCmd, Template, TemplateBase, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL, waitForUrl, } from './template.js';
@@ -0,0 +1,56 @@
1
+ import { CommandHandle, CommandResult, Commands, CommandStartOpts } from './commands.js';
2
+ /** A message emitted by a sandbox process. */
3
+ export declare class ProcessMessage {
4
+ readonly line: string;
5
+ /** Unix epoch in nanoseconds. */
6
+ readonly timestamp: number;
7
+ readonly error: boolean;
8
+ constructor(line: string,
9
+ /** Unix epoch in nanoseconds. */
10
+ timestamp: number, error: boolean);
11
+ toString(): string;
12
+ }
13
+ /** Captured output from a sandbox process. */
14
+ export declare class ProcessOutput {
15
+ private messages;
16
+ private _finished;
17
+ private _error;
18
+ private _exitCode;
19
+ get error(): boolean;
20
+ get exitCode(): number | undefined;
21
+ get stdout(): string;
22
+ get stderr(): string;
23
+ addStdout(message: ProcessMessage): void;
24
+ addStderr(message: ProcessMessage): void;
25
+ setExitCode(exitCode: number): void;
26
+ replace(result: CommandResult): void;
27
+ }
28
+ export interface ProcessOpts extends Omit<CommandStartOpts, 'cmd' | 'args' | 'onStdout' | 'onStderr' | 'onExit'> {
29
+ cmd: string;
30
+ onStdout?: (out: ProcessMessage) => Promise<void> | void;
31
+ onStderr?: (out: ProcessMessage) => Promise<void> | void;
32
+ onExit?: ((exitCode: number) => Promise<void> | void) | (() => Promise<void> | void);
33
+ }
34
+ /** A running sandbox process. */
35
+ export declare class Process {
36
+ readonly processID: string;
37
+ private readonly handle;
38
+ readonly output: ProcessOutput;
39
+ private readonly onExit?;
40
+ readonly finished: Promise<ProcessOutput>;
41
+ private waitPromise?;
42
+ constructor(processID: string, handle: CommandHandle, output: ProcessOutput, onExit?: ((exitCode: number) => Promise<void> | void) | undefined);
43
+ kill(): Promise<void>;
44
+ wait(timeout?: number): Promise<ProcessOutput>;
45
+ private waitOnce;
46
+ sendStdin(data: string): Promise<void>;
47
+ }
48
+ /** Manager for starting and interacting with sandbox processes. */
49
+ export declare class ProcessManager {
50
+ private readonly commands;
51
+ constructor(commands: Commands);
52
+ start(cmd: string): Promise<Process>;
53
+ start(opts: ProcessOpts): Promise<Process>;
54
+ startAndWait(cmd: string): Promise<ProcessOutput>;
55
+ startAndWait(opts: ProcessOpts): Promise<ProcessOutput>;
56
+ }
@@ -0,0 +1,137 @@
1
+ import { CommandExitError } from './commands.js';
2
+ import { TimeoutError } from './errors.js';
3
+ /** A message emitted by a sandbox process. */
4
+ export class ProcessMessage {
5
+ line;
6
+ timestamp;
7
+ error;
8
+ constructor(line,
9
+ /** Unix epoch in nanoseconds. */
10
+ timestamp, error) {
11
+ this.line = line;
12
+ this.timestamp = timestamp;
13
+ this.error = error;
14
+ }
15
+ toString() {
16
+ return this.line;
17
+ }
18
+ }
19
+ /** Captured output from a sandbox process. */
20
+ export class ProcessOutput {
21
+ messages = [];
22
+ _finished = false;
23
+ _error = false;
24
+ _exitCode;
25
+ get error() { return this._error; }
26
+ get exitCode() { return this._exitCode; }
27
+ get stdout() { return this.messages.filter((message) => !message.error).map(String).join(''); }
28
+ get stderr() { return this.messages.filter((message) => message.error).map(String).join(''); }
29
+ addStdout(message) {
30
+ this.messages.push(message);
31
+ }
32
+ addStderr(message) {
33
+ this.messages.push(message);
34
+ this._error = true;
35
+ }
36
+ setExitCode(exitCode) {
37
+ this._exitCode = exitCode;
38
+ this._finished = true;
39
+ if (exitCode !== 0)
40
+ this._error = true;
41
+ }
42
+ replace(result) {
43
+ this.messages = [];
44
+ if (result.stdout)
45
+ this.addStdout(processMessage(result.stdout, false));
46
+ if (result.stderr)
47
+ this.addStderr(processMessage(result.stderr, true));
48
+ this.setExitCode(result.exitCode);
49
+ }
50
+ }
51
+ /** A running sandbox process. */
52
+ export class Process {
53
+ processID;
54
+ handle;
55
+ output;
56
+ onExit;
57
+ finished;
58
+ waitPromise;
59
+ constructor(processID, handle, output, onExit) {
60
+ this.processID = processID;
61
+ this.handle = handle;
62
+ this.output = output;
63
+ this.onExit = onExit;
64
+ this.waitPromise = this.waitOnce();
65
+ this.finished = this.waitPromise;
66
+ }
67
+ async kill() {
68
+ await this.handle.kill();
69
+ }
70
+ async wait(timeout) {
71
+ if (!this.waitPromise)
72
+ this.waitPromise = this.waitOnce();
73
+ return waitFor(this.waitPromise, timeout);
74
+ }
75
+ async waitOnce() {
76
+ try {
77
+ this.output.replace(await this.handle.wait());
78
+ }
79
+ catch (error) {
80
+ if (error instanceof CommandExitError) {
81
+ this.output.replace(error);
82
+ }
83
+ else {
84
+ throw error;
85
+ }
86
+ }
87
+ await this.onExit?.(this.output.exitCode ?? 0);
88
+ return this.output;
89
+ }
90
+ async sendStdin(data) {
91
+ await this.handle.sendStdin(data);
92
+ }
93
+ }
94
+ function waitFor(promise, timeoutMs) {
95
+ if (timeoutMs === undefined || timeoutMs <= 0)
96
+ return promise;
97
+ return new Promise((resolve, reject) => {
98
+ const timer = setTimeout(() => reject(new TimeoutError()), timeoutMs);
99
+ promise.then(resolve, reject).finally(() => clearTimeout(timer));
100
+ });
101
+ }
102
+ /** Manager for starting and interacting with sandbox processes. */
103
+ export class ProcessManager {
104
+ commands;
105
+ constructor(commands) {
106
+ this.commands = commands;
107
+ }
108
+ async start(cmdOrOpts) {
109
+ const opts = processOpts(cmdOrOpts);
110
+ const { cmd, onStdout, onStderr, onExit, ...commandOpts } = opts;
111
+ const output = new ProcessOutput();
112
+ const handle = await this.commands.start(cmd, {
113
+ ...commandOpts,
114
+ onStdout: async (data) => {
115
+ const message = processMessage(data, false);
116
+ output.addStdout(message);
117
+ await onStdout?.(message);
118
+ },
119
+ onStderr: async (data) => {
120
+ const message = processMessage(data, true);
121
+ output.addStderr(message);
122
+ await onStderr?.(message);
123
+ },
124
+ });
125
+ return new Process(String(handle.pid), handle, output, onExit);
126
+ }
127
+ async startAndWait(cmdOrOpts) {
128
+ const process = await this.start(cmdOrOpts);
129
+ return process.wait(typeof cmdOrOpts === 'string' ? undefined : cmdOrOpts.timeout);
130
+ }
131
+ }
132
+ function processOpts(cmdOrOpts) {
133
+ return typeof cmdOrOpts === 'string' ? { cmd: cmdOrOpts } : cmdOrOpts;
134
+ }
135
+ function processMessage(line, error) {
136
+ return new ProcessMessage(line, Date.now() * 1_000_000, error);
137
+ }
@@ -14,6 +14,7 @@ export declare class ProcessSocket implements AsyncIterable<ProcessFrame> {
14
14
  connect(): Promise<this>;
15
15
  sendJson(payload: ProcessFrame): void;
16
16
  sendStdin(data: string | Uint8Array): void;
17
+ closeStdin(): void;
17
18
  close(): void;
18
19
  [Symbol.asyncIterator](): AsyncIterator<ProcessFrame>;
19
20
  private next;
@@ -23,3 +24,4 @@ export declare class ProcessSocket implements AsyncIterable<ProcessFrame> {
23
24
  }
24
25
  export declare function base64Encode(bytes: Uint8Array): string;
25
26
  export declare function base64DecodeText(value: unknown): string;
27
+ export declare function base64DecodeBytes(value: unknown): Uint8Array;
@@ -55,6 +55,9 @@ export class ProcessSocket {
55
55
  const raw = typeof data === 'string' ? new TextEncoder().encode(data) : data;
56
56
  this.sendJson({ type: 'stdin', data: base64Encode(raw) });
57
57
  }
58
+ closeStdin() {
59
+ this.sendJson({ type: 'close_stdin' });
60
+ }
58
61
  close() {
59
62
  this.closed = true;
60
63
  if (this.keepalive)
@@ -122,12 +125,17 @@ export function base64DecodeText(value) {
122
125
  if (typeof value !== 'string')
123
126
  return String(value ?? '');
124
127
  try {
125
- return Buffer.from(value, 'base64').toString('utf8');
128
+ return Buffer.from(base64DecodeBytes(value)).toString('utf8');
126
129
  }
127
130
  catch {
128
131
  return value;
129
132
  }
130
133
  }
134
+ export function base64DecodeBytes(value) {
135
+ if (typeof value !== 'string')
136
+ return new TextEncoder().encode(String(value ?? ''));
137
+ return new Uint8Array(Buffer.from(value, 'base64'));
138
+ }
131
139
  function rawDataToText(message) {
132
140
  if (typeof message === 'string')
133
141
  return message;
package/dist/pty.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { CommandHandle, CommandStartOpts } from './commands.js';
2
+ import { ConnectionConfig } from './connectionConfig.js';
3
+ import { DataPlaneClient } from './transport.js';
4
+ export interface PtySize {
5
+ cols: number;
6
+ rows: number;
7
+ }
8
+ export interface PtyCreateOpts extends Omit<CommandStartOpts, 'background' | 'onStdout' | 'onStderr'> {
9
+ cols?: number;
10
+ rows?: number;
11
+ size?: PtySize;
12
+ cmd?: string;
13
+ onData?: (data: Uint8Array) => void | Promise<void>;
14
+ }
15
+ export interface PtyConnectOpts {
16
+ onData?: (data: Uint8Array) => void | Promise<void>;
17
+ timeoutMs?: number;
18
+ requestTimeoutMs?: number;
19
+ }
20
+ /** PTY helper backed by the sandbox process WebSocket runtime. */
21
+ export declare class Pty {
22
+ private readonly dataPlane;
23
+ private readonly config;
24
+ constructor(dataPlane: DataPlaneClient, config: ConnectionConfig);
25
+ /** Create an interactive shell PTY and return its live command handle. */
26
+ create(opts: PtyCreateOpts): Promise<CommandHandle>;
27
+ /** Connect to a running PTY by pid. */
28
+ connect(pid: number | string, opts?: PtyConnectOpts): Promise<CommandHandle>;
29
+ /** Send input bytes or text to a PTY. */
30
+ sendStdin(pid: number | string, data: string | Uint8Array, opts?: PtyConnectOpts): Promise<void>;
31
+ /** Alias for `sendStdin`. */
32
+ sendInput(pid: number | string, data: string | Uint8Array, opts?: PtyConnectOpts): Promise<void>;
33
+ /** Resize a running PTY. */
34
+ resize(pid: number | string, size: PtySize, opts?: PtyConnectOpts): Promise<void>;
35
+ /** Kill a running PTY. */
36
+ kill(pid: number | string): Promise<boolean>;
37
+ }
package/dist/pty.js ADDED
@@ -0,0 +1,90 @@
1
+ import { CommandHandle } from './commands.js';
2
+ import { ProcessSocket } from './processSocket.js';
3
+ import { SandboxError } from './errors.js';
4
+ /** PTY helper backed by the sandbox process WebSocket runtime. */
5
+ export class Pty {
6
+ dataPlane;
7
+ config;
8
+ constructor(dataPlane, config) {
9
+ this.dataPlane = dataPlane;
10
+ this.config = config;
11
+ }
12
+ /** Create an interactive shell PTY and return its live command handle. */
13
+ async create(opts) {
14
+ const socket = await new ProcessSocket(this.dataPlane.baseUrl, this.dataPlane.token, '/runtime/v1/process', opts.requestTimeoutMs ?? this.config.requestTimeoutMs).connect();
15
+ const envs = { TERM: 'xterm-256color', LANG: 'C.UTF-8', LC_ALL: 'C.UTF-8', ...(opts.envVars ?? opts.envs ?? {}) };
16
+ const size = opts.size ?? { cols: opts.cols ?? 80, rows: opts.rows ?? 24 };
17
+ const args = opts.cmd === undefined ? ['-i', '-l'] : ['-l', '-c', opts.cmd];
18
+ socket.sendJson({
19
+ type: 'start',
20
+ cmd: '/bin/bash',
21
+ args,
22
+ cwd: opts.cwd ?? opts.rootDir,
23
+ user: opts.user,
24
+ environment: envs,
25
+ envs,
26
+ stdin: true,
27
+ pty: { cols: size.cols, rows: size.rows },
28
+ timeout_ms: opts.timeoutMs ?? opts.timeout ?? 60_000,
29
+ });
30
+ const first = await nextStarted(socket);
31
+ const pid = framePid(first);
32
+ if (pid === undefined)
33
+ throw new SandboxError('PTY started frame did not include pid');
34
+ return new CommandHandle(pid, socket, () => this.kill(pid), withFirst(first, socket), undefined, undefined, opts.onData ?? opts.onPty);
35
+ }
36
+ /** Connect to a running PTY by pid. */
37
+ async connect(pid, opts = {}) {
38
+ const socket = await new ProcessSocket(this.dataPlane.baseUrl, this.dataPlane.token, `/runtime/v1/process/${pid}/connect?since=0`, opts.requestTimeoutMs ?? this.config.requestTimeoutMs).connect();
39
+ const first = await nextStarted(socket);
40
+ const actualPid = framePid(first) ?? pid;
41
+ return new CommandHandle(actualPid, socket, () => this.kill(actualPid), withFirst(first, socket), undefined, undefined, opts.onData);
42
+ }
43
+ /** Send input bytes or text to a PTY. */
44
+ async sendStdin(pid, data, opts = {}) {
45
+ const handle = await this.connect(pid, opts);
46
+ try {
47
+ await handle.sendStdin(data);
48
+ }
49
+ finally {
50
+ await handle.disconnect();
51
+ }
52
+ }
53
+ /** Alias for `sendStdin`. */
54
+ async sendInput(pid, data, opts = {}) {
55
+ return this.sendStdin(pid, data, opts);
56
+ }
57
+ /** Resize a running PTY. */
58
+ async resize(pid, size, opts = {}) {
59
+ const handle = await this.connect(pid, opts);
60
+ try {
61
+ await handle.resize(size);
62
+ }
63
+ finally {
64
+ await handle.disconnect();
65
+ }
66
+ }
67
+ /** Kill a running PTY. */
68
+ async kill(pid) {
69
+ await this.dataPlane.postJson(`/runtime/v1/process/${pid}/signal`, {
70
+ json: { signal: 'SIGKILL' },
71
+ });
72
+ return true;
73
+ }
74
+ }
75
+ async function nextStarted(events) {
76
+ for await (const frame of events) {
77
+ if (frame.type === 'started')
78
+ return frame;
79
+ }
80
+ throw new SandboxError('PTY ended before started frame');
81
+ }
82
+ async function* withFirst(first, rest) {
83
+ yield first;
84
+ yield* rest;
85
+ }
86
+ function framePid(frame) {
87
+ const process = frame.process && typeof frame.process === 'object' ? frame.process : {};
88
+ const pid = frame.pid ?? process.pid ?? process.id;
89
+ return typeof pid === 'number' || typeof pid === 'string' ? pid : undefined;
90
+ }
package/dist/sandbox.d.ts CHANGED
@@ -2,6 +2,10 @@ import { Commands } from './commands.js';
2
2
  import { ConnectionConfig, ConnectionOpts } from './connectionConfig.js';
3
3
  import { ControlClient } from './transport.js';
4
4
  import { Filesystem } from './filesystem.js';
5
+ import { Git } from './git.js';
6
+ import { Pty } from './pty.js';
7
+ import { ProcessManager } from './process.js';
8
+ import { TerminalManager } from './terminal.js';
5
9
  export interface SandboxCreateOpts extends ConnectionOpts {
6
10
  /** Template slug to create. Defaults to "base". */
7
11
  template?: string;
@@ -11,14 +15,44 @@ export interface SandboxCreateOpts extends ConnectionOpts {
11
15
  envs?: Record<string, string>;
12
16
  secure?: boolean;
13
17
  allowInternetAccess?: boolean;
18
+ network?: SandboxNetworkUpdate;
14
19
  team?: string;
15
- mcp?: unknown;
20
+ /** MCP gateway configuration to launch inside an `mcp-gateway` sandbox. */
21
+ mcp?: McpServer;
16
22
  volumeMounts?: unknown;
17
23
  }
24
+ export type SandboxNetworkSelector = string | string[];
25
+ export interface SandboxNetworkUpdate {
26
+ allowOut?: SandboxNetworkSelector;
27
+ denyOut?: SandboxNetworkSelector;
28
+ allowInternetAccess?: boolean;
29
+ allowPackageRegistryAccess?: boolean;
30
+ allowPublicTraffic?: boolean;
31
+ egressProfile?: string;
32
+ egressProfiles?: string[];
33
+ networkClass?: string;
34
+ rules?: unknown;
35
+ maskRequestHost?: string;
36
+ }
37
+ export interface SandboxNetworkUpdateOpts extends ConnectionOpts {
38
+ }
18
39
  export interface SandboxConnectOpts extends ConnectionOpts {
19
40
  /** Optional new sandbox lifetime in milliseconds. */
20
41
  timeoutMs?: number;
21
42
  }
43
+ export interface SandboxListOpts extends ConnectionOpts {
44
+ /** Filters applied by the Watasu API. */
45
+ query?: {
46
+ metadata?: Record<string, string>;
47
+ state?: Array<'running' | 'paused' | string>;
48
+ };
49
+ /** Maximum number of sandboxes to return per page. */
50
+ limit?: number;
51
+ /** Pagination cursor returned by a previous page. */
52
+ nextToken?: string;
53
+ /** Team slug to list within. */
54
+ team?: string;
55
+ }
22
56
  export interface SandboxInfo {
23
57
  sandboxId: string;
24
58
  templateId?: string;
@@ -47,39 +81,84 @@ export interface SnapshotInfo {
47
81
  expiresAt?: string;
48
82
  raw: Record<string, unknown>;
49
83
  }
84
+ export interface FileUrlInfo {
85
+ method: string;
86
+ path: string;
87
+ url: string;
88
+ expiresAt?: string;
89
+ raw: Record<string, unknown>;
90
+ }
91
+ /** MCP gateway configuration accepted by `Sandbox.create({ mcp })`. */
92
+ export type McpServer = Record<string, unknown>;
93
+ /** Name accepted by `Template.addMcpServer`. Watasu keeps this open-ended. */
94
+ export type McpServerName = string;
95
+ export interface SandboxUrlOpts extends ConnectionOpts {
96
+ user?: string;
97
+ useSignatureExpiration?: number;
98
+ expiresInSeconds?: number;
99
+ }
50
100
  export interface CreateSnapshotOpts extends ConnectionOpts {
51
101
  name?: string;
52
102
  metadata?: Record<string, string>;
53
103
  expiresAt?: string;
54
104
  quiesceMode?: string;
55
105
  }
106
+ export interface SnapshotListOpts extends ConnectionOpts {
107
+ /** Filter snapshots by source sandbox id. */
108
+ sandboxId?: string;
109
+ /** Maximum number of snapshots to return per page. */
110
+ limit?: number;
111
+ /** Pagination cursor returned by a previous page. */
112
+ nextToken?: string;
113
+ }
56
114
  export interface RestoreSnapshotOpts extends ConnectionOpts {
57
115
  checkpointId?: string | number;
58
116
  snapshotId?: string | number;
59
117
  timeout?: number;
60
118
  timeoutMs?: number;
61
119
  }
120
+ /** Paginator for listing sandbox snapshots. */
62
121
  export declare class SnapshotPaginator {
63
- private readonly loadItems;
64
- private consumed;
122
+ private readonly opts;
123
+ hasNext: boolean;
124
+ nextToken: string | undefined;
125
+ constructor(opts?: SnapshotListOpts);
126
+ /** Fetch the next page of snapshot metadata. */
127
+ nextItems(opts?: ConnectionOpts): Promise<SnapshotInfo[]>;
128
+ /** Drain all remaining pages into one list. */
129
+ listItems(opts?: ConnectionOpts): Promise<SnapshotInfo[]>;
130
+ }
131
+ /** Paginator for listing sandboxes. */
132
+ export declare class SandboxPaginator {
133
+ private readonly opts;
65
134
  hasNext: boolean;
66
135
  nextToken: string | undefined;
67
- constructor(loadItems: () => Promise<SnapshotInfo[]>);
68
- nextItems(): Promise<SnapshotInfo[]>;
136
+ constructor(opts?: SandboxListOpts);
137
+ /** Fetch the next page of sandbox metadata. */
138
+ nextItems(opts?: ConnectionOpts): Promise<SandboxInfo[]>;
139
+ /** Drain all remaining pages into one list. */
140
+ listItems(opts?: ConnectionOpts): Promise<SandboxInfo[]>;
69
141
  }
70
142
  /** Running Watasu sandbox with ready `files` and `commands` helpers. */
71
143
  export declare class Sandbox {
72
144
  /** Default template slug used when create is called without a template. */
73
145
  static readonly defaultTemplate = "base";
146
+ /** Default template slug used by MCP creation once Watasu supports it. */
147
+ static readonly defaultMcpTemplate = "mcp-gateway";
148
+ /** Default sandbox lifetime in milliseconds. */
149
+ static readonly defaultSandboxTimeoutMs = 300000;
74
150
  files: Filesystem;
151
+ filesystem: Filesystem;
75
152
  commands: Commands;
153
+ process: ProcessManager;
154
+ pty: Pty;
155
+ terminal: TerminalManager;
156
+ git: Git;
157
+ cwd: string | undefined;
158
+ envVars: Record<string, string>;
76
159
  readonly sandboxId: string;
77
- readonly pty: {
78
- create: () => never;
79
- };
80
- readonly git: {
81
- clone: () => never;
82
- };
160
+ private readonly mcpPort;
161
+ private mcpToken;
83
162
  private readonly config;
84
163
  private readonly control;
85
164
  private readonly envs;
@@ -93,24 +172,40 @@ export declare class Sandbox {
93
172
  sandbox?: Record<string, unknown>;
94
173
  envs?: Record<string, string>;
95
174
  });
175
+ /** Sandbox id alias used by SDK-compatible code. */
176
+ get id(): string;
96
177
  static create(opts?: SandboxCreateOpts): Promise<Sandbox>;
97
178
  static create(template: string, opts?: SandboxCreateOpts): Promise<Sandbox>;
98
179
  /** Connect to an existing sandbox and return it with a fresh data-plane session. */
99
180
  static connect(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox>;
181
+ /** Alias for `connect`. */
182
+ static reconnect(sandboxId: string, opts?: SandboxConnectOpts): Promise<Sandbox>;
183
+ static reconnect(opts: SandboxConnectOpts & {
184
+ sandboxID: string;
185
+ }): Promise<Sandbox>;
100
186
  /** Refresh this sandbox's data-plane session in place. */
101
187
  connect(opts?: SandboxConnectOpts): Promise<this>;
188
+ /** Resume a paused sandbox by id. */
189
+ static resume(sandboxId: string, opts?: SandboxConnectOpts): Promise<boolean>;
190
+ /** Pause a sandbox by id. Returns false when it was already paused. */
191
+ static betaPause(sandboxId: string, opts?: ConnectionOpts): Promise<boolean>;
192
+ /** Alias for `betaPause`. */
193
+ static pause(sandboxId: string, opts?: ConnectionOpts): Promise<boolean>;
102
194
  /** Destroy a sandbox by id. */
103
- static kill(sandboxId: string, opts?: ConnectionOpts): Promise<boolean>;
195
+ static kill(sandboxId: string, opts?: ConnectionOpts | string): Promise<boolean>;
104
196
  /** Fetch sandbox metrics by id. */
105
197
  static getMetrics(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxMetrics[]>;
198
+ /** Atomically replace a sandbox's network egress policy by id. */
199
+ static updateNetwork(sandboxId: string, network: SandboxNetworkUpdate, opts?: SandboxNetworkUpdateOpts): Promise<void>;
200
+ private static putNetwork;
106
201
  /** Deprecated alias for `getInfo`. */
107
202
  static getFullInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
108
203
  /** Create a Watasu checkpoint using snapshot naming. */
109
204
  static createSnapshot(sandboxId: string, opts?: CreateSnapshotOpts): Promise<SnapshotInfo>;
110
- /** List checkpoints for one sandbox using snapshot naming. */
111
- static listSnapshots(sandboxId: string, opts?: ConnectionOpts): SnapshotPaginator;
112
- /** Snapshot deletion is not backed by a Watasu checkpoint delete API yet. */
113
- static deleteSnapshot(..._args: unknown[]): never;
205
+ /** List snapshots visible to the configured API key. */
206
+ static listSnapshots(opts?: SnapshotListOpts): SnapshotPaginator;
207
+ /** Delete a snapshot by id. Returns `false` when the snapshot does not exist. */
208
+ static deleteSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<boolean>;
114
209
  /** Destroy this sandbox. */
115
210
  kill(): Promise<boolean>;
116
211
  /** Check if this sandbox is in a runtime-active lifecycle state. */
@@ -119,6 +214,8 @@ export declare class Sandbox {
119
214
  static setTimeout(sandboxId: string, timeoutMs: number, opts?: ConnectionOpts): Promise<void>;
120
215
  /** Set this sandbox's lifetime. */
121
216
  setTimeout(timeoutMs: number): Promise<void>;
217
+ /** Keep the sandbox alive for `duration` milliseconds. */
218
+ keepAlive(duration: number): Promise<void>;
122
219
  /** Fetch control-plane metadata for a sandbox by id. */
123
220
  static getInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
124
221
  /** Fetch the latest control-plane metadata for this sandbox. */
@@ -127,21 +224,44 @@ export declare class Sandbox {
127
224
  getMetrics(opts?: ConnectionOpts): Promise<SandboxMetrics[]>;
128
225
  /** Create a Watasu checkpoint using snapshot naming. */
129
226
  createSnapshot(opts?: CreateSnapshotOpts): Promise<SnapshotInfo>;
227
+ /** Delete a snapshot by id. */
228
+ deleteSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<boolean>;
130
229
  /** Watasu-native alias for `createSnapshot`. */
131
230
  checkpoint(opts?: CreateSnapshotOpts): Promise<SnapshotInfo>;
132
231
  /** List checkpoints for this sandbox using snapshot naming. */
133
- listSnapshots(opts?: ConnectionOpts): SnapshotPaginator;
232
+ listSnapshots(opts?: Omit<SnapshotListOpts, 'sandboxId'>): SnapshotPaginator;
134
233
  /** Restore a checkpoint into a new sandbox and return its control-plane info. */
135
234
  restore(opts?: RestoreSnapshotOpts | string | number): Promise<SandboxInfo>;
136
- /** List sandboxes visible to the configured API key. */
137
- static list(opts?: ConnectionOpts & {
138
- team?: string;
139
- }): Promise<SandboxInfo[]>;
235
+ /** Return a paginator for sandboxes visible to the configured API key. */
236
+ static list(opts?: SandboxListOpts | string): SandboxPaginator;
140
237
  /** Return the public hostname for an exposed sandbox port. */
141
238
  getHost(port: number): string;
142
- updateNetwork(..._args: unknown[]): never;
143
- pause(): never;
144
- betaPause(): never;
145
- resume(): never;
239
+ /** Return the public hostname for the sandbox or an exposed sandbox port. */
240
+ getHostname(port?: number): string;
241
+ /** Return the conventional MCP URL for this sandbox. */
242
+ getMcpUrl(): string;
243
+ /** Return the MCP gateway token when the sandbox contains one. */
244
+ getMcpToken(): Promise<string | undefined>;
245
+ /** Return a protocol string for a secure or insecure sandbox URL. */
246
+ getProtocol(baseProtocol?: string, secure?: boolean): string;
247
+ /** Close the local SDK attachment. This does not destroy the sandbox. */
248
+ close(): Promise<void>;
249
+ /** Get a signed URL that accepts a POST upload for a sandbox file path. */
250
+ uploadUrl(path?: string, opts?: SandboxUrlOpts): Promise<string>;
251
+ /** Get a signed URL that accepts a GET download for a sandbox file path. */
252
+ downloadUrl(path: string, opts?: SandboxUrlOpts): Promise<string>;
253
+ /** Get signed upload URL metadata for a sandbox file path. */
254
+ uploadUrlInfo(path?: string, opts?: SandboxUrlOpts): Promise<FileUrlInfo>;
255
+ /** Get signed download URL metadata for a sandbox file path. */
256
+ downloadUrlInfo(path: string, opts?: SandboxUrlOpts): Promise<FileUrlInfo>;
257
+ /** Atomically replace this sandbox's network egress policy. */
258
+ updateNetwork(network: SandboxNetworkUpdate, opts?: SandboxNetworkUpdateOpts): Promise<void>;
259
+ /** Pause this sandbox. Returns false when it was already paused. */
260
+ betaPause(opts?: ConnectionOpts): Promise<boolean>;
261
+ /** Alias for `betaPause`. */
262
+ pause(opts?: ConnectionOpts): Promise<boolean>;
263
+ /** Resume this sandbox and refresh its data-plane session. */
264
+ resume(opts?: SandboxConnectOpts): Promise<boolean>;
265
+ private fileUrl;
146
266
  private configOptions;
147
267
  }