computesdk 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1834,6 +1834,12 @@ interface CommandResult {
1834
1834
  stderr: string;
1835
1835
  exitCode: number;
1836
1836
  durationMs: number;
1837
+ /** Command ID (present for background commands) */
1838
+ cmdId?: string;
1839
+ /** Terminal ID (present for background commands) */
1840
+ terminalId?: string;
1841
+ /** Command status (present for background commands) */
1842
+ status?: 'running' | 'completed' | 'failed';
1837
1843
  }
1838
1844
  /**
1839
1845
  * Supported languages for code execution
@@ -1846,6 +1852,13 @@ interface CodeRunOptions {
1846
1852
  /** Programming language (optional - will auto-detect if not specified) */
1847
1853
  language?: CodeLanguage;
1848
1854
  }
1855
+ /**
1856
+ * Options for waiting for command completion
1857
+ */
1858
+ interface CommandWaitOptions {
1859
+ /** Timeout in seconds to wait for command completion (default: 300, max: 300) */
1860
+ timeoutSeconds?: number;
1861
+ }
1849
1862
  /**
1850
1863
  * Command execution options
1851
1864
  */
@@ -1858,6 +1871,8 @@ interface CommandRunOptions {
1858
1871
  cwd?: string;
1859
1872
  /** Environment variables (optional) */
1860
1873
  env?: Record<string, string>;
1874
+ /** If true, wait for background command to complete before returning (default: false) */
1875
+ waitForCompletion?: boolean | CommandWaitOptions;
1861
1876
  }
1862
1877
  /**
1863
1878
  * Run - Resource namespace for executing code and commands
@@ -1876,14 +1891,28 @@ interface CommandRunOptions {
1876
1891
  * const result = await sandbox.run.command('ls -la');
1877
1892
  * console.log(result.stdout);
1878
1893
  * console.log(result.exitCode);
1894
+ *
1895
+ * // Run a command in background and wait for completion
1896
+ * const result = await sandbox.run.command('npm install', {
1897
+ * background: true,
1898
+ * waitForCompletion: true, // blocks until command completes
1899
+ * });
1900
+ * console.log(result.exitCode);
1901
+ *
1902
+ * // Run in background without waiting (fire-and-forget)
1903
+ * const result = await sandbox.run.command('npm install', { background: true });
1904
+ * console.log(result.cmdId); // command ID for manual tracking
1905
+ * console.log(result.terminalId); // terminal ID for manual tracking
1879
1906
  * ```
1880
1907
  */
1881
1908
  declare class Run {
1882
1909
  private codeHandler;
1883
1910
  private commandHandler;
1911
+ private waitHandler?;
1884
1912
  constructor(handlers: {
1885
1913
  code: (code: string, options?: CodeRunOptions) => Promise<CodeResult>;
1886
1914
  command: (command: string, options?: CommandRunOptions) => Promise<CommandResult>;
1915
+ wait?: (terminalId: string, cmdId: string, options?: CommandWaitOptions) => Promise<CommandResult>;
1887
1916
  });
1888
1917
  /**
1889
1918
  * Execute code with automatic language detection
@@ -1905,9 +1934,24 @@ declare class Run {
1905
1934
  * @param options.background - Run in background (optional)
1906
1935
  * @param options.cwd - Working directory for the command (optional)
1907
1936
  * @param options.env - Environment variables (optional)
1937
+ * @param options.waitForCompletion - If true (with background), wait for command to complete
1908
1938
  * @returns Command execution result with stdout, stderr, exit code, and duration
1909
1939
  */
1910
1940
  command(command: string, options?: CommandRunOptions): Promise<CommandResult>;
1941
+ /**
1942
+ * Wait for a background command to complete
1943
+ *
1944
+ * Uses the configured wait handler to block until the command
1945
+ * is complete or fails (typically via server-side long-polling).
1946
+ * Throws an error if the command fails or times out.
1947
+ *
1948
+ * @param terminalId - Terminal ID from background command result
1949
+ * @param cmdId - Command ID from background command result
1950
+ * @param options - Wait options passed to the handler
1951
+ * @returns Command result with final status
1952
+ * @throws Error if command fails or times out
1953
+ */
1954
+ waitForCompletion(terminalId: string, cmdId: string, options?: CommandWaitOptions): Promise<CommandResult>;
1911
1955
  }
