agentkernel 0.20.1 → 0.21.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/client.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BrowserSession } from "./browser.cjs";
2
2
  import { SandboxSession } from "./sandbox.cjs";
3
- import type { AgentKernelOptions, BatchCommand, BatchFileWriteResponse, BatchRunResponse, CreateStoreRequest, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateSandboxOptions, DetachedCommand, DetachedLogsResponse, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, FileReadResponse, FileWriteOptions, OrchestrationDefinition, RunOptions, RunOutput, Orchestration, SandboxInfo, Schedule, SnapshotMeta, StreamEvent, TakeSnapshotOptions } from "./types.cjs";
3
+ import type { AgentKernelOptions, BackendDiscovery, BatchCommand, BatchFileWriteResponse, BatchRunResponse, CreateStoreRequest, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateSandboxOptions, DetachedCommand, DetachedLogsResponse, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, FileReadResponse, FileWriteOptions, OrchestrationDefinition, RunOptions, RunOutput, Orchestration, SandboxInfo, Schedule, SnapshotMeta, StreamEvent, TakeSnapshotOptions } from "./types.cjs";
4
4
  /**
5
5
  * Client for the agentkernel HTTP API.
6
6
  *
@@ -33,6 +33,8 @@ export declare class AgentKernel {
33
33
  runStream(command: string[], opts?: RunOptions): AsyncGenerator<StreamEvent>;
34
34
  /** List all sandboxes. */
35
35
  listSandboxes(): Promise<SandboxInfo[]>;
36
+ /** Discover server-supported and ready sandbox backends. */
37
+ getBackends(): Promise<BackendDiscovery>;
36
38
  /** Create a new sandbox. */
37
39
  createSandbox(name: string, opts?: CreateSandboxOptions): Promise<SandboxInfo>;
38
40
  /** Get info about a sandbox. */
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BrowserSession } from "./browser.js";
2
2
  import { SandboxSession } from "./sandbox.js";
3
- import type { AgentKernelOptions, BatchCommand, BatchFileWriteResponse, BatchRunResponse, CreateStoreRequest, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateSandboxOptions, DetachedCommand, DetachedLogsResponse, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, FileReadResponse, FileWriteOptions, OrchestrationDefinition, RunOptions, RunOutput, Orchestration, SandboxInfo, Schedule, SnapshotMeta, StreamEvent, TakeSnapshotOptions } from "./types.js";
3
+ import type { AgentKernelOptions, BackendDiscovery, BatchCommand, BatchFileWriteResponse, BatchRunResponse, CreateStoreRequest, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateSandboxOptions, DetachedCommand, DetachedLogsResponse, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, FileReadResponse, FileWriteOptions, OrchestrationDefinition, RunOptions, RunOutput, Orchestration, SandboxInfo, Schedule, SnapshotMeta, StreamEvent, TakeSnapshotOptions } from "./types.js";
4
4
  /**
5
5
  * Client for the agentkernel HTTP API.
6
6
  *
@@ -33,6 +33,8 @@ export declare class AgentKernel {
33
33
  runStream(command: string[], opts?: RunOptions): AsyncGenerator<StreamEvent>;
34
34
  /** List all sandboxes. */
35
35
  listSandboxes(): Promise<SandboxInfo[]>;
36
+ /** Discover server-supported and ready sandbox backends. */
37
+ getBackends(): Promise<BackendDiscovery>;
36
38
  /** Create a new sandbox. */
37
39
  createSandbox(name: string, opts?: CreateSandboxOptions): Promise<SandboxInfo>;
38
40
  /** Get info about a sandbox. */
package/dist/index.cjs CHANGED
@@ -803,7 +803,7 @@ async function* parseSSE(body) {
803
803
  }
804
804
 
805
805
  // src/client.ts
