agentkernel 0.11.3 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -538,7 +538,9 @@ var AgentKernel = class {
|
|
|
538
538
|
profile: opts?.profile,
|
|
539
539
|
source_url: opts?.source_url,
|
|
540
540
|
source_ref: opts?.source_ref,
|
|
541
|
-
volumes: opts?.volumes
|
|
541
|
+
volumes: opts?.volumes,
|
|
542
|
+
secrets: opts?.secrets,
|
|
543
|
+
secret_files: opts?.secret_files
|
|
542
544
|
});
|
|
543
545
|
}
|
|
544
546
|
/** Get info about a sandbox. */
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.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 DetachedCommand,\n DetachedLogsResponse,\n DetachedStatus,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n PageLink,\n PageResult,\n RunOptions,\n RunOutput,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\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","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 CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\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 });\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 /** 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 /**\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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.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 DetachedCommand,\n DetachedLogsResponse,\n DetachedStatus,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n PageLink,\n PageResult,\n RunOptions,\n RunOutput,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\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","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 CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\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 /** 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 /**\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":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -35,6 +35,17 @@ interface CreateSandboxOptions {
|
|
|
35
35
|
source_ref?: string;
|
|
36
36
|
/** Volume mounts (slug:/path or slug:/path:ro). Create volumes via CLI first. */
|
|
37
37
|
volumes?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Secret bindings for proxy-based injection (Gondolin pattern).
|
|
40
|
+
* Secrets are injected as HTTP headers by the host proxy — they never enter the VM.
|
|
41
|
+
* Formats: "KEY=value:host", "KEY:host", "KEY:host:header"
|
|
42
|
+
*/
|
|
43
|
+
secrets?: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Secret keys to inject as files at /run/agentkernel/secrets/KEY.
|
|
46
|
+
* Values are resolved from the secret vault.
|
|
47
|
+
*/
|
|
48
|
+
secret_files?: string[];
|
|
38
49
|
}
|
|
39
50
|
/** Options for executing a command in a sandbox. */
|
|
40
51
|
interface ExecOptions {
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,17 @@ interface CreateSandboxOptions {
|
|
|
35
35
|
source_ref?: string;
|
|
36
36
|
/** Volume mounts (slug:/path or slug:/path:ro). Create volumes via CLI first. */
|
|
37
37
|
volumes?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Secret bindings for proxy-based injection (Gondolin pattern).
|
|
40
|
+
* Secrets are injected as HTTP headers by the host proxy — they never enter the VM.
|
|
41
|
+
* Formats: "KEY=value:host", "KEY:host", "KEY:host:header"
|
|
42
|
+
*/
|
|
43
|
+
secrets?: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Secret keys to inject as files at /run/agentkernel/secrets/KEY.
|
|
46
|
+
* Values are resolved from the secret vault.
|
|
47
|
+
*/
|
|
48
|
+
secret_files?: string[];
|
|
38
49
|
}
|
|
39
50
|
/** Options for executing a command in a sandbox. */
|
|
40
51
|
interface ExecOptions {
|
package/dist/index.js
CHANGED
|
@@ -502,7 +502,9 @@ var AgentKernel = class {
|
|
|
502
502
|
profile: opts?.profile,
|
|
503
503
|
source_url: opts?.source_url,
|
|
504
504
|
source_ref: opts?.source_ref,
|
|
505
|
-
volumes: opts?.volumes
|
|
505
|
+
volumes: opts?.volumes,
|
|
506
|
+
secrets: opts?.secrets,
|
|
507
|
+
secret_files: opts?.secret_files
|
|
506
508
|
});
|
|
507
509
|
}
|
|
508
510
|
/** Get info about a sandbox. */
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.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","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 CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\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 });\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 /** 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 /**\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":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.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","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 CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\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 /** 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 /**\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":[]}
|