1912
1956
 
1913
1957
  /**
@@ -1983,6 +2027,19 @@ declare class Child {
1983
2027
  * Overlays enable instant sandbox setup from template directories by copying
1984
2028
  * files directly for isolation, with heavy directories copied in the background.
1985
2029
  */
2030
+ /**
2031
+ * Options for waiting for overlay copy completion
2032
+ */
2033
+ interface WaitForCompletionOptions {
2034
+ /** Maximum number of retry attempts (default: 60) */
2035
+ maxRetries?: number;
2036
+ /** Initial delay between retries in milliseconds (default: 500) */
2037
+ initialDelayMs?: number;
2038
+ /** Maximum delay between retries in milliseconds (default: 5000) */
2039
+ maxDelayMs?: number;
2040
+ /** Backoff multiplier for exponential backoff (default: 1.5) */
2041
+ backoffFactor?: number;
2042
+ }
1986
2043
  /**
1987
2044
  * Options for creating an overlay
1988
2045
  */
@@ -1993,6 +2050,8 @@ interface CreateOverlayOptions {
1993
2050
  target: string;
1994
2051
  /** Glob patterns to ignore (e.g., ["node_modules", "*.log"]) */
1995
2052
  ignore?: string[];
2053
+ /** If true, wait for background copy to complete before returning (default: false) */
2054
+ waitForCompletion?: boolean | WaitForCompletionOptions;
1996
2055
  }
1997
2056
  /**
1998
2057
  * Copy status for overlay background operations
@@ -2062,6 +2121,16 @@ interface OverlayListResponse {
2062
2121
  * });
2063
2122
  * console.log(overlay.copyStatus); // 'pending' | 'in_progress' | 'complete' | 'failed'
2064
2123
  *
2124
+ * // Create an overlay and wait for background copy to complete
2125
+ * const overlay = await sandbox.filesystem.overlay.create({
2126
+ * source: '/templates/nextjs',
2127
+ * target: 'project',
2128
+ * waitForCompletion: true, // blocks until copy is complete
2129
+ * });
2130
+ *
2131
+ * // Wait for an existing overlay's copy to complete
2132
+ * const overlay = await sandbox.filesystem.overlay.waitForCompletion('overlay-id');
2133
+ *
2065
2134
  * // List all overlays
2066
2135
  * const overlays = await sandbox.filesystem.overlay.list();
2067
2136
  *
@@ -2097,6 +2166,7 @@ declare class Overlay {
2097
2166
  * @param options.source - Absolute path to source directory
2098
2167
  * @param options.target - Relative path in sandbox
2099
2168
  * @param options.ignore - Glob patterns to ignore (e.g., ["node_modules", "*.log"])
2169
+ * @param options.waitForCompletion - If true or options object, wait for background copy to complete
2100
2170
  * @returns Overlay info with copy status
2101
2171
  */
2102
2172
  create(options: CreateOverlayOptions): Promise<OverlayInfo>;
