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"