806
- var SDK_VERSION = "0.3.0";
806
+ var SDK_VERSION = "0.21.0";
807
807
  var AgentKernel = class {
808
808
  baseUrl;
809
809
  apiKey;
@@ -864,10 +864,15 @@ var AgentKernel = class {
864
864
  async listSandboxes() {
865
865
  return this.request("GET", "/sandboxes");
866
866
  }
867
+ /** Discover server-supported and ready sandbox backends. */
868
+ async getBackends() {
869
+ return this.request("GET", "/backends");
870
+ }
867
871
  /** Create a new sandbox. */
868
872
  async createSandbox(name, opts) {
869
873
  return this.request("POST", "/sandboxes", {
870
874
  name,
875
+ backend: opts?.backend,
871
876
  image: opts?.image,
872
877
  vcpus: opts?.vcpus,
873
878
  memory_mb: opts?.memory_mb,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["export { AgentKernel } from \"./client.js\";\nexport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nexport { SandboxSession } from \"./sandbox.js\";\nexport {\n AgentKernelError,\n AuthError,\n NotFoundError,\n ValidationError,\n ServerError,\n NetworkError,\n StreamError,\n} from \"./errors.js\";\nexport type {\n AgentKernelOptions,\n AriaSnapshot,\n BatchFileWriteResponse,\n BrowserEvent,\n CreateSandboxOptions,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateStoreRequest,\n DetachedCommand,\n DetachedLogsResponse,\n DetachedStatus,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n PageLink,\n PageResult,\n RunOptions,\n RunOutput,\n Orchestration,\n OrchestrationDefinition,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\n Schedule,\n TakeSnapshotOptions,\n ApiResponse,\n} from \"./types.js\";\n","import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","/**\n * Browser session for orchestrating headless browsers in sandboxes.\n *\n * Each method generates a self-contained Python/Playwright script,\n * runs it inside the sandbox, and parses the JSON result.\n */\n\nimport type { AriaSnapshot, PageResult, RunOutput } from \"./types.js\";\n\ntype RunInSandboxFn = (\n name: string,\n command: string[],\n) => Promise<RunOutput>;\ntype RemoveSandboxFn = (name: string) => Promise<void>;\n\nconst GOTO_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n title = await page.title()\n url_final = page.url\n text = await page.evaluate(\"() => document.body.innerText.slice(0, 8000)\")\n links = await page.evaluate('''() =>\n Array.from(document.querySelectorAll('a[href]'))\n .slice(0, 50)\n .map(a => ({text: a.textContent.trim(), href: a.href}))\n .filter(l => l.href.startsWith(\"http\"))\n ''')\n print(json.dumps({\"title\": title, \"url\": url_final, \"text\": text, \"links\": links}))\n await b.close()\nasyncio.run(main())\n`;\n\nconst SCREENSHOT_SCRIPT = `\nimport asyncio, base64, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n data = await page.screenshot()\n print(base64.b64encode(data).decode())\n await b.close()\nasyncio.run(main())\n`;\n\nconst EVALUATE_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n expr = sys.argv[2]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n result = await page.evaluate(expr)\n print(json.dumps(result))\n await b.close()\nasyncio.run(main())\n`;\n\n/** Command to install Playwright + Chromium inside the sandbox. */\nexport const BROWSER_SETUP_CMD = [\n \"sh\",\n \"-c\",\n \"pip install -q playwright && playwright install --with-deps chromium\",\n];\n\n// --- v2 scripts ---\n\nconst BROWSER_HEALTH_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\ntry:\n req = urllib.request.urlopen(f\"http://127.0.0.1:{port}/health\", timeout=5)\n print(req.read().decode())\nexcept Exception as e:\n print(json.dumps({\"status\": \"down\", \"error\": str(e)}))\n sys.exit(1)\n`;\n\nconst BROWSER_REQUEST_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\nmethod = sys.argv[2] if len(sys.argv) > 2 else \"GET\"\npath = sys.argv[3] if len(sys.argv) > 3 else \"/health\"\nbody_str = sys.argv[4] if len(sys.argv) > 4 else None\nurl = f\"http://127.0.0.1:{port}{path}\"\ndata = body_str.encode() if body_str else None\nreq = urllib.request.Request(url, data=data, method=method)\nif data:\n req.add_header(\"Content-Type\", \"application/json\")\ntry:\n resp = urllib.request.urlopen(req, timeout=60)\n print(resp.read().decode())\nexcept urllib.error.HTTPError as e:\n print(e.read().decode())\n sys.exit(1)\nexcept Exception as e:\n print(json.dumps({\"error\": str(e)}))\n sys.exit(1)\n`;\n\n/**\n * A sandboxed headless browser controlled from outside.\n *\n * The browser (Chromium via Playwright) runs inside an agentkernel sandbox.\n * You call high-level methods; the SDK generates and runs scripts internally.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * ```\n */\nexport class BrowserSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private _lastUrl: string | null = null;\n private readonly _run: RunInSandboxFn;\n private readonly _remove: RemoveSandboxFn;\n\n /** @internal */\n constructor(name: string, runFn: RunInSandboxFn, removeFn: RemoveSandboxFn) {\n this.name = name;\n this._run = runFn;\n this._remove = removeFn;\n }\n\n /** Navigate to a URL and return page data (title, text, links). */\n async goto(url: string): Promise<PageResult> {\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n GOTO_SCRIPT,\n url,\n ]);\n this._lastUrl = url;\n return JSON.parse(result.output) as PageResult;\n }\n\n /** Take a PNG screenshot. Returns a base64-encoded string. */\n async screenshot(url?: string): Promise<string> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n SCREENSHOT_SCRIPT,\n target,\n ]);\n return result.output.trim();\n }\n\n /** Run a JavaScript expression on a page and return the result. */\n async evaluate(expression: string, url?: string): Promise<unknown> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n EVALUATE_SCRIPT,\n target,\n expression,\n ]);\n return JSON.parse(result.output);\n }\n\n // --- v2 methods (ARIA snapshots, persistent pages, ref-based interaction) ---\n\n /** Navigate to a URL and return an ARIA snapshot. */\n async open(url: string, page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/goto`,\n JSON.stringify({ url }),\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Get the current ARIA snapshot without navigating. */\n async snapshot(page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"GET\",\n `/pages/${page}/snapshot`,\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Click an element by ref ID or CSS selector. Returns new snapshot. */\n async click(opts: { ref?: string; selector?: string; page?: string }): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = {};\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/click`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Fill an input by ref ID or CSS selector. Returns new snapshot. */\n async fill(\n value: string,\n opts: { ref?: string; selector?: string; page?: string },\n ): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = { value };\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/fill`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Close a named page. */\n async closePage(page = \"default\"): Promise<void> {\n await this._ensureServer();\n await this._browserRequest(\"DELETE\", `/pages/${page}`);\n }\n\n /** List active page names. */\n async listPages(): Promise<string[]> {\n await this._ensureServer();\n const result = await this._browserRequest(\"GET\", \"/pages\");\n const data = JSON.parse(result.output);\n return data.pages ?? [];\n }\n\n private _serverStarted = false;\n\n private async _ensureServer(): Promise<void> {\n if (this._serverStarted) return;\n // Health check\n try {\n const result = await this._run(this.name, [\n \"python3\", \"-c\", BROWSER_HEALTH_SCRIPT, \"9222\",\n ]);\n if (result.output.includes('\"status\":\"ok\"') || result.output.includes('\"status\": \"ok\"')) {\n this._serverStarted = true;\n return;\n }\n } catch {\n // Server not running, start it\n }\n // Start would require the full server script + ARIA JS — for SDK use,\n // the server is expected to already be running (started via browser_create or MCP)\n throw new Error(\n \"Browser server not running. Use browser_create to set up the sandbox, \" +\n \"or use the MCP browser_open tool which auto-starts the server.\",\n );\n }\n\n private async _browserRequest(\n method: string,\n path: string,\n body?: string,\n ): Promise<RunOutput> {\n const cmd = [\"python3\", \"-c\", BROWSER_REQUEST_SCRIPT, \"9222\", method, path];\n if (body) cmd.push(body);\n return this._run(this.name, cmd);\n }\n\n // --- v1 methods (backward compatible) ---\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._remove(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import type {\n BatchFileWriteResponse,\n ExecOptions,\n RunOutput,\n SandboxInfo,\n} from \"./types.js\";\n\ntype ExecFn = (\n name: string,\n command: string[],\n opts?: ExecOptions,\n) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\ntype WriteFilesFn = (\n name: string,\n files: Record<string, string>,\n) => Promise<BatchFileWriteResponse>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n private readonly _writeFiles: WriteFilesFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n writeFiles: WriteFilesFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n this._writeFiles = writeFiles;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[], opts?: ExecOptions): Promise<RunOutput> {\n return this._execInSandbox(this.name, command, opts);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Write multiple files in one request. */\n async writeFiles(\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this._writeFiles(this.name, files);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\nconst MAX_FIELD_PREFIX_LENGTH = 6\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {maxBufferSize, onComment, onError, onEvent, onId, onRetry} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n let skippingLine = false\n\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM at the start of the very first chunk\n * is stripped before parsing. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Strip one leading UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream.)\n // Two representations can reach us depending on how the caller decoded the\n // bytes: a single decoded U+FEFF (e.g. a `TextDecoder` created with\n // `ignoreBOM`) or the raw 3-byte sequence (0xEF 0xBB 0xBF, e.g. a latin1 or\n // passthrough decode). Both are stripped so a leading BOM is ignored\n // regardless of decode path.\n if (chunk.charCodeAt(0) === 0xfeff) {\n chunk = chunk.slice(1)\n } else if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk)\n if (!chunk) {\n return\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n storeTrailing(trailing)\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head =\n pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength)\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n skippingLine = true\n return\n }\n }\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n storeTrailing(processLines(input))\n checkBufferSize()\n }\n\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk: string): string {\n if (chunk.length === 0) {\n return chunk\n }\n\n if (skipNextLineFeed) {\n skipNextLineFeed = false\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk\n }\n\n const crIndex = chunk.indexOf('\\r')\n const lfIndex = chunk.indexOf('\\n')\n const lineEnd =\n crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex\n\n if (lineEnd === -1) {\n return ''\n }\n\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false\n skipNextLineFeed = true\n return ''\n }\n\n skippingLine = false\n return chunk.slice(\n lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1),\n )\n }\n\n function storeTrailing(trailing: string) {\n if (!trailing) return\n\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1)\n skipNextLineFeed = true\n return\n }\n\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n return\n }\n\n skippingLine = true\n }\n\n function shouldBufferTrailing(trailing: string) {\n const firstCharCode = trailing.charCodeAt(0)\n return (\n (firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry'))\n )\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n skippingLine = false\n skipNextLineFeed = false\n onError?.(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId?.(id)\n }\n if (dataLines > 0) {\n onEvent?.({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId?.(id)\n }\n onEvent?.({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry?.(parseInt(value, 10))\n } else {\n onError?.(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError?.(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (id !== undefined) {\n onId?.(id)\n }\n\n if (dataLines > 0) {\n onEvent?.({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n skippingLine = false\n skipNextLineFeed = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n\nfunction isPotentialField(line: string, field: string): boolean {\n let i = 1\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false\n }\n i++\n }\n\n return line.length <= field.length || line.charCodeAt(field.length) === 58\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n ApiResponse,\n BatchCommand,\n BatchFileWriteResponse,\n BatchRunResponse,\n CreateStoreRequest,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n FileReadResponse,\n FileWriteOptions,\n OrchestrationDefinition,\n RunOptions,\n RunOutput,\n Orchestration,\n SandboxInfo,\n Schedule,\n SnapshotMeta,\n StreamEvent,\n TakeSnapshotOptions,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.3.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n source_url: opts?.source_url,\n source_ref: opts?.source_ref,\n volumes: opts?.volumes,\n secrets: opts?.secrets,\n secret_files: opts?.secret_files,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Get info about a sandbox by UUID. */\n async getSandboxByUuid(uuid: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"GET\",\n `/sandboxes/by-uuid/${encodeURIComponent(uuid)}`,\n );\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Write multiple files to a sandbox in one request. */\n async writeFiles(\n name: string,\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this.request<BatchFileWriteResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/files`,\n { files },\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /** Start a detached (background) command in a sandbox. */\n async execDetached(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detach`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Get the status of a detached command. */\n async detachedStatus(\n name: string,\n cmdId: string,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** Get logs from a detached command. */\n async detachedLogs(\n name: string,\n cmdId: string,\n stream?: \"stdout\" | \"stderr\",\n ): Promise<DetachedLogsResponse> {\n const query = stream === \"stderr\" ? \"?stream=stderr\" : \"\";\n return this.request<DetachedLogsResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`,\n );\n }\n\n /** Kill a detached command. */\n async detachedKill(name: string, cmdId: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** List detached commands in a sandbox. */\n async detachedList(name: string): Promise<DetachedCommand[]> {\n return this.request<DetachedCommand[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached`,\n );\n }\n\n /** List all orchestrations. */\n async listOrchestrations(): Promise<Orchestration[]> {\n return this.request<Orchestration[]>(\"GET\", \"/orchestrations\");\n }\n\n /** Create a new orchestration. */\n async createOrchestration(payload: CreateOrchestrationRequest): Promise<Orchestration> {\n return this.request<Orchestration>(\"POST\", \"/orchestrations\", payload);\n }\n\n /** Get info about an orchestration by identifier. */\n async getOrchestration(id: string): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"GET\",\n `/orchestrations/${encodeURIComponent(id)}`,\n );\n }\n\n /** Raise an external event for an orchestration. */\n async signalOrchestration(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/events`,\n payload,\n );\n }\n\n /** Terminate an orchestration. */\n async terminateOrchestration(\n id: string,\n payload?: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/terminate`,\n payload ?? {},\n );\n }\n\n /** List orchestration definitions. */\n async listOrchestrationDefinitions(): Promise<OrchestrationDefinition[]> {\n return this.request<OrchestrationDefinition[]>(\n \"GET\",\n \"/orchestrations/definitions\",\n );\n }\n\n /** Register or update an orchestration definition. */\n async upsertOrchestrationDefinition(\n payload: OrchestrationDefinition,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"POST\",\n \"/orchestrations/definitions\",\n payload,\n );\n }\n\n /** Get an orchestration definition by name. */\n async getOrchestrationDefinition(\n name: string,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"GET\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete an orchestration definition by name. */\n async deleteOrchestrationDefinition(name: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** List all objects. */\n async listObjects(): Promise<DurableObject[]> {\n return this.request<DurableObject[]>(\"GET\", \"/objects\");\n }\n\n /** Create a new object. */\n async createObject(payload: CreateObjectRequest): Promise<DurableObject> {\n return this.request<DurableObject>(\"POST\", \"/objects\", payload);\n }\n\n /** Get an object by identifier. */\n async getObject(id: string): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"GET\",\n `/objects/${encodeURIComponent(id)}`,\n );\n }\n\n /** Call a method on a durable object (auto-creates/wakes if needed). */\n async callObject(\n className: string,\n objectId: string,\n method: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const resp = await this.request(\n \"POST\",\n `/objects/${encodeURIComponent(className)}/${encodeURIComponent(objectId)}/call/${encodeURIComponent(method)}`,\n args ?? {},\n );\n return resp;\n }\n\n /** Delete a durable object by identifier. */\n async deleteObject(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/objects/${encodeURIComponent(id)}`);\n }\n\n /** Partially update a durable object (storage and/or status). */\n async patchObject(\n id: string,\n payload: { storage?: unknown; status?: string },\n ): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"PATCH\",\n `/objects/${encodeURIComponent(id)}`,\n payload,\n );\n }\n\n /** List all schedules. */\n async listSchedules(): Promise<Schedule[]> {\n return this.request<Schedule[]>(\"GET\", \"/schedules\");\n }\n\n /** Create a new schedule. */\n async createSchedule(payload: CreateScheduleRequest): Promise<Schedule> {\n return this.request<Schedule>(\"POST\", \"/schedules\", payload);\n }\n\n /** Get a schedule by identifier. */\n async getSchedule(id: string): Promise<Schedule> {\n return this.request<Schedule>(\n \"GET\",\n `/schedules/${encodeURIComponent(id)}`,\n );\n }\n\n /** Delete a schedule by identifier. */\n async deleteSchedule(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/schedules/${encodeURIComponent(id)}`);\n }\n\n /** List all durable stores. */\n async listStores(): Promise<DurableStore[]> {\n return this.request<DurableStore[]>(\"GET\", \"/stores\");\n }\n\n /** Create a durable store. */\n async createStore(payload: CreateStoreRequest): Promise<DurableStore> {\n return this.request<DurableStore>(\"POST\", \"/stores\", payload);\n }\n\n /** Get a durable store by identifier. */\n async getStore(id: string): Promise<DurableStore> {\n return this.request<DurableStore>(\"GET\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Delete a durable store by identifier. */\n async deleteStore(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Execute a read query against a durable store. */\n async queryStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreQueryResponse> {\n return this.request<DurableStoreQueryResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/query`,\n payload,\n );\n }\n\n /** Execute a write statement against a durable store. */\n async executeStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreExecuteResponse> {\n return this.request<DurableStoreExecuteResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/execute`,\n payload,\n );\n }\n\n /** Execute a command against a durable store (Redis-style engines). */\n async commandStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreCommandResponse> {\n return this.request<DurableStoreCommandResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/command`,\n payload,\n );\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd, o) => this.execInSandbox(n, cmd, o),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n (n, f) => this.writeFiles(n, f),\n );\n }\n\n /**\n * Create a sandboxed browser session with automatic cleanup.\n *\n * Creates a sandbox with Chromium pre-installed via Playwright.\n * Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async browser(\n name: string,\n opts?: { memory_mb?: number },\n ): Promise<BrowserSession> {\n await this.createSandbox(name, {\n image: \"python:3.12-slim\",\n memory_mb: opts?.memory_mb ?? 2048,\n profile: \"moderate\",\n });\n await this.execInSandbox(name, BROWSER_SETUP_CMD);\n return new BrowserSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n );\n }\n\n // -- TTL & Snapshot methods --\n\n /** Extend a sandbox's TTL. Returns the new expiry time. */\n async extendTtl(name: string, opts: ExtendTtlOptions): Promise<ExtendTtlResponse> {\n return this.request<ExtendTtlResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/extend`,\n { by: opts.by },\n );\n }\n\n /** List all snapshots. */\n async listSnapshots(): Promise<SnapshotMeta[]> {\n return this.request<SnapshotMeta[]>(\"GET\", \"/snapshots\");\n }\n\n /** Take a snapshot of a sandbox. */\n async takeSnapshot(opts: TakeSnapshotOptions): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\"POST\", \"/snapshots\", opts);\n }\n\n /** Get info about a snapshot. */\n async getSnapshot(name: string): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\n \"GET\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete a snapshot. */\n async deleteSnapshot(name: string): Promise<void> {\n await this.request<string>(\n \"DELETE\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Restore a sandbox from a snapshot. */\n async restoreSnapshot(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"POST\",\n `/snapshots/${encodeURIComponent(name)}/restore`,\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":["value","line"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["export { AgentKernel } from \"./client.js\";\nexport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nexport { SandboxSession } from \"./sandbox.js\";\nexport {\n AgentKernelError,\n AuthError,\n NotFoundError,\n ValidationError,\n ServerError,\n NetworkError,\n StreamError,\n} from \"./errors.js\";\nexport type {\n AgentKernelOptions,\n BackendCapabilities,\n BackendDescriptor,\n BackendDiscovery,\n AriaSnapshot,\n BatchFileWriteResponse,\n BrowserEvent,\n CreateSandboxOptions,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateStoreRequest,\n DetachedCommand,\n DetachedLogsResponse,\n DetachedStatus,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n PageLink,\n PageResult,\n RunOptions,\n RunOutput,\n Orchestration,\n OrchestrationDefinition,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\n Schedule,\n TakeSnapshotOptions,\n ApiResponse,\n} from \"./types.js\";\n","import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","/**\n * Browser session for orchestrating headless browsers in sandboxes.\n *\n * Each method generates a self-contained Python/Playwright script,\n * runs it inside the sandbox, and parses the JSON result.\n */\n\nimport type { AriaSnapshot, PageResult, RunOutput } from \"./types.js\";\n\ntype RunInSandboxFn = (\n name: string,\n command: string[],\n) => Promise<RunOutput>;\ntype RemoveSandboxFn = (name: string) => Promise<void>;\n\nconst GOTO_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n title = await page.title()\n url_final = page.url\n text = await page.evaluate(\"() => document.body.innerText.slice(0, 8000)\")\n links = await page.evaluate('''() =>\n Array.from(document.querySelectorAll('a[href]'))\n .slice(0, 50)\n .map(a => ({text: a.textContent.trim(), href: a.href}))\n .filter(l => l.href.startsWith(\"http\"))\n ''')\n print(json.dumps({\"title\": title, \"url\": url_final, \"text\": text, \"links\": links}))\n await b.close()\nasyncio.run(main())\n`;\n\nconst SCREENSHOT_SCRIPT = `\nimport asyncio, base64, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n data = await page.screenshot()\n print(base64.b64encode(data).decode())\n await b.close()\nasyncio.run(main())\n`;\n\nconst EVALUATE_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n expr = sys.argv[2]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n result = await page.evaluate(expr)\n print(json.dumps(result))\n await b.close()\nasyncio.run(main())\n`;\n\n/** Command to install Playwright + Chromium inside the sandbox. */\nexport const BROWSER_SETUP_CMD = [\n \"sh\",\n \"-c\",\n \"pip install -q playwright && playwright install --with-deps chromium\",\n];\n\n// --- v2 scripts ---\n\nconst BROWSER_HEALTH_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\ntry:\n req = urllib.request.urlopen(f\"http://127.0.0.1:{port}/health\", timeout=5)\n print(req.read().decode())\nexcept Exception as e:\n print(json.dumps({\"status\": \"down\", \"error\": str(e)}))\n sys.exit(1)\n`;\n\nconst BROWSER_REQUEST_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\nmethod = sys.argv[2] if len(sys.argv) > 2 else \"GET\"\npath = sys.argv[3] if len(sys.argv) > 3 else \"/health\"\nbody_str = sys.argv[4] if len(sys.argv) > 4 else None\nurl = f\"http://127.0.0.1:{port}{path}\"\ndata = body_str.encode() if body_str else None\nreq = urllib.request.Request(url, data=data, method=method)\nif data:\n req.add_header(\"Content-Type\", \"application/json\")\ntry:\n resp = urllib.request.urlopen(req, timeout=60)\n print(resp.read().decode())\nexcept urllib.error.HTTPError as e:\n print(e.read().decode())\n sys.exit(1)\nexcept Exception as e:\n print(json.dumps({\"error\": str(e)}))\n sys.exit(1)\n`;\n\n/**\n * A sandboxed headless browser controlled from outside.\n *\n * The browser (Chromium via Playwright) runs inside an agentkernel sandbox.\n * You call high-level methods; the SDK generates and runs scripts internally.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * ```\n */\nexport class BrowserSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private _lastUrl: string | null = null;\n private readonly _run: RunInSandboxFn;\n private readonly _remove: RemoveSandboxFn;\n\n /** @internal */\n constructor(name: string, runFn: RunInSandboxFn, removeFn: RemoveSandboxFn) {\n this.name = name;\n this._run = runFn;\n this._remove = removeFn;\n }\n\n /** Navigate to a URL and return page data (title, text, links). */\n async goto(url: string): Promise<PageResult> {\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n GOTO_SCRIPT,\n url,\n ]);\n this._lastUrl = url;\n return JSON.parse(result.output) as PageResult;\n }\n\n /** Take a PNG screenshot. Returns a base64-encoded string. */\n async screenshot(url?: string): Promise<string> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n SCREENSHOT_SCRIPT,\n target,\n ]);\n return result.output.trim();\n }\n\n /** Run a JavaScript expression on a page and return the result. */\n async evaluate(expression: string, url?: string): Promise<unknown> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n EVALUATE_SCRIPT,\n target,\n expression,\n ]);\n return JSON.parse(result.output);\n }\n\n // --- v2 methods (ARIA snapshots, persistent pages, ref-based interaction) ---\n\n /** Navigate to a URL and return an ARIA snapshot. */\n async open(url: string, page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/goto`,\n JSON.stringify({ url }),\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Get the current ARIA snapshot without navigating. */\n async snapshot(page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"GET\",\n `/pages/${page}/snapshot`,\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Click an element by ref ID or CSS selector. Returns new snapshot. */\n async click(opts: { ref?: string; selector?: string; page?: string }): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = {};\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/click`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Fill an input by ref ID or CSS selector. Returns new snapshot. */\n async fill(\n value: string,\n opts: { ref?: string; selector?: string; page?: string },\n ): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = { value };\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/fill`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Close a named page. */\n async closePage(page = \"default\"): Promise<void> {\n await this._ensureServer();\n await this._browserRequest(\"DELETE\", `/pages/${page}`);\n }\n\n /** List active page names. */\n async listPages(): Promise<string[]> {\n await this._ensureServer();\n const result = await this._browserRequest(\"GET\", \"/pages\");\n const data = JSON.parse(result.output);\n return data.pages ?? [];\n }\n\n private _serverStarted = false;\n\n private async _ensureServer(): Promise<void> {\n if (this._serverStarted) return;\n // Health check\n try {\n const result = await this._run(this.name, [\n \"python3\", \"-c\", BROWSER_HEALTH_SCRIPT, \"9222\",\n ]);\n if (result.output.includes('\"status\":\"ok\"') || result.output.includes('\"status\": \"ok\"')) {\n this._serverStarted = true;\n return;\n }\n } catch {\n // Server not running, start it\n }\n // Start would require the full server script + ARIA JS — for SDK use,\n // the server is expected to already be running (started via browser_create or MCP)\n throw new Error(\n \"Browser server not running. Use browser_create to set up the sandbox, \" +\n \"or use the MCP browser_open tool which auto-starts the server.\",\n );\n }\n\n private async _browserRequest(\n method: string,\n path: string,\n body?: string,\n ): Promise<RunOutput> {\n const cmd = [\"python3\", \"-c\", BROWSER_REQUEST_SCRIPT, \"9222\", method, path];\n if (body) cmd.push(body);\n return this._run(this.name, cmd);\n }\n\n // --- v1 methods (backward compatible) ---\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._remove(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import type {\n BatchFileWriteResponse,\n ExecOptions,\n RunOutput,\n SandboxInfo,\n} from \"./types.js\";\n\ntype ExecFn = (\n name: string,\n command: string[],\n opts?: ExecOptions,\n) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\ntype WriteFilesFn = (\n name: string,\n files: Record<string, string>,\n) => Promise<BatchFileWriteResponse>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n private readonly _writeFiles: WriteFilesFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n writeFiles: WriteFilesFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n this._writeFiles = writeFiles;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[], opts?: ExecOptions): Promise<RunOutput> {\n return this._execInSandbox(this.name, command, opts);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Write multiple files in one request. */\n async writeFiles(\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this._writeFiles(this.name, files);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\nconst MAX_FIELD_PREFIX_LENGTH = 6\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {maxBufferSize, onComment, onError, onEvent, onId, onRetry} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n let skippingLine = false\n\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM at the start of the very first chunk\n * is stripped before parsing. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Strip one leading UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream.)\n // Two representations can reach us depending on how the caller decoded the\n // bytes: a single decoded U+FEFF (e.g. a `TextDecoder` created with\n // `ignoreBOM`) or the raw 3-byte sequence (0xEF 0xBB 0xBF, e.g. a latin1 or\n // passthrough decode). Both are stripped so a leading BOM is ignored\n // regardless of decode path.\n if (chunk.charCodeAt(0) === 0xfeff) {\n chunk = chunk.slice(1)\n } else if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk)\n if (!chunk) {\n return\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n storeTrailing(trailing)\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head =\n pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength)\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n skippingLine = true\n return\n }\n }\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n storeTrailing(processLines(input))\n checkBufferSize()\n }\n\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk: string): string {\n if (chunk.length === 0) {\n return chunk\n }\n\n if (skipNextLineFeed) {\n skipNextLineFeed = false\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk\n }\n\n const crIndex = chunk.indexOf('\\r')\n const lfIndex = chunk.indexOf('\\n')\n const lineEnd =\n crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex\n\n if (lineEnd === -1) {\n return ''\n }\n\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false\n skipNextLineFeed = true\n return ''\n }\n\n skippingLine = false\n return chunk.slice(\n lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1),\n )\n }\n\n function storeTrailing(trailing: string) {\n if (!trailing) return\n\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1)\n skipNextLineFeed = true\n return\n }\n\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n return\n }\n\n skippingLine = true\n }\n\n function shouldBufferTrailing(trailing: string) {\n const firstCharCode = trailing.charCodeAt(0)\n return (\n (firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry'))\n )\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n skippingLine = false\n skipNextLineFeed = false\n onError?.(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId?.(id)\n }\n if (dataLines > 0) {\n onEvent?.({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId?.(id)\n }\n onEvent?.({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry?.(parseInt(value, 10))\n } else {\n onError?.(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError?.(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (id !== undefined) {\n onId?.(id)\n }\n\n if (dataLines > 0) {\n onEvent?.({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n skippingLine = false\n skipNextLineFeed = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n\nfunction isPotentialField(line: string, field: string): boolean {\n let i = 1\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false\n }\n i++\n }\n\n return line.length <= field.length || line.charCodeAt(field.length) === 58\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n BackendDiscovery,\n ApiResponse,\n BatchCommand,\n BatchFileWriteResponse,\n BatchRunResponse,\n CreateStoreRequest,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n FileReadResponse,\n FileWriteOptions,\n OrchestrationDefinition,\n RunOptions,\n RunOutput,\n Orchestration,\n SandboxInfo,\n Schedule,\n SnapshotMeta,\n StreamEvent,\n TakeSnapshotOptions,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.21.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Discover server-supported and ready sandbox backends. */\n async getBackends(): Promise<BackendDiscovery> {\n return this.request<BackendDiscovery>(\"GET\", \"/backends\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n backend: opts?.backend,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n source_url: opts?.source_url,\n source_ref: opts?.source_ref,\n volumes: opts?.volumes,\n secrets: opts?.secrets,\n secret_files: opts?.secret_files,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Get info about a sandbox by UUID. */\n async getSandboxByUuid(uuid: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"GET\",\n `/sandboxes/by-uuid/${encodeURIComponent(uuid)}`,\n );\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Write multiple files to a sandbox in one request. */\n async writeFiles(\n name: string,\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this.request<BatchFileWriteResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/files`,\n { files },\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /** Start a detached (background) command in a sandbox. */\n async execDetached(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detach`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Get the status of a detached command. */\n async detachedStatus(\n name: string,\n cmdId: string,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** Get logs from a detached command. */\n async detachedLogs(\n name: string,\n cmdId: string,\n stream?: \"stdout\" | \"stderr\",\n ): Promise<DetachedLogsResponse> {\n const query = stream === \"stderr\" ? \"?stream=stderr\" : \"\";\n return this.request<DetachedLogsResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`,\n );\n }\n\n /** Kill a detached command. */\n async detachedKill(name: string, cmdId: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** List detached commands in a sandbox. */\n async detachedList(name: string): Promise<DetachedCommand[]> {\n return this.request<DetachedCommand[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached`,\n );\n }\n\n /** List all orchestrations. */\n async listOrchestrations(): Promise<Orchestration[]> {\n return this.request<Orchestration[]>(\"GET\", \"/orchestrations\");\n }\n\n /** Create a new orchestration. */\n async createOrchestration(payload: CreateOrchestrationRequest): Promise<Orchestration> {\n return this.request<Orchestration>(\"POST\", \"/orchestrations\", payload);\n }\n\n /** Get info about an orchestration by identifier. */\n async getOrchestration(id: string): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"GET\",\n `/orchestrations/${encodeURIComponent(id)}`,\n );\n }\n\n /** Raise an external event for an orchestration. */\n async signalOrchestration(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/events`,\n payload,\n );\n }\n\n /** Terminate an orchestration. */\n async terminateOrchestration(\n id: string,\n payload?: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/terminate`,\n payload ?? {},\n );\n }\n\n /** List orchestration definitions. */\n async listOrchestrationDefinitions(): Promise<OrchestrationDefinition[]> {\n return this.request<OrchestrationDefinition[]>(\n \"GET\",\n \"/orchestrations/definitions\",\n );\n }\n\n /** Register or update an orchestration definition. */\n async upsertOrchestrationDefinition(\n payload: OrchestrationDefinition,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"POST\",\n \"/orchestrations/definitions\",\n payload,\n );\n }\n\n /** Get an orchestration definition by name. */\n async getOrchestrationDefinition(\n name: string,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"GET\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete an orchestration definition by name. */\n async deleteOrchestrationDefinition(name: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** List all objects. */\n async listObjects(): Promise<DurableObject[]> {\n return this.request<DurableObject[]>(\"GET\", \"/objects\");\n }\n\n /** Create a new object. */\n async createObject(payload: CreateObjectRequest): Promise<DurableObject> {\n return this.request<DurableObject>(\"POST\", \"/objects\", payload);\n }\n\n /** Get an object by identifier. */\n async getObject(id: string): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"GET\",\n `/objects/${encodeURIComponent(id)}`,\n );\n }\n\n /** Call a method on a durable object (auto-creates/wakes if needed). */\n async callObject(\n className: string,\n objectId: string,\n method: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const resp = await this.request(\n \"POST\",\n `/objects/${encodeURIComponent(className)}/${encodeURIComponent(objectId)}/call/${encodeURIComponent(method)}`,\n args ?? {},\n );\n return resp;\n }\n\n /** Delete a durable object by identifier. */\n async deleteObject(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/objects/${encodeURIComponent(id)}`);\n }\n\n /** Partially update a durable object (storage and/or status). */\n async patchObject(\n id: string,\n payload: { storage?: unknown; status?: string },\n ): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"PATCH\",\n `/objects/${encodeURIComponent(id)}`,\n payload,\n );\n }\n\n /** List all schedules. */\n async listSchedules(): Promise<Schedule[]> {\n return this.request<Schedule[]>(\"GET\", \"/schedules\");\n }\n\n /** Create a new schedule. */\n async createSchedule(payload: CreateScheduleRequest): Promise<Schedule> {\n return this.request<Schedule>(\"POST\", \"/schedules\", payload);\n }\n\n /** Get a schedule by identifier. */\n async getSchedule(id: string): Promise<Schedule> {\n return this.request<Schedule>(\n \"GET\",\n `/schedules/${encodeURIComponent(id)}`,\n );\n }\n\n /** Delete a schedule by identifier. */\n async deleteSchedule(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/schedules/${encodeURIComponent(id)}`);\n }\n\n /** List all durable stores. */\n async listStores(): Promise<DurableStore[]> {\n return this.request<DurableStore[]>(\"GET\", \"/stores\");\n }\n\n /** Create a durable store. */\n async createStore(payload: CreateStoreRequest): Promise<DurableStore> {\n return this.request<DurableStore>(\"POST\", \"/stores\", payload);\n }\n\n /** Get a durable store by identifier. */\n async getStore(id: string): Promise<DurableStore> {\n return this.request<DurableStore>(\"GET\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Delete a durable store by identifier. */\n async deleteStore(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Execute a read query against a durable store. */\n async queryStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreQueryResponse> {\n return this.request<DurableStoreQueryResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/query`,\n payload,\n );\n }\n\n /** Execute a write statement against a durable store. */\n async executeStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreExecuteResponse> {\n return this.request<DurableStoreExecuteResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/execute`,\n payload,\n );\n }\n\n /** Execute a command against a durable store (Redis-style engines). */\n async commandStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreCommandResponse> {\n return this.request<DurableStoreCommandResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/command`,\n payload,\n );\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd, o) => this.execInSandbox(n, cmd, o),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n (n, f) => this.writeFiles(n, f),\n );\n }\n\n /**\n * Create a sandboxed browser session with automatic cleanup.\n *\n * Creates a sandbox with Chromium pre-installed via Playwright.\n * Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async browser(\n name: string,\n opts?: { memory_mb?: number },\n ): Promise<BrowserSession> {\n await this.createSandbox(name, {\n image: \"python:3.12-slim\",\n memory_mb: opts?.memory_mb ?? 2048,\n profile: \"moderate\",\n });\n await this.execInSandbox(name, BROWSER_SETUP_CMD);\n return new BrowserSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n );\n }\n\n // -- TTL & Snapshot methods --\n\n /** Extend a sandbox's TTL. Returns the new expiry time. */\n async extendTtl(name: string, opts: ExtendTtlOptions): Promise<ExtendTtlResponse> {\n return this.request<ExtendTtlResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/extend`,\n { by: opts.by },\n );\n }\n\n /** List all snapshots. */\n async listSnapshots(): Promise<SnapshotMeta[]> {\n return this.request<SnapshotMeta[]>(\"GET\", \"/snapshots\");\n }\n\n /** Take a snapshot of a sandbox. */\n async takeSnapshot(opts: TakeSnapshotOptions): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\"POST\", \"/snapshots\", opts);\n }\n\n /** Get info about a snapshot. */\n async getSnapshot(name: string): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\n \"GET\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete a snapshot. */\n async deleteSnapshot(name: string): Promise<void> {\n await this.request<string>(\n \"DELETE\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Restore a sandbox from a snapshot. */\n async restoreSnapshot(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"POST\",\n `/snapshots/${encodeURIComponent(name)}/restore`,\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":["value","line"]}
package/dist/index.d.cts CHANGED
@@ -2,4 +2,4 @@ export { AgentKernel } from "./client.cjs";
2
2
  export { BrowserSession, BROWSER_SETUP_CMD } from "./browser.cjs";
3
3
  export { SandboxSession } from "./sandbox.cjs";
4
4
  export { AgentKernelError, AuthError, NotFoundError, ValidationError, ServerError, NetworkError, StreamError, } from "./errors.cjs";
5
- export type { AgentKernelOptions, AriaSnapshot, BatchFileWriteResponse, BrowserEvent, CreateSandboxOptions, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateStoreRequest, DetachedCommand, DetachedLogsResponse, DetachedStatus, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, PageLink, PageResult, RunOptions, RunOutput, Orchestration, OrchestrationDefinition, SandboxInfo, SnapshotMeta, StreamEvent, StreamEventType, SecurityProfile, SandboxStatus, Schedule, TakeSnapshotOptions, ApiResponse, } from "./types.cjs";
5
+ export type { AgentKernelOptions, BackendCapabilities, BackendDescriptor, BackendDiscovery, AriaSnapshot, BatchFileWriteResponse, BrowserEvent, CreateSandboxOptions, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateStoreRequest, DetachedCommand, DetachedLogsResponse, DetachedStatus, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, PageLink, PageResult, RunOptions, RunOutput, Orchestration, OrchestrationDefinition, SandboxInfo, SnapshotMeta, StreamEvent, StreamEventType, SecurityProfile, SandboxStatus, Schedule, TakeSnapshotOptions, ApiResponse, } from "./types.cjs";
package/dist/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export { AgentKernel } from "./client.js";
2
2
  export { BrowserSession, BROWSER_SETUP_CMD } from "./browser.js";
3
3
  export { SandboxSession } from "./sandbox.js";
4
4
  export { AgentKernelError, AuthError, NotFoundError, ValidationError, ServerError, NetworkError, StreamError, } from "./errors.js";
5
- export type { AgentKernelOptions, AriaSnapshot, BatchFileWriteResponse, BrowserEvent, CreateSandboxOptions, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateStoreRequest, DetachedCommand, DetachedLogsResponse, DetachedStatus, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, PageLink, PageResult, RunOptions, RunOutput, Orchestration, OrchestrationDefinition, SandboxInfo, SnapshotMeta, StreamEvent, StreamEventType, SecurityProfile, SandboxStatus, Schedule, TakeSnapshotOptions, ApiResponse, } from "./types.js";
5
+ export type { AgentKernelOptions, BackendCapabilities, BackendDescriptor, BackendDiscovery, AriaSnapshot, BatchFileWriteResponse, BrowserEvent, CreateSandboxOptions, CreateObjectRequest, CreateOrchestrationRequest, CreateScheduleRequest, CreateStoreRequest, DetachedCommand, DetachedLogsResponse, DetachedStatus, ExecOptions, ExtendTtlOptions, ExtendTtlResponse, DurableObject, DurableStore, DurableStoreCommandResponse, DurableStoreExecuteResponse, DurableStoreQueryResponse, PageLink, PageResult, RunOptions, RunOutput, Orchestration, OrchestrationDefinition, SandboxInfo, SnapshotMeta, StreamEvent, StreamEventType, SecurityProfile, SandboxStatus, Schedule, TakeSnapshotOptions, ApiResponse, } from "./types.js";
package/dist/index.js CHANGED
@@ -767,7 +767,7 @@ async function* parseSSE(body) {
767
767
  }
768
768
 
769
769
  // src/client.ts
770
- var SDK_VERSION = "0.3.0";
770
+ var SDK_VERSION = "0.21.0";
771
771
  var AgentKernel = class {
772
772
  baseUrl;
773
773
  apiKey;
@@ -828,10 +828,15 @@ var AgentKernel = class {
828
828
  async listSandboxes() {
829
829
  return this.request("GET", "/sandboxes");
830
830
  }
831
+ /** Discover server-supported and ready sandbox backends. */
832
+ async getBackends() {
833
+ return this.request("GET", "/backends");
834
+ }
831
835
  /** Create a new sandbox. */
832
836
  async createSandbox(name, opts) {
833
837
  return this.request("POST", "/sandboxes", {
834
838
  name,
839
+ backend: opts?.backend,
835
840
  image: opts?.image,
836
841
  vcpus: opts?.vcpus,
837
842
  memory_mb: opts?.memory_mb,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","/**\n * Browser session for orchestrating headless browsers in sandboxes.\n *\n * Each method generates a self-contained Python/Playwright script,\n * runs it inside the sandbox, and parses the JSON result.\n */\n\nimport type { AriaSnapshot, PageResult, RunOutput } from \"./types.js\";\n\ntype RunInSandboxFn = (\n name: string,\n command: string[],\n) => Promise<RunOutput>;\ntype RemoveSandboxFn = (name: string) => Promise<void>;\n\nconst GOTO_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n title = await page.title()\n url_final = page.url\n text = await page.evaluate(\"() => document.body.innerText.slice(0, 8000)\")\n links = await page.evaluate('''() =>\n Array.from(document.querySelectorAll('a[href]'))\n .slice(0, 50)\n .map(a => ({text: a.textContent.trim(), href: a.href}))\n .filter(l => l.href.startsWith(\"http\"))\n ''')\n print(json.dumps({\"title\": title, \"url\": url_final, \"text\": text, \"links\": links}))\n await b.close()\nasyncio.run(main())\n`;\n\nconst SCREENSHOT_SCRIPT = `\nimport asyncio, base64, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n data = await page.screenshot()\n print(base64.b64encode(data).decode())\n await b.close()\nasyncio.run(main())\n`;\n\nconst EVALUATE_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n expr = sys.argv[2]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n result = await page.evaluate(expr)\n print(json.dumps(result))\n await b.close()\nasyncio.run(main())\n`;\n\n/** Command to install Playwright + Chromium inside the sandbox. */\nexport const BROWSER_SETUP_CMD = [\n \"sh\",\n \"-c\",\n \"pip install -q playwright && playwright install --with-deps chromium\",\n];\n\n// --- v2 scripts ---\n\nconst BROWSER_HEALTH_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\ntry:\n req = urllib.request.urlopen(f\"http://127.0.0.1:{port}/health\", timeout=5)\n print(req.read().decode())\nexcept Exception as e:\n print(json.dumps({\"status\": \"down\", \"error\": str(e)}))\n sys.exit(1)\n`;\n\nconst BROWSER_REQUEST_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\nmethod = sys.argv[2] if len(sys.argv) > 2 else \"GET\"\npath = sys.argv[3] if len(sys.argv) > 3 else \"/health\"\nbody_str = sys.argv[4] if len(sys.argv) > 4 else None\nurl = f\"http://127.0.0.1:{port}{path}\"\ndata = body_str.encode() if body_str else None\nreq = urllib.request.Request(url, data=data, method=method)\nif data:\n req.add_header(\"Content-Type\", \"application/json\")\ntry:\n resp = urllib.request.urlopen(req, timeout=60)\n print(resp.read().decode())\nexcept urllib.error.HTTPError as e:\n print(e.read().decode())\n sys.exit(1)\nexcept Exception as e:\n print(json.dumps({\"error\": str(e)}))\n sys.exit(1)\n`;\n\n/**\n * A sandboxed headless browser controlled from outside.\n *\n * The browser (Chromium via Playwright) runs inside an agentkernel sandbox.\n * You call high-level methods; the SDK generates and runs scripts internally.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * ```\n */\nexport class BrowserSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private _lastUrl: string | null = null;\n private readonly _run: RunInSandboxFn;\n private readonly _remove: RemoveSandboxFn;\n\n /** @internal */\n constructor(name: string, runFn: RunInSandboxFn, removeFn: RemoveSandboxFn) {\n this.name = name;\n this._run = runFn;\n this._remove = removeFn;\n }\n\n /** Navigate to a URL and return page data (title, text, links). */\n async goto(url: string): Promise<PageResult> {\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n GOTO_SCRIPT,\n url,\n ]);\n this._lastUrl = url;\n return JSON.parse(result.output) as PageResult;\n }\n\n /** Take a PNG screenshot. Returns a base64-encoded string. */\n async screenshot(url?: string): Promise<string> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n SCREENSHOT_SCRIPT,\n target,\n ]);\n return result.output.trim();\n }\n\n /** Run a JavaScript expression on a page and return the result. */\n async evaluate(expression: string, url?: string): Promise<unknown> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n EVALUATE_SCRIPT,\n target,\n expression,\n ]);\n return JSON.parse(result.output);\n }\n\n // --- v2 methods (ARIA snapshots, persistent pages, ref-based interaction) ---\n\n /** Navigate to a URL and return an ARIA snapshot. */\n async open(url: string, page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/goto`,\n JSON.stringify({ url }),\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Get the current ARIA snapshot without navigating. */\n async snapshot(page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"GET\",\n `/pages/${page}/snapshot`,\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Click an element by ref ID or CSS selector. Returns new snapshot. */\n async click(opts: { ref?: string; selector?: string; page?: string }): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = {};\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/click`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Fill an input by ref ID or CSS selector. Returns new snapshot. */\n async fill(\n value: string,\n opts: { ref?: string; selector?: string; page?: string },\n ): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = { value };\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/fill`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Close a named page. */\n async closePage(page = \"default\"): Promise<void> {\n await this._ensureServer();\n await this._browserRequest(\"DELETE\", `/pages/${page}`);\n }\n\n /** List active page names. */\n async listPages(): Promise<string[]> {\n await this._ensureServer();\n const result = await this._browserRequest(\"GET\", \"/pages\");\n const data = JSON.parse(result.output);\n return data.pages ?? [];\n }\n\n private _serverStarted = false;\n\n private async _ensureServer(): Promise<void> {\n if (this._serverStarted) return;\n // Health check\n try {\n const result = await this._run(this.name, [\n \"python3\", \"-c\", BROWSER_HEALTH_SCRIPT, \"9222\",\n ]);\n if (result.output.includes('\"status\":\"ok\"') || result.output.includes('\"status\": \"ok\"')) {\n this._serverStarted = true;\n return;\n }\n } catch {\n // Server not running, start it\n }\n // Start would require the full server script + ARIA JS — for SDK use,\n // the server is expected to already be running (started via browser_create or MCP)\n throw new Error(\n \"Browser server not running. Use browser_create to set up the sandbox, \" +\n \"or use the MCP browser_open tool which auto-starts the server.\",\n );\n }\n\n private async _browserRequest(\n method: string,\n path: string,\n body?: string,\n ): Promise<RunOutput> {\n const cmd = [\"python3\", \"-c\", BROWSER_REQUEST_SCRIPT, \"9222\", method, path];\n if (body) cmd.push(body);\n return this._run(this.name, cmd);\n }\n\n // --- v1 methods (backward compatible) ---\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._remove(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import type {\n BatchFileWriteResponse,\n ExecOptions,\n RunOutput,\n SandboxInfo,\n} from \"./types.js\";\n\ntype ExecFn = (\n name: string,\n command: string[],\n opts?: ExecOptions,\n) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\ntype WriteFilesFn = (\n name: string,\n files: Record<string, string>,\n) => Promise<BatchFileWriteResponse>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n private readonly _writeFiles: WriteFilesFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n writeFiles: WriteFilesFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n this._writeFiles = writeFiles;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[], opts?: ExecOptions): Promise<RunOutput> {\n return this._execInSandbox(this.name, command, opts);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Write multiple files in one request. */\n async writeFiles(\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this._writeFiles(this.name, files);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\nconst MAX_FIELD_PREFIX_LENGTH = 6\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {maxBufferSize, onComment, onError, onEvent, onId, onRetry} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n let skippingLine = false\n\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM at the start of the very first chunk\n * is stripped before parsing. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Strip one leading UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream.)\n // Two representations can reach us depending on how the caller decoded the\n // bytes: a single decoded U+FEFF (e.g. a `TextDecoder` created with\n // `ignoreBOM`) or the raw 3-byte sequence (0xEF 0xBB 0xBF, e.g. a latin1 or\n // passthrough decode). Both are stripped so a leading BOM is ignored\n // regardless of decode path.\n if (chunk.charCodeAt(0) === 0xfeff) {\n chunk = chunk.slice(1)\n } else if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk)\n if (!chunk) {\n return\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n storeTrailing(trailing)\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head =\n pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength)\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n skippingLine = true\n return\n }\n }\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n storeTrailing(processLines(input))\n checkBufferSize()\n }\n\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk: string): string {\n if (chunk.length === 0) {\n return chunk\n }\n\n if (skipNextLineFeed) {\n skipNextLineFeed = false\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk\n }\n\n const crIndex = chunk.indexOf('\\r')\n const lfIndex = chunk.indexOf('\\n')\n const lineEnd =\n crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex\n\n if (lineEnd === -1) {\n return ''\n }\n\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false\n skipNextLineFeed = true\n return ''\n }\n\n skippingLine = false\n return chunk.slice(\n lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1),\n )\n }\n\n function storeTrailing(trailing: string) {\n if (!trailing) return\n\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1)\n skipNextLineFeed = true\n return\n }\n\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n return\n }\n\n skippingLine = true\n }\n\n function shouldBufferTrailing(trailing: string) {\n const firstCharCode = trailing.charCodeAt(0)\n return (\n (firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry'))\n )\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n skippingLine = false\n skipNextLineFeed = false\n onError?.(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId?.(id)\n }\n if (dataLines > 0) {\n onEvent?.({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId?.(id)\n }\n onEvent?.({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry?.(parseInt(value, 10))\n } else {\n onError?.(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError?.(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (id !== undefined) {\n onId?.(id)\n }\n\n if (dataLines > 0) {\n onEvent?.({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n skippingLine = false\n skipNextLineFeed = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n\nfunction isPotentialField(line: string, field: string): boolean {\n let i = 1\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false\n }\n i++\n }\n\n return line.length <= field.length || line.charCodeAt(field.length) === 58\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n ApiResponse,\n BatchCommand,\n BatchFileWriteResponse,\n BatchRunResponse,\n CreateStoreRequest,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n FileReadResponse,\n FileWriteOptions,\n OrchestrationDefinition,\n RunOptions,\n RunOutput,\n Orchestration,\n SandboxInfo,\n Schedule,\n SnapshotMeta,\n StreamEvent,\n TakeSnapshotOptions,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.3.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n source_url: opts?.source_url,\n source_ref: opts?.source_ref,\n volumes: opts?.volumes,\n secrets: opts?.secrets,\n secret_files: opts?.secret_files,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Get info about a sandbox by UUID. */\n async getSandboxByUuid(uuid: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"GET\",\n `/sandboxes/by-uuid/${encodeURIComponent(uuid)}`,\n );\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Write multiple files to a sandbox in one request. */\n async writeFiles(\n name: string,\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this.request<BatchFileWriteResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/files`,\n { files },\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /** Start a detached (background) command in a sandbox. */\n async execDetached(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detach`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Get the status of a detached command. */\n async detachedStatus(\n name: string,\n cmdId: string,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** Get logs from a detached command. */\n async detachedLogs(\n name: string,\n cmdId: string,\n stream?: \"stdout\" | \"stderr\",\n ): Promise<DetachedLogsResponse> {\n const query = stream === \"stderr\" ? \"?stream=stderr\" : \"\";\n return this.request<DetachedLogsResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`,\n );\n }\n\n /** Kill a detached command. */\n async detachedKill(name: string, cmdId: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** List detached commands in a sandbox. */\n async detachedList(name: string): Promise<DetachedCommand[]> {\n return this.request<DetachedCommand[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached`,\n );\n }\n\n /** List all orchestrations. */\n async listOrchestrations(): Promise<Orchestration[]> {\n return this.request<Orchestration[]>(\"GET\", \"/orchestrations\");\n }\n\n /** Create a new orchestration. */\n async createOrchestration(payload: CreateOrchestrationRequest): Promise<Orchestration> {\n return this.request<Orchestration>(\"POST\", \"/orchestrations\", payload);\n }\n\n /** Get info about an orchestration by identifier. */\n async getOrchestration(id: string): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"GET\",\n `/orchestrations/${encodeURIComponent(id)}`,\n );\n }\n\n /** Raise an external event for an orchestration. */\n async signalOrchestration(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/events`,\n payload,\n );\n }\n\n /** Terminate an orchestration. */\n async terminateOrchestration(\n id: string,\n payload?: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/terminate`,\n payload ?? {},\n );\n }\n\n /** List orchestration definitions. */\n async listOrchestrationDefinitions(): Promise<OrchestrationDefinition[]> {\n return this.request<OrchestrationDefinition[]>(\n \"GET\",\n \"/orchestrations/definitions\",\n );\n }\n\n /** Register or update an orchestration definition. */\n async upsertOrchestrationDefinition(\n payload: OrchestrationDefinition,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"POST\",\n \"/orchestrations/definitions\",\n payload,\n );\n }\n\n /** Get an orchestration definition by name. */\n async getOrchestrationDefinition(\n name: string,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"GET\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete an orchestration definition by name. */\n async deleteOrchestrationDefinition(name: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** List all objects. */\n async listObjects(): Promise<DurableObject[]> {\n return this.request<DurableObject[]>(\"GET\", \"/objects\");\n }\n\n /** Create a new object. */\n async createObject(payload: CreateObjectRequest): Promise<DurableObject> {\n return this.request<DurableObject>(\"POST\", \"/objects\", payload);\n }\n\n /** Get an object by identifier. */\n async getObject(id: string): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"GET\",\n `/objects/${encodeURIComponent(id)}`,\n );\n }\n\n /** Call a method on a durable object (auto-creates/wakes if needed). */\n async callObject(\n className: string,\n objectId: string,\n method: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const resp = await this.request(\n \"POST\",\n `/objects/${encodeURIComponent(className)}/${encodeURIComponent(objectId)}/call/${encodeURIComponent(method)}`,\n args ?? {},\n );\n return resp;\n }\n\n /** Delete a durable object by identifier. */\n async deleteObject(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/objects/${encodeURIComponent(id)}`);\n }\n\n /** Partially update a durable object (storage and/or status). */\n async patchObject(\n id: string,\n payload: { storage?: unknown; status?: string },\n ): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"PATCH\",\n `/objects/${encodeURIComponent(id)}`,\n payload,\n );\n }\n\n /** List all schedules. */\n async listSchedules(): Promise<Schedule[]> {\n return this.request<Schedule[]>(\"GET\", \"/schedules\");\n }\n\n /** Create a new schedule. */\n async createSchedule(payload: CreateScheduleRequest): Promise<Schedule> {\n return this.request<Schedule>(\"POST\", \"/schedules\", payload);\n }\n\n /** Get a schedule by identifier. */\n async getSchedule(id: string): Promise<Schedule> {\n return this.request<Schedule>(\n \"GET\",\n `/schedules/${encodeURIComponent(id)}`,\n );\n }\n\n /** Delete a schedule by identifier. */\n async deleteSchedule(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/schedules/${encodeURIComponent(id)}`);\n }\n\n /** List all durable stores. */\n async listStores(): Promise<DurableStore[]> {\n return this.request<DurableStore[]>(\"GET\", \"/stores\");\n }\n\n /** Create a durable store. */\n async createStore(payload: CreateStoreRequest): Promise<DurableStore> {\n return this.request<DurableStore>(\"POST\", \"/stores\", payload);\n }\n\n /** Get a durable store by identifier. */\n async getStore(id: string): Promise<DurableStore> {\n return this.request<DurableStore>(\"GET\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Delete a durable store by identifier. */\n async deleteStore(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Execute a read query against a durable store. */\n async queryStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreQueryResponse> {\n return this.request<DurableStoreQueryResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/query`,\n payload,\n );\n }\n\n /** Execute a write statement against a durable store. */\n async executeStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreExecuteResponse> {\n return this.request<DurableStoreExecuteResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/execute`,\n payload,\n );\n }\n\n /** Execute a command against a durable store (Redis-style engines). */\n async commandStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreCommandResponse> {\n return this.request<DurableStoreCommandResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/command`,\n payload,\n );\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd, o) => this.execInSandbox(n, cmd, o),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n (n, f) => this.writeFiles(n, f),\n );\n }\n\n /**\n * Create a sandboxed browser session with automatic cleanup.\n *\n * Creates a sandbox with Chromium pre-installed via Playwright.\n * Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async browser(\n name: string,\n opts?: { memory_mb?: number },\n ): Promise<BrowserSession> {\n await this.createSandbox(name, {\n image: \"python:3.12-slim\",\n memory_mb: opts?.memory_mb ?? 2048,\n profile: \"moderate\",\n });\n await this.execInSandbox(name, BROWSER_SETUP_CMD);\n return new BrowserSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n );\n }\n\n // -- TTL & Snapshot methods --\n\n /** Extend a sandbox's TTL. Returns the new expiry time. */\n async extendTtl(name: string, opts: ExtendTtlOptions): Promise<ExtendTtlResponse> {\n return this.request<ExtendTtlResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/extend`,\n { by: opts.by },\n );\n }\n\n /** List all snapshots. */\n async listSnapshots(): Promise<SnapshotMeta[]> {\n return this.request<SnapshotMeta[]>(\"GET\", \"/snapshots\");\n }\n\n /** Take a snapshot of a sandbox. */\n async takeSnapshot(opts: TakeSnapshotOptions): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\"POST\", \"/snapshots\", opts);\n }\n\n /** Get info about a snapshot. */\n async getSnapshot(name: string): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\n \"GET\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete a snapshot. */\n async deleteSnapshot(name: string): Promise<void> {\n await this.request<string>(\n \"DELETE\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Restore a sandbox from a snapshot. */\n async restoreSnapshot(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"POST\",\n `/snapshots/${encodeURIComponent(name)}/restore`,\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":["value","line"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","/**\n * Browser session for orchestrating headless browsers in sandboxes.\n *\n * Each method generates a self-contained Python/Playwright script,\n * runs it inside the sandbox, and parses the JSON result.\n */\n\nimport type { AriaSnapshot, PageResult, RunOutput } from \"./types.js\";\n\ntype RunInSandboxFn = (\n name: string,\n command: string[],\n) => Promise<RunOutput>;\ntype RemoveSandboxFn = (name: string) => Promise<void>;\n\nconst GOTO_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n title = await page.title()\n url_final = page.url\n text = await page.evaluate(\"() => document.body.innerText.slice(0, 8000)\")\n links = await page.evaluate('''() =>\n Array.from(document.querySelectorAll('a[href]'))\n .slice(0, 50)\n .map(a => ({text: a.textContent.trim(), href: a.href}))\n .filter(l => l.href.startsWith(\"http\"))\n ''')\n print(json.dumps({\"title\": title, \"url\": url_final, \"text\": text, \"links\": links}))\n await b.close()\nasyncio.run(main())\n`;\n\nconst SCREENSHOT_SCRIPT = `\nimport asyncio, base64, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n data = await page.screenshot()\n print(base64.b64encode(data).decode())\n await b.close()\nasyncio.run(main())\n`;\n\nconst EVALUATE_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n expr = sys.argv[2]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n result = await page.evaluate(expr)\n print(json.dumps(result))\n await b.close()\nasyncio.run(main())\n`;\n\n/** Command to install Playwright + Chromium inside the sandbox. */\nexport const BROWSER_SETUP_CMD = [\n \"sh\",\n \"-c\",\n \"pip install -q playwright && playwright install --with-deps chromium\",\n];\n\n// --- v2 scripts ---\n\nconst BROWSER_HEALTH_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\ntry:\n req = urllib.request.urlopen(f\"http://127.0.0.1:{port}/health\", timeout=5)\n print(req.read().decode())\nexcept Exception as e:\n print(json.dumps({\"status\": \"down\", \"error\": str(e)}))\n sys.exit(1)\n`;\n\nconst BROWSER_REQUEST_SCRIPT = `\nimport json, urllib.request, sys\nport = sys.argv[1] if len(sys.argv) > 1 else \"9222\"\nmethod = sys.argv[2] if len(sys.argv) > 2 else \"GET\"\npath = sys.argv[3] if len(sys.argv) > 3 else \"/health\"\nbody_str = sys.argv[4] if len(sys.argv) > 4 else None\nurl = f\"http://127.0.0.1:{port}{path}\"\ndata = body_str.encode() if body_str else None\nreq = urllib.request.Request(url, data=data, method=method)\nif data:\n req.add_header(\"Content-Type\", \"application/json\")\ntry:\n resp = urllib.request.urlopen(req, timeout=60)\n print(resp.read().decode())\nexcept urllib.error.HTTPError as e:\n print(e.read().decode())\n sys.exit(1)\nexcept Exception as e:\n print(json.dumps({\"error\": str(e)}))\n sys.exit(1)\n`;\n\n/**\n * A sandboxed headless browser controlled from outside.\n *\n * The browser (Chromium via Playwright) runs inside an agentkernel sandbox.\n * You call high-level methods; the SDK generates and runs scripts internally.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * ```\n */\nexport class BrowserSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private _lastUrl: string | null = null;\n private readonly _run: RunInSandboxFn;\n private readonly _remove: RemoveSandboxFn;\n\n /** @internal */\n constructor(name: string, runFn: RunInSandboxFn, removeFn: RemoveSandboxFn) {\n this.name = name;\n this._run = runFn;\n this._remove = removeFn;\n }\n\n /** Navigate to a URL and return page data (title, text, links). */\n async goto(url: string): Promise<PageResult> {\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n GOTO_SCRIPT,\n url,\n ]);\n this._lastUrl = url;\n return JSON.parse(result.output) as PageResult;\n }\n\n /** Take a PNG screenshot. Returns a base64-encoded string. */\n async screenshot(url?: string): Promise<string> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n SCREENSHOT_SCRIPT,\n target,\n ]);\n return result.output.trim();\n }\n\n /** Run a JavaScript expression on a page and return the result. */\n async evaluate(expression: string, url?: string): Promise<unknown> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n EVALUATE_SCRIPT,\n target,\n expression,\n ]);\n return JSON.parse(result.output);\n }\n\n // --- v2 methods (ARIA snapshots, persistent pages, ref-based interaction) ---\n\n /** Navigate to a URL and return an ARIA snapshot. */\n async open(url: string, page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/goto`,\n JSON.stringify({ url }),\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Get the current ARIA snapshot without navigating. */\n async snapshot(page = \"default\"): Promise<AriaSnapshot> {\n await this._ensureServer();\n const result = await this._browserRequest(\n \"GET\",\n `/pages/${page}/snapshot`,\n );\n return JSON.parse(result.output) as AriaSnapshot;\n }\n\n /** Click an element by ref ID or CSS selector. Returns new snapshot. */\n async click(opts: { ref?: string; selector?: string; page?: string }): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = {};\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/click`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Fill an input by ref ID or CSS selector. Returns new snapshot. */\n async fill(\n value: string,\n opts: { ref?: string; selector?: string; page?: string },\n ): Promise<AriaSnapshot> {\n const page = opts.page ?? \"default\";\n await this._ensureServer();\n const body: Record<string, string> = { value };\n if (opts.ref) body.ref = opts.ref;\n if (opts.selector) body.selector = opts.selector;\n const result = await this._browserRequest(\n \"POST\",\n `/pages/${page}/fill`,\n JSON.stringify(body),\n );\n const data = JSON.parse(result.output);\n if (data.error) throw new Error(data.error);\n return data as AriaSnapshot;\n }\n\n /** Close a named page. */\n async closePage(page = \"default\"): Promise<void> {\n await this._ensureServer();\n await this._browserRequest(\"DELETE\", `/pages/${page}`);\n }\n\n /** List active page names. */\n async listPages(): Promise<string[]> {\n await this._ensureServer();\n const result = await this._browserRequest(\"GET\", \"/pages\");\n const data = JSON.parse(result.output);\n return data.pages ?? [];\n }\n\n private _serverStarted = false;\n\n private async _ensureServer(): Promise<void> {\n if (this._serverStarted) return;\n // Health check\n try {\n const result = await this._run(this.name, [\n \"python3\", \"-c\", BROWSER_HEALTH_SCRIPT, \"9222\",\n ]);\n if (result.output.includes('\"status\":\"ok\"') || result.output.includes('\"status\": \"ok\"')) {\n this._serverStarted = true;\n return;\n }\n } catch {\n // Server not running, start it\n }\n // Start would require the full server script + ARIA JS — for SDK use,\n // the server is expected to already be running (started via browser_create or MCP)\n throw new Error(\n \"Browser server not running. Use browser_create to set up the sandbox, \" +\n \"or use the MCP browser_open tool which auto-starts the server.\",\n );\n }\n\n private async _browserRequest(\n method: string,\n path: string,\n body?: string,\n ): Promise<RunOutput> {\n const cmd = [\"python3\", \"-c\", BROWSER_REQUEST_SCRIPT, \"9222\", method, path];\n if (body) cmd.push(body);\n return this._run(this.name, cmd);\n }\n\n // --- v1 methods (backward compatible) ---\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._remove(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import type {\n BatchFileWriteResponse,\n ExecOptions,\n RunOutput,\n SandboxInfo,\n} from \"./types.js\";\n\ntype ExecFn = (\n name: string,\n command: string[],\n opts?: ExecOptions,\n) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\ntype WriteFilesFn = (\n name: string,\n files: Record<string, string>,\n) => Promise<BatchFileWriteResponse>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n private readonly _writeFiles: WriteFilesFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n writeFiles: WriteFilesFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n this._writeFiles = writeFiles;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[], opts?: ExecOptions): Promise<RunOutput> {\n return this._execInSandbox(this.name, command, opts);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Write multiple files in one request. */\n async writeFiles(\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this._writeFiles(this.name, files);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\nconst MAX_FIELD_PREFIX_LENGTH = 6\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {maxBufferSize, onComment, onError, onEvent, onId, onRetry} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n let skippingLine = false\n\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM at the start of the very first chunk\n * is stripped before parsing. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Strip one leading UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream.)\n // Two representations can reach us depending on how the caller decoded the\n // bytes: a single decoded U+FEFF (e.g. a `TextDecoder` created with\n // `ignoreBOM`) or the raw 3-byte sequence (0xEF 0xBB 0xBF, e.g. a latin1 or\n // passthrough decode). Both are stripped so a leading BOM is ignored\n // regardless of decode path.\n if (chunk.charCodeAt(0) === 0xfeff) {\n chunk = chunk.slice(1)\n } else if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk)\n if (!chunk) {\n return\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n storeTrailing(trailing)\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head =\n pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength)\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n skippingLine = true\n return\n }\n }\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n storeTrailing(processLines(input))\n checkBufferSize()\n }\n\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk: string): string {\n if (chunk.length === 0) {\n return chunk\n }\n\n if (skipNextLineFeed) {\n skipNextLineFeed = false\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk\n }\n\n const crIndex = chunk.indexOf('\\r')\n const lfIndex = chunk.indexOf('\\n')\n const lineEnd =\n crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex\n\n if (lineEnd === -1) {\n return ''\n }\n\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false\n skipNextLineFeed = true\n return ''\n }\n\n skippingLine = false\n return chunk.slice(\n lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1),\n )\n }\n\n function storeTrailing(trailing: string) {\n if (!trailing) return\n\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1)\n skipNextLineFeed = true\n return\n }\n\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n return\n }\n\n skippingLine = true\n }\n\n function shouldBufferTrailing(trailing: string) {\n const firstCharCode = trailing.charCodeAt(0)\n return (\n (firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry'))\n )\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n skippingLine = false\n skipNextLineFeed = false\n onError?.(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (id !== undefined) {\n onId?.(id)\n }\n if (dataLines > 0) {\n onEvent?.({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n if (id !== undefined) {\n onId?.(id)\n }\n onEvent?.({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry?.(parseInt(value, 10))\n } else {\n onError?.(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError?.(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (id !== undefined) {\n onId?.(id)\n }\n\n if (dataLines > 0) {\n onEvent?.({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n skippingLine = false\n skipNextLineFeed = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n\nfunction isPotentialField(line: string, field: string): boolean {\n let i = 1\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false\n }\n i++\n }\n\n return line.length <= field.length || line.charCodeAt(field.length) === 58\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n BackendDiscovery,\n ApiResponse,\n BatchCommand,\n BatchFileWriteResponse,\n BatchRunResponse,\n CreateStoreRequest,\n CreateObjectRequest,\n CreateOrchestrationRequest,\n CreateScheduleRequest,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n DurableObject,\n DurableStore,\n DurableStoreCommandResponse,\n DurableStoreExecuteResponse,\n DurableStoreQueryResponse,\n FileReadResponse,\n FileWriteOptions,\n OrchestrationDefinition,\n RunOptions,\n RunOutput,\n Orchestration,\n SandboxInfo,\n Schedule,\n SnapshotMeta,\n StreamEvent,\n TakeSnapshotOptions,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.21.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Discover server-supported and ready sandbox backends. */\n async getBackends(): Promise<BackendDiscovery> {\n return this.request<BackendDiscovery>(\"GET\", \"/backends\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n backend: opts?.backend,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n source_url: opts?.source_url,\n source_ref: opts?.source_ref,\n volumes: opts?.volumes,\n secrets: opts?.secrets,\n secret_files: opts?.secret_files,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Get info about a sandbox by UUID. */\n async getSandboxByUuid(uuid: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"GET\",\n `/sandboxes/by-uuid/${encodeURIComponent(uuid)}`,\n );\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Write multiple files to a sandbox in one request. */\n async writeFiles(\n name: string,\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this.request<BatchFileWriteResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/files`,\n { files },\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /** Start a detached (background) command in a sandbox. */\n async execDetached(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detach`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Get the status of a detached command. */\n async detachedStatus(\n name: string,\n cmdId: string,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** Get logs from a detached command. */\n async detachedLogs(\n name: string,\n cmdId: string,\n stream?: \"stdout\" | \"stderr\",\n ): Promise<DetachedLogsResponse> {\n const query = stream === \"stderr\" ? \"?stream=stderr\" : \"\";\n return this.request<DetachedLogsResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`,\n );\n }\n\n /** Kill a detached command. */\n async detachedKill(name: string, cmdId: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** List detached commands in a sandbox. */\n async detachedList(name: string): Promise<DetachedCommand[]> {\n return this.request<DetachedCommand[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached`,\n );\n }\n\n /** List all orchestrations. */\n async listOrchestrations(): Promise<Orchestration[]> {\n return this.request<Orchestration[]>(\"GET\", \"/orchestrations\");\n }\n\n /** Create a new orchestration. */\n async createOrchestration(payload: CreateOrchestrationRequest): Promise<Orchestration> {\n return this.request<Orchestration>(\"POST\", \"/orchestrations\", payload);\n }\n\n /** Get info about an orchestration by identifier. */\n async getOrchestration(id: string): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"GET\",\n `/orchestrations/${encodeURIComponent(id)}`,\n );\n }\n\n /** Raise an external event for an orchestration. */\n async signalOrchestration(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/events`,\n payload,\n );\n }\n\n /** Terminate an orchestration. */\n async terminateOrchestration(\n id: string,\n payload?: Record<string, unknown>,\n ): Promise<Orchestration> {\n return this.request<Orchestration>(\n \"POST\",\n `/orchestrations/${encodeURIComponent(id)}/terminate`,\n payload ?? {},\n );\n }\n\n /** List orchestration definitions. */\n async listOrchestrationDefinitions(): Promise<OrchestrationDefinition[]> {\n return this.request<OrchestrationDefinition[]>(\n \"GET\",\n \"/orchestrations/definitions\",\n );\n }\n\n /** Register or update an orchestration definition. */\n async upsertOrchestrationDefinition(\n payload: OrchestrationDefinition,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"POST\",\n \"/orchestrations/definitions\",\n payload,\n );\n }\n\n /** Get an orchestration definition by name. */\n async getOrchestrationDefinition(\n name: string,\n ): Promise<OrchestrationDefinition> {\n return this.request<OrchestrationDefinition>(\n \"GET\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete an orchestration definition by name. */\n async deleteOrchestrationDefinition(name: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/orchestrations/definitions/${encodeURIComponent(name)}`,\n );\n }\n\n /** List all objects. */\n async listObjects(): Promise<DurableObject[]> {\n return this.request<DurableObject[]>(\"GET\", \"/objects\");\n }\n\n /** Create a new object. */\n async createObject(payload: CreateObjectRequest): Promise<DurableObject> {\n return this.request<DurableObject>(\"POST\", \"/objects\", payload);\n }\n\n /** Get an object by identifier. */\n async getObject(id: string): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"GET\",\n `/objects/${encodeURIComponent(id)}`,\n );\n }\n\n /** Call a method on a durable object (auto-creates/wakes if needed). */\n async callObject(\n className: string,\n objectId: string,\n method: string,\n args?: Record<string, unknown>,\n ): Promise<unknown> {\n const resp = await this.request(\n \"POST\",\n `/objects/${encodeURIComponent(className)}/${encodeURIComponent(objectId)}/call/${encodeURIComponent(method)}`,\n args ?? {},\n );\n return resp;\n }\n\n /** Delete a durable object by identifier. */\n async deleteObject(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/objects/${encodeURIComponent(id)}`);\n }\n\n /** Partially update a durable object (storage and/or status). */\n async patchObject(\n id: string,\n payload: { storage?: unknown; status?: string },\n ): Promise<DurableObject> {\n return this.request<DurableObject>(\n \"PATCH\",\n `/objects/${encodeURIComponent(id)}`,\n payload,\n );\n }\n\n /** List all schedules. */\n async listSchedules(): Promise<Schedule[]> {\n return this.request<Schedule[]>(\"GET\", \"/schedules\");\n }\n\n /** Create a new schedule. */\n async createSchedule(payload: CreateScheduleRequest): Promise<Schedule> {\n return this.request<Schedule>(\"POST\", \"/schedules\", payload);\n }\n\n /** Get a schedule by identifier. */\n async getSchedule(id: string): Promise<Schedule> {\n return this.request<Schedule>(\n \"GET\",\n `/schedules/${encodeURIComponent(id)}`,\n );\n }\n\n /** Delete a schedule by identifier. */\n async deleteSchedule(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/schedules/${encodeURIComponent(id)}`);\n }\n\n /** List all durable stores. */\n async listStores(): Promise<DurableStore[]> {\n return this.request<DurableStore[]>(\"GET\", \"/stores\");\n }\n\n /** Create a durable store. */\n async createStore(payload: CreateStoreRequest): Promise<DurableStore> {\n return this.request<DurableStore>(\"POST\", \"/stores\", payload);\n }\n\n /** Get a durable store by identifier. */\n async getStore(id: string): Promise<DurableStore> {\n return this.request<DurableStore>(\"GET\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Delete a durable store by identifier. */\n async deleteStore(id: string): Promise<string> {\n return this.request<string>(\"DELETE\", `/stores/${encodeURIComponent(id)}`);\n }\n\n /** Execute a read query against a durable store. */\n async queryStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreQueryResponse> {\n return this.request<DurableStoreQueryResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/query`,\n payload,\n );\n }\n\n /** Execute a write statement against a durable store. */\n async executeStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreExecuteResponse> {\n return this.request<DurableStoreExecuteResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/execute`,\n payload,\n );\n }\n\n /** Execute a command against a durable store (Redis-style engines). */\n async commandStore(\n id: string,\n payload: Record<string, unknown>,\n ): Promise<DurableStoreCommandResponse> {\n return this.request<DurableStoreCommandResponse>(\n \"POST\",\n `/stores/${encodeURIComponent(id)}/command`,\n payload,\n );\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd, o) => this.execInSandbox(n, cmd, o),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n (n, f) => this.writeFiles(n, f),\n );\n }\n\n /**\n * Create a sandboxed browser session with automatic cleanup.\n *\n * Creates a sandbox with Chromium pre-installed via Playwright.\n * Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async browser(\n name: string,\n opts?: { memory_mb?: number },\n ): Promise<BrowserSession> {\n await this.createSandbox(name, {\n image: \"python:3.12-slim\",\n memory_mb: opts?.memory_mb ?? 2048,\n profile: \"moderate\",\n });\n await this.execInSandbox(name, BROWSER_SETUP_CMD);\n return new BrowserSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n );\n }\n\n // -- TTL & Snapshot methods --\n\n /** Extend a sandbox's TTL. Returns the new expiry time. */\n async extendTtl(name: string, opts: ExtendTtlOptions): Promise<ExtendTtlResponse> {\n return this.request<ExtendTtlResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/extend`,\n { by: opts.by },\n );\n }\n\n /** List all snapshots. */\n async listSnapshots(): Promise<SnapshotMeta[]> {\n return this.request<SnapshotMeta[]>(\"GET\", \"/snapshots\");\n }\n\n /** Take a snapshot of a sandbox. */\n async takeSnapshot(opts: TakeSnapshotOptions): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\"POST\", \"/snapshots\", opts);\n }\n\n /** Get info about a snapshot. */\n async getSnapshot(name: string): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\n \"GET\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete a snapshot. */\n async deleteSnapshot(name: string): Promise<void> {\n await this.request<string>(\n \"DELETE\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Restore a sandbox from a snapshot. */\n async restoreSnapshot(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"POST\",\n `/snapshots/${encodeURIComponent(name)}/restore`,\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":["value","line"]}
package/dist/types.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Security profile for sandbox execution. */
2
2
  export type SecurityProfile = "permissive" | "moderate" | "restrictive";
3
3
  /** Sandbox status. */
4
- export type SandboxStatus = "running" | "stopped";
4
+ export type SandboxStatus = "running" | "paused" | "stopped" | "dormant" | "archived";
5
5
  /** SSE event types emitted by /run/stream. */
6
6
  export type StreamEventType = "started" | "progress" | "output" | "done" | "error";
7
7
  /** Configuration options for the AgentKernel client. */
@@ -24,6 +24,8 @@ export interface RunOptions {
24
24
  }
25
25
  /** Options for creating a sandbox. */
26
26
  export interface CreateSandboxOptions {
27
+ /** Backend identifier; omit or use automatic for server selection. */
28
+ backend?: string;
27
29
  /** Docker image to use. Default: alpine:3.24 */
28
30
  image?: string;
29
31
  vcpus?: number;
@@ -71,6 +73,31 @@ export interface SandboxInfo {
71
73
  memory_mb?: number;
72
74
  created_at?: string;
73
75
  }
76
+ export interface BackendCapabilities {
77
+ mount_cwd: boolean;
78
+ mount_home: boolean;
79
+ attach: boolean;
80
+ host_volumes: boolean;
81
+ ssh: boolean;
82
+ proxy_secret_bindings: boolean;
83
+ secret_files: boolean;
84
+ snapshots: boolean;
85
+ resume: boolean;
86
+ full_state_pause_resume: boolean;
87
+ full_state_fork: boolean;
88
+ endpoints: boolean;
89
+ }
90
+ export interface BackendDescriptor {
91
+ backend: string;
92
+ configured: boolean;
93
+ usable: boolean;
94
+ readiness_reason: string;
95
+ capabilities: BackendCapabilities;
96
+ }
97
+ export interface BackendDiscovery {
98
+ default_backend?: string;
99
+ backends: BackendDescriptor[];
100
+ }
74
101
  /** SSE stream event. */
75
102
  export interface StreamEvent {
76
103
  type: StreamEventType;
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Security profile for sandbox execution. */
2
2
  export type SecurityProfile = "permissive" | "moderate" | "restrictive";
3
3
  /** Sandbox status. */
4
- export type SandboxStatus = "running" | "stopped";
4
+ export type SandboxStatus = "running" | "paused" | "stopped" | "dormant" | "archived";
5
5
  /** SSE event types emitted by /run/stream. */
6
6
  export type StreamEventType = "started" | "progress" | "output" | "done" | "error";
7
7
  /** Configuration options for the AgentKernel client. */
@@ -24,6 +24,8 @@ export interface RunOptions {
24
24
  }
25
25
  /** Options for creating a sandbox. */
26
26
  export interface CreateSandboxOptions {
27
+ /** Backend identifier; omit or use automatic for server selection. */
28
+ backend?: string;
27
29
  /** Docker image to use. Default: alpine:3.24 */
28
30
  image?: string;
29
31
  vcpus?: number;
@@ -71,6 +73,31 @@ export interface SandboxInfo {
71
73
  memory_mb?: number;
72
74
  created_at?: string;
73
75
  }
76
+ export interface BackendCapabilities {
77
+ mount_cwd: boolean;
78
+ mount_home: boolean;
79
+ attach: boolean;
80
+ host_volumes: boolean;
81
+ ssh: boolean;
82
+ proxy_secret_bindings: boolean;
83
+ secret_files: boolean;
84
+ snapshots: boolean;
85
+ resume: boolean;
86
+ full_state_pause_resume: boolean;
87
+ full_state_fork: boolean;
88
+ endpoints: boolean;
89
+ }
90
+ export interface BackendDescriptor {
91
+ backend: string;
92
+ configured: boolean;
93
+ usable: boolean;
94
+ readiness_reason: string;
95
+ capabilities: BackendCapabilities;
96
+ }
97
+ export interface BackendDiscovery {
98
+ default_backend?: string;
99
+ backends: BackendDescriptor[];
100
+ }
74
101
  /** SSE stream event. */
75
102
  export interface StreamEvent {
76
103
  type: StreamEventType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentkernel",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Node.js SDK for agentkernel — run AI coding agents in secure, isolated microVMs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",