@@ -2119,6 +2189,18 @@ declare class Overlay {
2119
2189
  * @param id - Overlay ID
2120
2190
  */
2121
2191
  destroy(id: string): Promise<void>;
2192
+ /**
2193
+ * Wait for an overlay's background copy to complete
2194
+ *
2195
+ * Polls the overlay status with exponential backoff until the copy
2196
+ * is complete or fails. Throws an error if the copy fails or times out.
2197
+ *
2198
+ * @param id - Overlay ID
2199
+ * @param options - Polling options
2200
+ * @returns Overlay info with final copy status
2201
+ * @throws Error if copy fails or times out
2202
+ */
2203
+ waitForCompletion(id: string, options?: WaitForCompletionOptions): Promise<OverlayInfo>;
2122
2204
  /**
2123
2205
  * Convert API response to OverlayInfo
2124
2206
  */
@@ -3174,6 +3256,26 @@ declare class Sandbox {
3174
3256
  * @throws {Error} If terminal is in PTY mode, command not found, or timeout occurs
3175
3257
  */
3176
3258
  waitForCommand(terminalId: string, cmdId: string, timeout?: number): Promise<CommandDetailsResponse>;
3259
+ /**
3260
+ * Wait for a background command to complete using long-polling
3261
+ *
3262
+ * Uses the server's long-polling endpoint with configurable timeout.
3263
+ * The tunnel supports up to 5 minutes (300 seconds) via X-Request-Timeout header.
3264
+ *
3265
+ * @param terminalId - The terminal ID
3266
+ * @param cmdId - The command ID
3267
+ * @param options - Wait options (timeoutSeconds, default 300)
3268
+ * @returns Command result with final status
3269
+ * @throws Error if command fails or times out
3270
+ * @internal
3271
+ */
3272
+ private waitForCommandCompletion;
3273
+ /**
3274
+ * Wait for a command with extended timeout support
3275
+ * Uses X-Request-Timeout header for tunnel timeout configuration
3276
+ * @internal
3277
+ */
3278
+ private waitForCommandWithTimeout;
3177
3279
  /**
3178
3280
  * Create a new file watcher with WebSocket integration
3179
3281
  * @param path - Path to watch
package/dist/index.d.ts CHANGED
@@ -1834,6 +1834,12 @@ interface CommandResult {
1834
1834
  stderr: string;
1835
1835
  exitCode: number;
1836
1836
  durationMs: number;
1837
+ /** Command ID (present for background commands) */
1838
+ cmdId?: string;
1839
+ /** Terminal ID (present for background commands) */
1840
+ terminalId?: string;
1841
+ /** Command status (present for background commands) */
1842
+ status?: 'running' | 'completed' | 'failed';
1837
1843
  }
1838
1844
  /**
1839
1845
  * Supported languages for code execution
@@ -1846,6 +1852,13 @@ interface CodeRunOptions {
1846
1852
  /** Programming language (optional - will auto-detect if not specified) */
1847
1853
  language?: CodeLanguage;
1848
1854
  }
1855
+ /**
1856
+ * Options for waiting for command completion
1857
+ */
1858
+ interface CommandWaitOptions {
1859
+ /** Timeout in seconds to wait for command completion (default: 300, max: 300) */
1860
+ timeoutSeconds?: number;
1861
+ }
1849
1862
  /**
1850
1863
  * Command execution options
1851
1864
  */
@@ -1858,6 +1871,8 @@ interface CommandRunOptions {
1858
1871
  cwd?: string;
1859
1872
  /** Environment variables (optional) */
1860
1873
  env?: Record<string, string>;
1874
+ /** If true, wait for background command to complete before returning (default: false) */
1875
+ waitForCompletion?: boolean | CommandWaitOptions;
1861
1876
  }
1862
1877
  /**
1863
1878
  * Run - Resource namespace for executing code and commands
@@ -1876,14 +1891,28 @@ interface CommandRunOptions {
1876
1891
  * const result = await sandbox.run.command('ls -la');
1877
1892
  * console.log(result.stdout);
1878
1893
  * console.log(result.exitCode);
1894
+ *
1895
+ * // Run a command in background and wait for completion
1896
+ * const result = await sandbox.run.command('npm install', {
1897
+ * background: true,
1898
+ * waitForCompletion: true, // blocks until command completes
1899
+ * });
1900
+ * console.log(result.exitCode);
1901
+ *
1902
+ * // Run in background without waiting (fire-and-forget)
1903
+ * const result = await sandbox.run.command('npm install', { background: true });
1904
+ * console.log(result.cmdId); // command ID for manual tracking
1905
+ * console.log(result.terminalId); // terminal ID for manual tracking
1879
1906
  * ```
1880
1907
  */
