diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index b28fea9..7d9b009 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.9.1"
+ ".": "0.10.0"
}
diff --git a/.stats.yml b/.stats.yml
index f6de080..b791078 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 31
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-b55c3e0424fa7733487139488b9fff00ad8949ff02ee3160ee36b9334e84b134.yml
-openapi_spec_hash: 17f36677e3dc0a3aeb419654c8d5cae3
-config_hash: f67e4b33b2fb30c1405ee2fff8096320
+configured_endpoints: 41
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a7c1df5070fe59642d7a1f168aa902a468227752bfc930cbf38930f7c205dbb6.yml
+openapi_spec_hash: eab65e39aef4f0a0952b82adeecf6b5b
+config_hash: 5de78bc29ac060562575cb54bb26826c
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f38f36..2c88191 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog
+## 0.10.0 (2025-08-27)
+
+Full Changelog: [v0.9.1...v0.10.0](https://github.com/onkernel/kernel-node-sdk/compare/v0.9.1...v0.10.0)
+
+### Features
+
+* **api:** new process, fs, and log endpoints ([0cceb4e](https://github.com/onkernel/kernel-node-sdk/commit/0cceb4e3be5b8e6d267f075f6d9f696f24b1d7f3))
+* **mcp:** add code execution tool ([d3a08a9](https://github.com/onkernel/kernel-node-sdk/commit/d3a08a9e8bccbdf15e2404c9131f0969dc95be24))
+
+
+### Chores
+
+* add package to package.json ([294b1d8](https://github.com/onkernel/kernel-node-sdk/commit/294b1d85cbbe33ce1fd68f4fd879e95922b651c5))
+* **client:** qualify global Blob ([7ac9358](https://github.com/onkernel/kernel-node-sdk/commit/7ac9358a1f9d8d2b12ea1f91cd54c1cb169abab9))
+* **deps:** update dependency @types/node to v20.17.58 ([797f96b](https://github.com/onkernel/kernel-node-sdk/commit/797f96bd96877114412860f63f47e8ac16a7ab6c))
+* **internal:** formatting change ([8a4b4cf](https://github.com/onkernel/kernel-node-sdk/commit/8a4b4cf31f313b0cbe2c8de9eed168519b702dd7))
+* update CI script ([b0aabec](https://github.com/onkernel/kernel-node-sdk/commit/b0aabec18bf5b0f50264e42fd460b80a347db4a1))
+
## 0.9.1 (2025-08-15)
Full Changelog: [v0.9.0...v0.9.1](https://github.com/onkernel/kernel-node-sdk/compare/v0.9.0...v0.9.1)
diff --git a/api.md b/api.md
index 19d1eca..69fe6bf 100644
--- a/api.md
+++ b/api.md
@@ -97,11 +97,14 @@ Methods:
- client.browsers.fs.createDirectory(id, { ...params }) -> void
- client.browsers.fs.deleteDirectory(id, { ...params }) -> void
- client.browsers.fs.deleteFile(id, { ...params }) -> void
+- client.browsers.fs.downloadDirZip(id, { ...params }) -> Response
- client.browsers.fs.fileInfo(id, { ...params }) -> FFileInfoResponse
- client.browsers.fs.listFiles(id, { ...params }) -> FListFilesResponse
- client.browsers.fs.move(id, { ...params }) -> void
- client.browsers.fs.readFile(id, { ...params }) -> Response
- client.browsers.fs.setFilePermissions(id, { ...params }) -> void
+- client.browsers.fs.upload(id, { ...params }) -> void
+- client.browsers.fs.uploadZip(id, { ...params }) -> void
- client.browsers.fs.writeFile(id, contents, { ...params }) -> void
### Watch
@@ -116,3 +119,29 @@ Methods:
- client.browsers.fs.watch.events(watchID, { ...params }) -> WatchEventsResponse
- client.browsers.fs.watch.start(id, { ...params }) -> WatchStartResponse
- client.browsers.fs.watch.stop(watchID, { ...params }) -> void
+
+## Process
+
+Types:
+
+- ProcessExecResponse
+- ProcessKillResponse
+- ProcessSpawnResponse
+- ProcessStatusResponse
+- ProcessStdinResponse
+- ProcessStdoutStreamResponse
+
+Methods:
+
+- client.browsers.process.exec(id, { ...params }) -> ProcessExecResponse
+- client.browsers.process.kill(processID, { ...params }) -> ProcessKillResponse
+- client.browsers.process.spawn(id, { ...params }) -> ProcessSpawnResponse
+- client.browsers.process.status(processID, { ...params }) -> ProcessStatusResponse
+- client.browsers.process.stdin(processID, { ...params }) -> ProcessStdinResponse
+- client.browsers.process.stdoutStream(processID, { ...params }) -> ProcessStdoutStreamResponse
+
+## Logs
+
+Methods:
+
+- client.browsers.logs.stream(id, { ...params }) -> LogEvent
diff --git a/package.json b/package.json
index e3715cb..af5ef84 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@onkernel/sdk",
- "version": "0.9.1",
+ "version": "0.10.0",
"description": "The official TypeScript library for the Kernel API",
"author": "Kernel <>",
"types": "dist/index.d.ts",
@@ -44,8 +44,9 @@
"publint": "^0.2.12",
"ts-jest": "^29.1.0",
"ts-node": "^10.5.0",
- "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz",
+ "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz",
"tsconfig-paths": "^4.0.0",
+ "tslib": "^2.8.1",
"typescript": "5.8.3",
"typescript-eslint": "8.31.1"
},
diff --git a/scripts/bootstrap b/scripts/bootstrap
index 0af58e2..062a034 100755
--- a/scripts/bootstrap
+++ b/scripts/bootstrap
@@ -15,4 +15,4 @@ echo "==> Installing Node dependencies…"
PACKAGE_MANAGER=$(command -v yarn >/dev/null 2>&1 && echo "yarn" || echo "npm")
-$PACKAGE_MANAGER install
+$PACKAGE_MANAGER install "$@"
diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh
index 5580c06..ab5947d 100755
--- a/scripts/utils/upload-artifact.sh
+++ b/scripts/utils/upload-artifact.sh
@@ -12,7 +12,7 @@ if [[ "$SIGNED_URL" == "null" ]]; then
exit 1
fi
-UPLOAD_RESPONSE=$(tar -cz dist | curl -v -X PUT \
+UPLOAD_RESPONSE=$(tar -cz "${BUILD_PATH:-dist}" | curl -v -X PUT \
-H "Content-Type: application/gzip" \
--data-binary @- "$SIGNED_URL" 2>&1)
diff --git a/src/client.ts b/src/client.ts
index 0da7c4c..9956866 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -742,7 +742,7 @@ export class Kernel {
// Preserve legacy string encoding behavior for now
headers.values.has('content-type')) ||
// `Blob` is superset of `File`
- body instanceof Blob ||
+ ((globalThis as any).Blob && body instanceof (globalThis as any).Blob) ||
// `FormData` -> `multipart/form-data`
body instanceof FormData ||
// `URLSearchParams` -> `application/x-www-form-urlencoded`
@@ -796,10 +796,12 @@ export class Kernel {
invocations: API.Invocations = new API.Invocations(this);
browsers: API.Browsers = new API.Browsers(this);
}
+
Kernel.Deployments = Deployments;
Kernel.Apps = Apps;
Kernel.Invocations = Invocations;
Kernel.Browsers = Browsers;
+
export declare namespace Kernel {
export type RequestOptions = Opts.RequestOptions;
diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts
index 3e37d79..20a3e0c 100644
--- a/src/resources/browsers/browsers.ts
+++ b/src/resources/browsers/browsers.ts
@@ -2,6 +2,24 @@
import { APIResource } from '../../core/resource';
import * as BrowsersAPI from './browsers';
+import * as LogsAPI from './logs';
+import { LogStreamParams, Logs } from './logs';
+import * as ProcessAPI from './process';
+import {
+ Process,
+ ProcessExecParams,
+ ProcessExecResponse,
+ ProcessKillParams,
+ ProcessKillResponse,
+ ProcessSpawnParams,
+ ProcessSpawnResponse,
+ ProcessStatusParams,
+ ProcessStatusResponse,
+ ProcessStdinParams,
+ ProcessStdinResponse,
+ ProcessStdoutStreamParams,
+ ProcessStdoutStreamResponse,
+} from './process';
import * as ReplaysAPI from './replays';
import {
ReplayDownloadParams,
@@ -16,6 +34,7 @@ import {
FCreateDirectoryParams,
FDeleteDirectoryParams,
FDeleteFileParams,
+ FDownloadDirZipParams,
FFileInfoParams,
FFileInfoResponse,
FListFilesParams,
@@ -23,6 +42,8 @@ import {
FMoveParams,
FReadFileParams,
FSetFilePermissionsParams,
+ FUploadParams,
+ FUploadZipParams,
FWriteFileParams,
Fs,
} from './fs/fs';
@@ -34,6 +55,8 @@ import { path } from '../../internal/utils/path';
export class Browsers extends APIResource {
replays: ReplaysAPI.Replays = new ReplaysAPI.Replays(this._client);
fs: FsAPI.Fs = new FsAPI.Fs(this._client);
+ process: ProcessAPI.Process = new ProcessAPI.Process(this._client);
+ logs: LogsAPI.Logs = new LogsAPI.Logs(this._client);
/**
* Create a new browser session from within an action.
@@ -296,6 +319,8 @@ export interface BrowserDeleteParams {
Browsers.Replays = Replays;
Browsers.Fs = Fs;
+Browsers.Process = Process;
+Browsers.Logs = Logs;
export declare namespace Browsers {
export {
@@ -323,11 +348,32 @@ export declare namespace Browsers {
type FCreateDirectoryParams as FCreateDirectoryParams,
type FDeleteDirectoryParams as FDeleteDirectoryParams,
type FDeleteFileParams as FDeleteFileParams,
+ type FDownloadDirZipParams as FDownloadDirZipParams,
type FFileInfoParams as FFileInfoParams,
type FListFilesParams as FListFilesParams,
type FMoveParams as FMoveParams,
type FReadFileParams as FReadFileParams,
type FSetFilePermissionsParams as FSetFilePermissionsParams,
+ type FUploadParams as FUploadParams,
+ type FUploadZipParams as FUploadZipParams,
type FWriteFileParams as FWriteFileParams,
};
+
+ export {
+ Process as Process,
+ type ProcessExecResponse as ProcessExecResponse,
+ type ProcessKillResponse as ProcessKillResponse,
+ type ProcessSpawnResponse as ProcessSpawnResponse,
+ type ProcessStatusResponse as ProcessStatusResponse,
+ type ProcessStdinResponse as ProcessStdinResponse,
+ type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse,
+ type ProcessExecParams as ProcessExecParams,
+ type ProcessKillParams as ProcessKillParams,
+ type ProcessSpawnParams as ProcessSpawnParams,
+ type ProcessStatusParams as ProcessStatusParams,
+ type ProcessStdinParams as ProcessStdinParams,
+ type ProcessStdoutStreamParams as ProcessStdoutStreamParams,
+ };
+
+ export { Logs as Logs, type LogStreamParams as LogStreamParams };
}
diff --git a/src/resources/browsers/fs/fs.ts b/src/resources/browsers/fs/fs.ts
index caaa148..b6adb02 100644
--- a/src/resources/browsers/fs/fs.ts
+++ b/src/resources/browsers/fs/fs.ts
@@ -11,8 +11,10 @@ import {
WatchStopParams,
} from './watch';
import { APIPromise } from '../../../core/api-promise';
+import { type Uploadable } from '../../../core/uploads';
import { buildHeaders } from '../../../internal/headers';
import { RequestOptions } from '../../../internal/request-options';
+import { multipartFormRequestOptions } from '../../../internal/uploads';
import { path } from '../../../internal/utils/path';
export class Fs extends APIResource {
@@ -70,6 +72,29 @@ export class Fs extends APIResource {
});
}
+ /**
+ * Returns a ZIP file containing the contents of the specified directory.
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.fs.downloadDirZip(
+ * 'id',
+ * { path: '/J!' },
+ * );
+ *
+ * const content = await response.blob();
+ * console.log(content);
+ * ```
+ */
+ downloadDirZip(id: string, query: FDownloadDirZipParams, options?: RequestOptions): APIPromise {
+ return this._client.get(path`/browsers/${id}/fs/download_dir_zip`, {
+ query,
+ ...options,
+ headers: buildHeaders([{ Accept: 'application/zip' }, options?.headers]),
+ __binaryResponse: true,
+ });
+ }
+
/**
* Get information about a file or directory
*
@@ -162,6 +187,52 @@ export class Fs extends APIResource {
});
}
+ /**
+ * Allows uploading single or multiple files to the remote filesystem.
+ *
+ * @example
+ * ```ts
+ * await client.browsers.fs.upload('id', {
+ * files: [
+ * {
+ * dest_path: '/J!',
+ * file: fs.createReadStream('path/to/file'),
+ * },
+ * ],
+ * });
+ * ```
+ */
+ upload(id: string, body: FUploadParams, options?: RequestOptions): APIPromise {
+ return this._client.post(
+ path`/browsers/${id}/fs/upload`,
+ multipartFormRequestOptions(
+ { body, ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]) },
+ this._client,
+ ),
+ );
+ }
+
+ /**
+ * Upload a zip file and extract its contents to the specified destination path.
+ *
+ * @example
+ * ```ts
+ * await client.browsers.fs.uploadZip('id', {
+ * dest_path: '/J!',
+ * zip_file: fs.createReadStream('path/to/file'),
+ * });
+ * ```
+ */
+ uploadZip(id: string, body: FUploadZipParams, options?: RequestOptions): APIPromise {
+ return this._client.post(
+ path`/browsers/${id}/fs/upload_zip`,
+ multipartFormRequestOptions(
+ { body, ...options, headers: buildHeaders([{ Accept: '*/*' }, options?.headers]) },
+ this._client,
+ ),
+ );
+ }
+
/**
* Write or create a file
*
@@ -290,6 +361,13 @@ export interface FDeleteFileParams {
path: string;
}
+export interface FDownloadDirZipParams {
+ /**
+ * Absolute directory path to archive and download.
+ */
+ path: string;
+}
+
export interface FFileInfoParams {
/**
* Absolute path of the file or directory.
@@ -345,6 +423,30 @@ export interface FSetFilePermissionsParams {
owner?: string;
}
+export interface FUploadParams {
+ files: Array;
+}
+
+export namespace FUploadParams {
+ export interface File {
+ /**
+ * Absolute destination path to write the file.
+ */
+ dest_path: string;
+
+ file: Uploadable;
+ }
+}
+
+export interface FUploadZipParams {
+ /**
+ * Absolute destination directory to extract the archive to.
+ */
+ dest_path: string;
+
+ zip_file: Uploadable;
+}
+
export interface FWriteFileParams {
/**
* Query param: Destination absolute file path.
@@ -366,11 +468,14 @@ export declare namespace Fs {
type FCreateDirectoryParams as FCreateDirectoryParams,
type FDeleteDirectoryParams as FDeleteDirectoryParams,
type FDeleteFileParams as FDeleteFileParams,
+ type FDownloadDirZipParams as FDownloadDirZipParams,
type FFileInfoParams as FFileInfoParams,
type FListFilesParams as FListFilesParams,
type FMoveParams as FMoveParams,
type FReadFileParams as FReadFileParams,
type FSetFilePermissionsParams as FSetFilePermissionsParams,
+ type FUploadParams as FUploadParams,
+ type FUploadZipParams as FUploadZipParams,
type FWriteFileParams as FWriteFileParams,
};
diff --git a/src/resources/browsers/fs/index.ts b/src/resources/browsers/fs/index.ts
index 14c3cb8..0109d98 100644
--- a/src/resources/browsers/fs/index.ts
+++ b/src/resources/browsers/fs/index.ts
@@ -7,11 +7,14 @@ export {
type FCreateDirectoryParams,
type FDeleteDirectoryParams,
type FDeleteFileParams,
+ type FDownloadDirZipParams,
type FFileInfoParams,
type FListFilesParams,
type FMoveParams,
type FReadFileParams,
type FSetFilePermissionsParams,
+ type FUploadParams,
+ type FUploadZipParams,
type FWriteFileParams,
} from './fs';
export {
diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts
index cc79adb..3437de1 100644
--- a/src/resources/browsers/index.ts
+++ b/src/resources/browsers/index.ts
@@ -16,13 +16,32 @@ export {
type FCreateDirectoryParams,
type FDeleteDirectoryParams,
type FDeleteFileParams,
+ type FDownloadDirZipParams,
type FFileInfoParams,
type FListFilesParams,
type FMoveParams,
type FReadFileParams,
type FSetFilePermissionsParams,
+ type FUploadParams,
+ type FUploadZipParams,
type FWriteFileParams,
} from './fs/index';
+export { Logs, type LogStreamParams } from './logs';
+export {
+ Process,
+ type ProcessExecResponse,
+ type ProcessKillResponse,
+ type ProcessSpawnResponse,
+ type ProcessStatusResponse,
+ type ProcessStdinResponse,
+ type ProcessStdoutStreamResponse,
+ type ProcessExecParams,
+ type ProcessKillParams,
+ type ProcessSpawnParams,
+ type ProcessStatusParams,
+ type ProcessStdinParams,
+ type ProcessStdoutStreamParams,
+} from './process';
export {
Replays,
type ReplayListResponse,
diff --git a/src/resources/browsers/logs.ts b/src/resources/browsers/logs.ts
new file mode 100644
index 0000000..485f9d7
--- /dev/null
+++ b/src/resources/browsers/logs.ts
@@ -0,0 +1,50 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../core/resource';
+import * as Shared from '../shared';
+import { APIPromise } from '../../core/api-promise';
+import { Stream } from '../../core/streaming';
+import { buildHeaders } from '../../internal/headers';
+import { RequestOptions } from '../../internal/request-options';
+import { path } from '../../internal/utils/path';
+
+export class Logs extends APIResource {
+ /**
+ * Stream log files on the browser instance via SSE
+ *
+ * @example
+ * ```ts
+ * const logEvent = await client.browsers.logs.stream('id', {
+ * source: 'path',
+ * });
+ * ```
+ */
+ stream(id: string, query: LogStreamParams, options?: RequestOptions): APIPromise> {
+ return this._client.get(path`/browsers/${id}/logs/stream`, {
+ query,
+ ...options,
+ headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]),
+ stream: true,
+ }) as APIPromise>;
+ }
+}
+
+export interface LogStreamParams {
+ source: 'path' | 'supervisor';
+
+ follow?: boolean;
+
+ /**
+ * only required if source is path
+ */
+ path?: string;
+
+ /**
+ * only required if source is supervisor
+ */
+ supervisor_process?: string;
+}
+
+export declare namespace Logs {
+ export { type LogStreamParams as LogStreamParams };
+}
diff --git a/src/resources/browsers/process.ts b/src/resources/browsers/process.ts
new file mode 100644
index 0000000..2a3be95
--- /dev/null
+++ b/src/resources/browsers/process.ts
@@ -0,0 +1,366 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../core/resource';
+import { APIPromise } from '../../core/api-promise';
+import { Stream } from '../../core/streaming';
+import { buildHeaders } from '../../internal/headers';
+import { RequestOptions } from '../../internal/request-options';
+import { path } from '../../internal/utils/path';
+
+export class Process extends APIResource {
+ /**
+ * Execute a command synchronously
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.exec('id', {
+ * command: 'command',
+ * });
+ * ```
+ */
+ exec(id: string, body: ProcessExecParams, options?: RequestOptions): APIPromise {
+ return this._client.post(path`/browsers/${id}/process/exec`, { body, ...options });
+ }
+
+ /**
+ * Send signal to process
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.kill(
+ * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
+ * { id: 'id', signal: 'TERM' },
+ * );
+ * ```
+ */
+ kill(
+ processID: string,
+ params: ProcessKillParams,
+ options?: RequestOptions,
+ ): APIPromise {
+ const { id, ...body } = params;
+ return this._client.post(path`/browsers/${id}/process/${processID}/kill`, { body, ...options });
+ }
+
+ /**
+ * Execute a command asynchronously
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.spawn('id', {
+ * command: 'command',
+ * });
+ * ```
+ */
+ spawn(id: string, body: ProcessSpawnParams, options?: RequestOptions): APIPromise {
+ return this._client.post(path`/browsers/${id}/process/spawn`, { body, ...options });
+ }
+
+ /**
+ * Get process status
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.status(
+ * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
+ * { id: 'id' },
+ * );
+ * ```
+ */
+ status(
+ processID: string,
+ params: ProcessStatusParams,
+ options?: RequestOptions,
+ ): APIPromise {
+ const { id } = params;
+ return this._client.get(path`/browsers/${id}/process/${processID}/status`, options);
+ }
+
+ /**
+ * Write to process stdin
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.stdin(
+ * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
+ * { id: 'id', data_b64: 'data_b64' },
+ * );
+ * ```
+ */
+ stdin(
+ processID: string,
+ params: ProcessStdinParams,
+ options?: RequestOptions,
+ ): APIPromise {
+ const { id, ...body } = params;
+ return this._client.post(path`/browsers/${id}/process/${processID}/stdin`, { body, ...options });
+ }
+
+ /**
+ * Stream process stdout via SSE
+ *
+ * @example
+ * ```ts
+ * const response = await client.browsers.process.stdoutStream(
+ * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
+ * { id: 'id' },
+ * );
+ * ```
+ */
+ stdoutStream(
+ processID: string,
+ params: ProcessStdoutStreamParams,
+ options?: RequestOptions,
+ ): APIPromise> {
+ const { id } = params;
+ return this._client.get(path`/browsers/${id}/process/${processID}/stdout/stream`, {
+ ...options,
+ headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]),
+ stream: true,
+ }) as APIPromise>;
+ }
+}
+
+/**
+ * Result of a synchronous command execution.
+ */
+export interface ProcessExecResponse {
+ /**
+ * Execution duration in milliseconds.
+ */
+ duration_ms?: number;
+
+ /**
+ * Process exit code.
+ */
+ exit_code?: number;
+
+ /**
+ * Base64-encoded stderr buffer.
+ */
+ stderr_b64?: string;
+
+ /**
+ * Base64-encoded stdout buffer.
+ */
+ stdout_b64?: string;
+}
+
+/**
+ * Generic OK response.
+ */
+export interface ProcessKillResponse {
+ /**
+ * Indicates success.
+ */
+ ok: boolean;
+}
+
+/**
+ * Information about a spawned process.
+ */
+export interface ProcessSpawnResponse {
+ /**
+ * OS process ID.
+ */
+ pid?: number;
+
+ /**
+ * Server-assigned identifier for the process.
+ */
+ process_id?: string;
+
+ /**
+ * Timestamp when the process started.
+ */
+ started_at?: string;
+}
+
+/**
+ * Current status of a process.
+ */
+export interface ProcessStatusResponse {
+ /**
+ * Estimated CPU usage percentage.
+ */
+ cpu_pct?: number;
+
+ /**
+ * Exit code if the process has exited.
+ */
+ exit_code?: number | null;
+
+ /**
+ * Estimated resident memory usage in bytes.
+ */
+ mem_bytes?: number;
+
+ /**
+ * Process state.
+ */
+ state?: 'running' | 'exited';
+}
+
+/**
+ * Result of writing to stdin.
+ */
+export interface ProcessStdinResponse {
+ /**
+ * Number of bytes written.
+ */
+ written_bytes?: number;
+}
+
+/**
+ * SSE payload representing process output or lifecycle events.
+ */
+export interface ProcessStdoutStreamResponse {
+ /**
+ * Base64-encoded data from the process stream.
+ */
+ data_b64?: string;
+
+ /**
+ * Lifecycle event type.
+ */
+ event?: 'exit';
+
+ /**
+ * Exit code when the event is "exit".
+ */
+ exit_code?: number;
+
+ /**
+ * Source stream of the data chunk.
+ */
+ stream?: 'stdout' | 'stderr';
+}
+
+export interface ProcessExecParams {
+ /**
+ * Executable or shell command to run.
+ */
+ command: string;
+
+ /**
+ * Command arguments.
+ */
+ args?: Array;
+
+ /**
+ * Run the process with root privileges.
+ */
+ as_root?: boolean;
+
+ /**
+ * Run the process as this user.
+ */
+ as_user?: string | null;
+
+ /**
+ * Working directory (absolute path) to run the command in.
+ */
+ cwd?: string | null;
+
+ /**
+ * Environment variables to set for the process.
+ */
+ env?: { [key: string]: string };
+
+ /**
+ * Maximum execution time in seconds.
+ */
+ timeout_sec?: number | null;
+}
+
+export interface ProcessKillParams {
+ /**
+ * Path param: Browser session ID
+ */
+ id: string;
+
+ /**
+ * Body param: Signal to send.
+ */
+ signal: 'TERM' | 'KILL' | 'INT' | 'HUP';
+}
+
+export interface ProcessSpawnParams {
+ /**
+ * Executable or shell command to run.
+ */
+ command: string;
+
+ /**
+ * Command arguments.
+ */
+ args?: Array;
+
+ /**
+ * Run the process with root privileges.
+ */
+ as_root?: boolean;
+
+ /**
+ * Run the process as this user.
+ */
+ as_user?: string | null;
+
+ /**
+ * Working directory (absolute path) to run the command in.
+ */
+ cwd?: string | null;
+
+ /**
+ * Environment variables to set for the process.
+ */
+ env?: { [key: string]: string };
+
+ /**
+ * Maximum execution time in seconds.
+ */
+ timeout_sec?: number | null;
+}
+
+export interface ProcessStatusParams {
+ /**
+ * Browser session ID
+ */
+ id: string;
+}
+
+export interface ProcessStdinParams {
+ /**
+ * Path param: Browser session ID
+ */
+ id: string;
+
+ /**
+ * Body param: Base64-encoded data to write.
+ */
+ data_b64: string;
+}
+
+export interface ProcessStdoutStreamParams {
+ /**
+ * Browser session ID
+ */
+ id: string;
+}
+
+export declare namespace Process {
+ export {
+ type ProcessExecResponse as ProcessExecResponse,
+ type ProcessKillResponse as ProcessKillResponse,
+ type ProcessSpawnResponse as ProcessSpawnResponse,
+ type ProcessStatusResponse as ProcessStatusResponse,
+ type ProcessStdinResponse as ProcessStdinResponse,
+ type ProcessStdoutStreamResponse as ProcessStdoutStreamResponse,
+ type ProcessExecParams as ProcessExecParams,
+ type ProcessKillParams as ProcessKillParams,
+ type ProcessSpawnParams as ProcessSpawnParams,
+ type ProcessStatusParams as ProcessStatusParams,
+ type ProcessStdinParams as ProcessStdinParams,
+ type ProcessStdoutStreamParams as ProcessStdoutStreamParams,
+ };
+}
diff --git a/src/version.ts b/src/version.ts
index 72f481f..c2e5b96 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '0.9.1'; // x-release-please-version
+export const VERSION = '0.10.0'; // x-release-please-version
diff --git a/tests/api-resources/browsers/fs/fs.test.ts b/tests/api-resources/browsers/fs/fs.test.ts
index 87fbb3d..92a0c9c 100644
--- a/tests/api-resources/browsers/fs/fs.test.ts
+++ b/tests/api-resources/browsers/fs/fs.test.ts
@@ -59,6 +59,10 @@ describe('resource fs', () => {
const response = await client.browsers.fs.deleteFile('id', { path: '/J!' });
});
+ test('downloadDirZip: required and optional params', async () => {
+ const response = await client.browsers.fs.downloadDirZip('id', { path: '/J!' });
+ });
+
// Prism tests are disabled
test.skip('fileInfo: only required params', async () => {
const responsePromise = client.browsers.fs.fileInfo('id', { path: '/J!' });
@@ -136,6 +140,50 @@ describe('resource fs', () => {
});
});
+ // Prism tests are disabled
+ test.skip('upload: only required params', async () => {
+ const responsePromise = client.browsers.fs.upload('id', {
+ files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }],
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('upload: required and optional params', async () => {
+ const response = await client.browsers.fs.upload('id', {
+ files: [{ dest_path: '/J!', file: await toFile(Buffer.from('# my file contents'), 'README.md') }],
+ });
+ });
+
+ // Prism tests are disabled
+ test.skip('uploadZip: only required params', async () => {
+ const responsePromise = client.browsers.fs.uploadZip('id', {
+ dest_path: '/J!',
+ zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'),
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('uploadZip: required and optional params', async () => {
+ const response = await client.browsers.fs.uploadZip('id', {
+ dest_path: '/J!',
+ zip_file: await toFile(Buffer.from('# my file contents'), 'README.md'),
+ });
+ });
+
// Prism tests are disabled
test.skip('writeFile: only required params', async () => {
const responsePromise = client.browsers.fs.writeFile(
diff --git a/tests/api-resources/browsers/logs.test.ts b/tests/api-resources/browsers/logs.test.ts
new file mode 100644
index 0000000..0fa405e
--- /dev/null
+++ b/tests/api-resources/browsers/logs.test.ts
@@ -0,0 +1,32 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Kernel from '@onkernel/sdk';
+
+const client = new Kernel({
+ apiKey: 'My API Key',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource logs', () => {
+ // Prism doesn't support text/event-stream responses
+ test.skip('stream: only required params', async () => {
+ const responsePromise = client.browsers.logs.stream('id', { source: 'path' });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism doesn't support text/event-stream responses
+ test.skip('stream: required and optional params', async () => {
+ const response = await client.browsers.logs.stream('id', {
+ source: 'path',
+ follow: true,
+ path: 'path',
+ supervisor_process: 'supervisor_process',
+ });
+ });
+});
diff --git a/tests/api-resources/browsers/process.test.ts b/tests/api-resources/browsers/process.test.ts
new file mode 100644
index 0000000..138070a
--- /dev/null
+++ b/tests/api-resources/browsers/process.test.ts
@@ -0,0 +1,148 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Kernel from '@onkernel/sdk';
+
+const client = new Kernel({
+ apiKey: 'My API Key',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource process', () => {
+ // Prism tests are disabled
+ test.skip('exec: only required params', async () => {
+ const responsePromise = client.browsers.process.exec('id', { command: 'command' });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('exec: required and optional params', async () => {
+ const response = await client.browsers.process.exec('id', {
+ command: 'command',
+ args: ['string'],
+ as_root: true,
+ as_user: 'as_user',
+ cwd: '/J!',
+ env: { foo: 'string' },
+ timeout_sec: 0,
+ });
+ });
+
+ // Prism tests are disabled
+ test.skip('kill: only required params', async () => {
+ const responsePromise = client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ signal: 'TERM',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('kill: required and optional params', async () => {
+ const response = await client.browsers.process.kill('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ signal: 'TERM',
+ });
+ });
+
+ // Prism tests are disabled
+ test.skip('spawn: only required params', async () => {
+ const responsePromise = client.browsers.process.spawn('id', { command: 'command' });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('spawn: required and optional params', async () => {
+ const response = await client.browsers.process.spawn('id', {
+ command: 'command',
+ args: ['string'],
+ as_root: true,
+ as_user: 'as_user',
+ cwd: '/J!',
+ env: { foo: 'string' },
+ timeout_sec: 0,
+ });
+ });
+
+ // Prism tests are disabled
+ test.skip('status: only required params', async () => {
+ const responsePromise = client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('status: required and optional params', async () => {
+ const response = await client.browsers.process.status('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ });
+ });
+
+ // Prism tests are disabled
+ test.skip('stdin: only required params', async () => {
+ const responsePromise = client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ data_b64: 'data_b64',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism tests are disabled
+ test.skip('stdin: required and optional params', async () => {
+ const response = await client.browsers.process.stdin('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ data_b64: 'data_b64',
+ });
+ });
+
+ // Prism doesn't support text/event-stream responses
+ test.skip('stdoutStream: only required params', async () => {
+ const responsePromise = client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ // Prism doesn't support text/event-stream responses
+ test.skip('stdoutStream: required and optional params', async () => {
+ const response = await client.browsers.process.stdoutStream('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', {
+ id: 'id',
+ });
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 58c08d5..8311caf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -938,11 +938,11 @@
undici-types "~5.26.4"
"@types/node@^20.17.6":
- version "20.17.6"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.6.tgz#6e4073230c180d3579e8c60141f99efdf5df0081"
- integrity sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==
+ version "20.19.11"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4"
+ integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow==
dependencies:
- undici-types "~6.19.2"
+ undici-types "~6.21.0"
"@types/stack-utils@^2.0.0":
version "2.0.3"
@@ -3283,9 +3283,9 @@ ts-node@^10.5.0:
v8-compile-cache-lib "^3.0.0"
yn "3.1.1"
-"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz":
- version "1.1.8"
- resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.8/tsc-multi.tgz#f544b359b8f05e607771ffacc280e58201476b04"
+"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz":
+ version "1.1.9"
+ resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd"
dependencies:
debug "^4.3.7"
fast-glob "^3.3.2"
@@ -3353,10 +3353,10 @@ undici-types@~5.26.4:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
-undici-types@~6.19.2:
- version "6.19.8"
- resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
- integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
+undici-types@~6.21.0:
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
+ integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
unicode-emoji-modifier-base@^1.0.0:
version "1.0.0"