1881
1908
  declare class Run {
1882
1909
  private codeHandler;
1883
1910
  private commandHandler;
1911
+ private waitHandler?;
1884
1912
  constructor(handlers: {
1885
1913
  code: (code: string, options?: CodeRunOptions) => Promise<CodeResult>;
1886
1914
  command: (command: string, options?: CommandRunOptions) => Promise<CommandResult>;
1915
+ wait?: (terminalId: string, cmdId: string, options?: CommandWaitOptions) => Promise<CommandResult>;
1887
1916
  });
1888
1917
  /**
1889
1918
  * Execute code with automatic language detection
@@ -1905,9 +1934,24 @@ declare class Run {
1905
1934
  * @param options.background - Run in background (optional)
1906
1935
  * @param options.cwd - Working directory for the command (optional)
1907
1936
  * @param options.env - Environment variables (optional)
1937
+ * @param options.waitForCompletion - If true (with background), wait for command to complete
1908
1938
  * @returns Command execution result with stdout, stderr, exit code, and duration
1909
1939
  */
1910
1940
  command(command: string, options?: CommandRunOptions): Promise<CommandResult>;
1941
+ /**
1942
+ * Wait for a background command to complete
1943
+ *
1944
+ * Uses the configured wait handler to block until the command
1945
+ * is complete or fails (typically via server-side long-polling).
1946
+ * Throws an error if the command fails or times out.
1947
+ *
1948
+ * @param terminalId - Terminal ID from background command result
1949
+ * @param cmdId - Command ID from background command result
1950
+ * @param options - Wait options passed to the handler
1951
+ * @returns Command result with final status
1952
+ * @throws Error if command fails or times out
1953
+ */
1954
+ waitForCompletion(terminalId: string, cmdId: string, options?: CommandWaitOptions): Promise<CommandResult>;
1911
1955
  }
1912
1956
 
1913
1957
  /**
@@ -1983,6 +2027,19 @@ declare class Child {
1983
2027
  * Overlays enable instant sandbox setup from template directories by copying
1984
2028
  * files directly for isolation, with heavy directories copied in the background.
1985
2029
  */
2030
+ /**
2031
+ * Options for waiting for overlay copy completion
2032
+ */
2033
+ interface WaitForCompletionOptions {
2034
+ /** Maximum number of retry attempts (default: 60) */
2035
+ maxRetries?: number;
2036
+ /** Initial delay between retries in milliseconds (default: 500) */
2037
+ initialDelayMs?: number;
2038
+ /** Maximum delay between retries in milliseconds (default: 5000) */
2039
+ maxDelayMs?: number;
2040
+ /** Backoff multiplier for exponential backoff (default: 1.5) */
2041
+ backoffFactor?: number;
2042
+ }
1986
2043
  /**
1987
2044
  * Options for creating an overlay
1988
2045
  */
@@ -1993,6 +2050,8 @@ interface CreateOverlayOptions {
1993
2050
  target: string;
1994
2051
  /** Glob patterns to ignore (e.g., ["node_modules", "*.log"]) */
1995
2052
  ignore?: string[];
2053
+ /** If true, wait for background copy to complete before returning (default: false) */
2054
+ waitForCompletion?: boolean | WaitForCompletionOptions;
1996
2055
  }
1997
2056
  /**
1998
2057
  * Copy status for overlay background operations
@@ -2062,6 +2121,16 @@ interface OverlayListResponse {
2062
2121
  * });
2063
2122
  * console.log(overlay.copyStatus); // 'pending' | 'in_progress' | 'complete' | 'failed'
2064
2123
  *
2124
+ * // Create an overlay and wait for background copy to complete
2125
+ * const overlay = await sandbox.filesystem.overlay.create({
2126
+ * source: '/templates/nextjs',
2127
+ * target: 'project',
2128
+ * waitForCompletion: true, // blocks until copy is complete
2129
+ * });
2130
+ *
2131
+ * // Wait for an existing overlay's copy to complete
2132
+ * const overlay = await sandbox.filesystem.overlay.waitForCompletion('overlay-id');
2133
+ *
2065
2134
  * // List all overlays
2066
2135
  * const overlays = await sandbox.filesystem.overlay.list();
2067
2136
  *
@@ -2097,6 +2166,7 @@ declare class Overlay {
2097
2166
  * @param options.source - Absolute path to source directory
2098
2167
  * @param options.target - Relative path in sandbox
2099
2168
  * @param options.ignore - Glob patterns to ignore (e.g., ["node_modules", "*.log"])
2169
+ * @param options.waitForCompletion - If true or options object, wait for background copy to complete
2100
2170
  * @returns Overlay info with copy status
2101
2171
  */
2102
2172
  create(options: CreateOverlayOptions): Promise<OverlayInfo>;
@@ -2119,6 +2189,18 @@ declare class Overlay {
2119
2189
  * @param id - Overlay ID
2120
2190
  */
2121
2191
  destroy(id: string): Promise<void>;
2192
+ /**
2193
+ * Wait for an overlay's background copy to complete
2194
+ *
2195
+ * Polls the overlay status with exponential backoff until the copy
2196
+ * is complete or fails. Throws an error if the copy fails or times out.
2197
+ *
2198
+ * @param id - Overlay ID
2199
+ * @param options - Polling options
2200
+ * @returns Overlay info with final copy status
2201
+ * @throws Error if copy fails or times out
2202
+ */
2203
+ waitForCompletion(id: string, options?: WaitForCompletionOptions): Promise<OverlayInfo>;
2122
2204
  /**
2123
2205
  * Convert API response to OverlayInfo
2124
2206
  */
@@ -3174,6 +3256,26 @@ declare class Sandbox {
3174
3256
  * @throws {Error} If terminal is in PTY mode, command not found, or timeout occurs
3175
3257
  */
3176
3258
  waitForCommand(terminalId: string, cmdId: string, timeout?: number): Promise<CommandDetailsResponse>;
3259
+ /**
3260
+ * Wait for a background command to complete using long-polling
3261
+ *
3262
+ * Uses the server's long-polling endpoint with configurable timeout.
3263
+ * The tunnel supports up to 5 minutes (300 seconds) via X-Request-Timeout header.
3264
+ *
3265
+ * @param terminalId - The terminal ID
3266
+ * @param cmdId - The command ID
3267
+ * @param options - Wait options (timeoutSeconds, default 300)
3268
+ * @returns Command result with final status
3269
+ * @throws Error if command fails or times out
3270
+ * @internal
3271
+ */
3272
+ private waitForCommandCompletion;
3273
+ /**
3274
+ * Wait for a command with extended timeout support
3275
+ * Uses X-Request-Timeout header for tunnel timeout configuration
3276
+ * @internal
3277
+ */
3278
+ private waitForCommandWithTimeout;
3177
3279
  /**
3178
3280
  * Create a new file watcher with WebSocket integration
3179
3281
  * @param path - Path to watch
package/dist/index.js CHANGED
@@ -1855,6 +1855,7 @@ var Run = class {
1855
1855
  constructor(handlers) {
1856
1856
  this.codeHandler = handlers.code;
1857
1857
  this.commandHandler = handlers.command;
1858
+ this.waitHandler = handlers.wait;
1858
1859
  }
1859
1860
  /**
1860
1861
  * Execute code with automatic language detection
@@ -1878,10 +1879,38 @@ var Run = class {
1878
1879
  * @param options.background - Run in background (optional)
1879
1880
  * @param options.cwd - Working directory for the command (optional)
1880
1881
  * @param options.env - Environment variables (optional)
1882
+ * @param options.waitForCompletion - If true (with background), wait for command to complete
1881
1883
  * @returns Command execution result with stdout, stderr, exit code, and duration
1882
1884
  */
1883
1885
  async command(command, options) {
1884
- return this.commandHandler(command, options);
1886
+ const result = await this.commandHandler(command, options);
1887
+ if (options?.background && options?.waitForCompletion && result.cmdId && result.terminalId) {
1888
+ if (!this.waitHandler) {
1889
+ throw new Error("Wait handler not configured");
1890
+ }
1891
+ const waitOptions = typeof options.waitForCompletion === "object" ? options.waitForCompletion : void 0;
1892
+ return this.waitHandler(result.terminalId, result.cmdId, waitOptions);
1893
+ }
1894
+ return result;
1895
+ }
1896
+ /**
1897
+ * Wait for a background command to complete
1898
+ *
1899
+ * Uses the configured wait handler to block until the command
1900
+ * is complete or fails (typically via server-side long-polling).
1901
+ * Throws an error if the command fails or times out.
1902
+ *
1903
+ * @param terminalId - Terminal ID from background command result
1904
+ * @param cmdId - Command ID from background command result
1905
+ * @param options - Wait options passed to the handler
1906
+ * @returns Command result with final status
1907
+ * @throws Error if command fails or times out
1908
+ */
1909
+ async waitForCompletion(terminalId, cmdId, options) {
1910
+ if (!this.waitHandler) {
1911
+ throw new Error("Wait handler not configured");
1912
+ }
1913
+ return this.waitHandler(terminalId, cmdId, options);
1885
1914
  }
1886
1915
  };
1887
1916
 
@@ -1946,11 +1975,17 @@ var Overlay = class {
1946
1975
  * @param options.source - Absolute path to source directory
1947
1976
  * @param options.target - Relative path in sandbox
1948
1977
  * @param options.ignore - Glob patterns to ignore (e.g., ["node_modules", "*.log"])
1978
+ * @param options.waitForCompletion - If true or options object, wait for background copy to complete
1949
1979
  * @returns Overlay info with copy status
1950
1980
  */
1951
1981
  async create(options) {
1952
1982
  const response = await this.createHandler(options);
1953
- return this.toOverlayInfo(response);
1983
+ const overlay = this.toOverlayInfo(response);
1984
+ if (options.waitForCompletion) {
1985
+ const waitOptions = typeof options.waitForCompletion === "object" ? options.waitForCompletion : void 0;
1986
+ return this.waitForCompletion(overlay.id, waitOptions);
1987
+ }
1988
+ return overlay;
1954
1989
  }
1955
1990
  /**
1956
1991
  * List all overlays for the current sandbox
@@ -1979,6 +2014,48 @@ var Overlay = class {
1979
2014
  async destroy(id) {
1980
2015
  return this.destroyHandler(id);
1981
2016
  }
2017
+ /**
2018
+ * Wait for an overlay's background copy to complete
2019
+ *
2020
+ * Polls the overlay status with exponential backoff until the copy
2021
+ * is complete or fails. Throws an error if the copy fails or times out.
2022
+ *
2023
+ * @param id - Overlay ID
2024
+ * @param options - Polling options
2025
+ * @returns Overlay info with final copy status
2026
+ * @throws Error if copy fails or times out
2027
+ */
2028
+ async waitForCompletion(id, options = {}) {
2029
+ const maxRetries = options.maxRetries ?? 60;
2030
+ const initialDelayMs = options.initialDelayMs ?? 500;
2031
+ const maxDelayMs = options.maxDelayMs ?? 5e3;
2032
+ const backoffFactor = options.backoffFactor ?? 1.5;
2033
+ let currentDelay = initialDelayMs;
2034
+ for (let i = 0; i < maxRetries; i++) {
2035
+ const overlay = await this.retrieve(id);
2036
+ if (overlay.copyStatus === "complete") {
2037
+ return overlay;
2038
+ }
2039
+ if (overlay.copyStatus === "failed") {
2040
+ throw new Error(
2041
+ `Overlay copy failed: ${overlay.copyError || "Unknown error"}
2042
+ Overlay ID: ${id}`
2043
+ );
2044
+ }
2045
+ if (i < maxRetries - 1) {
2046
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
2047
+ currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
2048
+ }
2049
+ }
2050
+ const finalOverlay = await this.retrieve(id);
2051
+ throw new Error(
2052
+ `Overlay copy timed out after ${maxRetries} attempts.
2053
+ Overlay ID: ${id}
2054
+ Current status: ${finalOverlay.copyStatus}
2055
+
2056
+ Try increasing maxRetries or check if the source directory is very large.`
2057
+ );
2058
+ }
1982
2059
  /**
1983
2060
  * Convert API response to OverlayInfo
1984
2061
  */
@@ -2022,6 +2099,7 @@ function isCommandExitError(error) {
2022
2099
  }
2023
2100
 
2024
2101
  // src/client/index.ts
2102
+ var MAX_TUNNEL_TIMEOUT_SECONDS = 300;
2025
2103
  var Sandbox = class {
2026
2104
  constructor(config) {
2027
2105
  this._token = null;
@@ -2140,8 +2218,15 @@ var Sandbox = class {
2140
2218
  stdout: result.data.stdout,
2141
2219
  stderr: result.data.stderr,
2142
2220
  exitCode: result.data.exit_code ?? 0,
2143
- durationMs: result.data.duration_ms ?? 0
2221
+ durationMs: result.data.duration_ms ?? 0,
2222
+ // Include cmdId and terminalId for background commands
2223
+ cmdId: result.data.cmd_id,
2224
+ terminalId: result.data.terminal_id,
2225
+ status: result.data.status
2144
2226
  };
2227
+ },
2228
+ wait: async (terminalId, cmdId, options) => {
2229
+ return this.waitForCommandCompletion(terminalId, cmdId, options);
2145
2230
  }
2146
2231
  });
2147
2232
  this.server = new Server({
@@ -2812,6 +2897,47 @@ API request failed (${response.status}): ${error}`
2812
2897
  const endpoint = `/terminals/${terminalId}/commands/${cmdId}/wait${params ? `?${params}` : ""}`;
2813
2898
  return this.request(endpoint);
2814
2899
  }
2900
+ /**
2901
+ * Wait for a background command to complete using long-polling
2902
+ *
2903
+ * Uses the server's long-polling endpoint with configurable timeout.
2904
+ * The tunnel supports up to 5 minutes (300 seconds) via X-Request-Timeout header.
2905
+ *
2906
+ * @param terminalId - The terminal ID
2907
+ * @param cmdId - The command ID
2908
+ * @param options - Wait options (timeoutSeconds, default 300)
2909
+ * @returns Command result with final status
2910
+ * @throws Error if command fails or times out
2911
+ * @internal
2912
+ */
2913
+ async waitForCommandCompletion(terminalId, cmdId, options) {
2914
+ const timeoutSeconds = options?.timeoutSeconds ?? MAX_TUNNEL_TIMEOUT_SECONDS;
2915
+ const response = await this.waitForCommandWithTimeout(terminalId, cmdId, timeoutSeconds);
2916
+ return {
2917
+ stdout: response.data.stdout,
2918
+ stderr: response.data.stderr,
2919
+ exitCode: response.data.exit_code ?? 0,
2920
+ durationMs: response.data.duration_ms ?? 0,
2921
+ cmdId: response.data.cmd_id,
2922
+ terminalId,
2923
+ status: response.data.status
2924
+ };
2925
+ }
2926
+ /**
2927
+ * Wait for a command with extended timeout support
2928
+ * Uses X-Request-Timeout header for tunnel timeout configuration
2929
+ * @internal
2930
+ */
2931
+ async waitForCommandWithTimeout(terminalId, cmdId, timeoutSeconds) {
2932
+ const params = new URLSearchParams({ timeout: timeoutSeconds.toString() });
2933
+ const endpoint = `/terminals/${terminalId}/commands/${cmdId}/wait?${params}`;
2934
+ const requestTimeout = Math.min(timeoutSeconds, MAX_TUNNEL_TIMEOUT_SECONDS);
2935
+ return this.request(endpoint, {
2936
+ headers: {
2937
+ "X-Request-Timeout": requestTimeout.toString()
2938
+ }
2939
+ });
2940
+ }
2815
2941
  // ============================================================================
2816
2942
  // File Watchers
2817
2943
  // ============================================================================