@prompteryx/sdk 0.4.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/resources/autopilot.ts","../src/resources/cloudBrowser.ts","../src/resources/executions.ts","../src/resources/profiles.ts","../src/resources/schedules.ts","../src/resources/subscription.ts","../src/resources/workflows.ts","../src/page.ts","../src/models.ts"],"sourcesContent":["/**\n * @prompteryx/sdk\n *\n * Official TypeScript SDK for the Prompteryx platform.\n *\n * Two AI surfaces:\n *\n * • **Copilot** — helps with ONE step you describe in plain English.\n * Your code drives Playwright; copilot just figures out the\n * selector to click / the data to pull / what's on the page.\n *\n * ```ts\n * await px.copilot.do(page, 'click the Sign up button')\n * const product = await px.copilot.read(page, productSchema)\n * const actions = await px.copilot.scan(page, 'checkout buttons')\n * ```\n *\n * • **Autopilot** — runs an autonomous multi-step task end-to-end\n * with no per-action involvement from you.\n *\n * ```ts\n * const result = await px.autopilot.run({\n * goal: 'Apply for the Senior Engineer role at OpenAI',\n * saveAsWorkflow: true, // permanent zero-AI-cost replay\n * })\n * ```\n *\n * Plus workflows, executions, cloud browser sessions / fetch / search,\n * schedules, profiles, and subscription telemetry.\n *\n * TWO KEY FAMILIES:\n * • `apiKey` (`px_live_…`) — the platform API key; sent as\n * `Authorization: Bearer`. 60 requests/minute, 10,000/day.\n * • `cloudBrowserKey` (`pcb_live_…`) — the Cloud Browser key; required\n * only for `px.cloudBrowser.*`, sent as `x-api-key`.\n *\n * Quick start:\n *\n * ```ts\n * import { Prompteryx } from '@prompteryx/sdk'\n * import { chromium } from 'playwright-core'\n *\n * const px = new Prompteryx({\n * apiKey: process.env.PROMPTERYX_API_KEY!, // px_live_…\n * cloudBrowserKey: process.env.PROMPTERYX_CLOUD_BROWSER_KEY, // pcb_live_…\n * })\n *\n * // 1. Cloud browser session\n * const session = await px.cloudBrowser.sessions.create({\n * useProxy: true, proxyLocation: 'us',\n * })\n * const browser = await chromium.connectOverCDP(session.connectUrl)\n * const page = browser.contexts()[0].pages()[0]\n *\n * // 2. Copilot on top of Playwright\n * await page.goto('https://news.ycombinator.com')\n * const top = await px.copilot.read(page, z.object({\n * stories: z.array(z.object({ title: z.string(), url: z.string() })),\n * }))\n * ```\n *\n * See PROMPTERYX_SDK.md in docs/ for the full design + reference.\n */\n\nimport { HttpClient } from './client'\nimport { AutopilotResource } from './resources/autopilot'\nimport { CloudBrowserResource } from './resources/cloudBrowser'\nimport { ExecutionsResource } from './resources/executions'\nimport { ProfilesResource } from './resources/profiles'\nimport { SchedulesResource } from './resources/schedules'\nimport { SubscriptionResource } from './resources/subscription'\nimport { WorkflowsResource } from './resources/workflows'\nimport { CopilotHelpers, type PageLike } from './page'\nimport type {\n CopilotDoResult,\n DiscoveredAction,\n PrompteryxClientOptions,\n} from './types'\n\n// Public re-exports\nexport * from './errors'\nexport * from './types'\nexport * from './models'\nexport type { PageLike }\n\n// v0.4.0 (2026-09-03): the connectHub, customNodes, templates, apiKeys and\n// recordings namespaces plus subscription.usage() were REMOVED from the\n// public surface — the routes they target don't exist on the live API (or,\n// for api-keys, can never accept API-key auth). The source files remain in\n// src/resources/ with dated NOT-SHIPPED headers for a future release.\n\n/**\n * Copilot surface — bundles the three on-page primitives behind a\n * single namespace so calling code reads as\n * `px.copilot.do(...)` / `px.copilot.read(...)` / `px.copilot.scan(...)`.\n * Used internally by the Prompteryx class.\n */\nclass Copilot {\n constructor(private readonly helpers: CopilotHelpers) {}\n /** Execute a natural-language action on a connected Playwright page. */\n do(page: PageLike, instruction: string, opts?: { timeout?: number }): Promise<CopilotDoResult> {\n return this.helpers.do(page, instruction, opts)\n }\n /** Pull typed data from the page (Zod schema or raw JSON Schema). */\n read<T>(page: PageLike, schema: { parse(input: unknown): T } | { jsonSchema: unknown }): Promise<T> {\n return this.helpers.read<T>(page, schema as any)\n }\n /** Discover available actions on the page; useful pre-`do` step. */\n scan(page: PageLike, hint?: string): Promise<DiscoveredAction[]> {\n return this.helpers.scan(page, hint)\n }\n}\n\nexport class Prompteryx {\n private readonly http: HttpClient\n\n // Core resources — the verified live surface.\n public readonly workflows: WorkflowsResource\n public readonly executions: ExecutionsResource\n public readonly cloudBrowser: CloudBrowserResource\n public readonly autopilot: AutopilotResource\n public readonly copilot: Copilot\n public readonly schedules: SchedulesResource\n public readonly profiles: ProfilesResource\n public readonly subscription: SubscriptionResource\n\n constructor(opts: PrompteryxClientOptions) {\n this.http = new HttpClient(opts)\n this.workflows = new WorkflowsResource(this.http)\n this.executions = new ExecutionsResource(this.http)\n this.cloudBrowser = new CloudBrowserResource(this.http)\n this.autopilot = new AutopilotResource(this.http)\n this.copilot = new Copilot(new CopilotHelpers(this.http))\n this.schedules = new SchedulesResource(this.http)\n this.profiles = new ProfilesResource(this.http)\n this.subscription = new SubscriptionResource(this.http)\n }\n}\n\nexport default Prompteryx\n","/**\r\n * Typed error hierarchy for the Prompteryx SDK.\r\n *\r\n * Every error from the SDK is an instance of `PrompteryxError`. Subclass\r\n * by HTTP status family so callers can `if (err instanceof QuotaError)`\r\n * without parsing strings. Network/parse errors get their own classes\r\n * too so retries can fork on category.\r\n */\r\n\r\n/** Base class — every SDK error inherits from this. */\r\nexport class PrompteryxError extends Error {\r\n public readonly status?: number\r\n public readonly code?: string\r\n public readonly requestId?: string\r\n public readonly raw?: unknown\r\n\r\n constructor(message: string, opts: { status?: number; code?: string; requestId?: string; raw?: unknown } = {}) {\r\n super(message)\r\n this.name = 'PrompteryxError'\r\n this.status = opts.status\r\n this.code = opts.code\r\n this.requestId = opts.requestId\r\n this.raw = opts.raw\r\n // Restore prototype chain for `instanceof` checks across realms.\r\n Object.setPrototypeOf(this, new.target.prototype)\r\n }\r\n}\r\n\r\n/** 401 / 403 — bad or revoked API key, or insufficient scope. */\r\nexport class AuthError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'AuthError'\r\n Object.setPrototypeOf(this, AuthError.prototype)\r\n }\r\n}\r\n\r\n/** 402 — plan allowance exhausted (AI Credits, cloud minutes, etc.). */\r\nexport class QuotaError extends PrompteryxError {\r\n /** Which resources are exhausted, when known. */\r\n public readonly resources?: string[]\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] & { resources?: string[] } = {}) {\r\n super(message, opts)\r\n this.name = 'QuotaError'\r\n this.resources = opts.resources\r\n Object.setPrototypeOf(this, QuotaError.prototype)\r\n }\r\n}\r\n\r\n/** 404 — resource doesn't exist (workflow id, execution id, session id). */\r\nexport class NotFoundError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'NotFoundError'\r\n Object.setPrototypeOf(this, NotFoundError.prototype)\r\n }\r\n}\r\n\r\n/** 422 — request body shape was wrong. */\r\nexport class ValidationError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'ValidationError'\r\n Object.setPrototypeOf(this, ValidationError.prototype)\r\n }\r\n}\r\n\r\n/** 429 — rate-limited. Caller can retry after `retryAfterSeconds`. */\r\nexport class RateLimitError extends PrompteryxError {\r\n public readonly retryAfterSeconds?: number\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] & { retryAfterSeconds?: number } = {}) {\r\n super(message, opts)\r\n this.name = 'RateLimitError'\r\n this.retryAfterSeconds = opts.retryAfterSeconds\r\n Object.setPrototypeOf(this, RateLimitError.prototype)\r\n }\r\n}\r\n\r\n/** 5xx — server-side failure. SDK retries these by default for idempotent ops. */\r\nexport class ServerError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'ServerError'\r\n Object.setPrototypeOf(this, ServerError.prototype)\r\n }\r\n}\r\n\r\n/** Network / DNS / socket / aborted — never reached the server. */\r\nexport class NetworkError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'NetworkError'\r\n Object.setPrototypeOf(this, NetworkError.prototype)\r\n }\r\n}\r\n\r\n/** Response body parse failure (server returned a non-JSON 500 page, etc.). */\r\nexport class ParseError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'ParseError'\r\n Object.setPrototypeOf(this, ParseError.prototype)\r\n }\r\n}\r\n\r\n/** Timed-out waiting for a long-running op (execution polling, agent run). */\r\nexport class TimeoutError extends PrompteryxError {\r\n constructor(message: string, opts: ConstructorParameters<typeof PrompteryxError>[1] = {}) {\r\n super(message, opts)\r\n this.name = 'TimeoutError'\r\n Object.setPrototypeOf(this, TimeoutError.prototype)\r\n }\r\n}\r\n","/**\r\n * HTTP client for the Prompteryx SDK.\r\n *\r\n * Thin layer over `fetch` that adds:\r\n * - Bearer auth from the configured API key\r\n * - JSON serialisation + content-type\r\n * - Status-to-typed-error mapping (see errors.ts)\r\n * - Configurable timeout via AbortController\r\n * - Bounded retry for idempotent ops on 5xx / network errors\r\n * - Optional SSE streaming for execution logs / agent traces\r\n *\r\n * Anything that needs raw `Response` (e.g. downloading a recording\r\n * binary) can use `rawRequest()`. Everything else should use\r\n * `request<T>()` which returns the parsed JSON body typed as T.\r\n */\r\n\r\nimport {\r\n AuthError,\r\n NetworkError,\r\n NotFoundError,\r\n ParseError,\r\n PrompteryxError,\r\n QuotaError,\r\n RateLimitError,\r\n ServerError,\r\n TimeoutError,\r\n ValidationError,\r\n} from './errors'\r\nimport type { PrompteryxClientOptions } from './types'\r\n\r\nconst DEFAULT_BASE_URL = 'https://prompteryx.com'\r\nconst DEFAULT_TIMEOUT_MS = 60_000\r\nconst DEFAULT_MAX_RETRIES = 2\r\n\r\nexport interface RequestOptions {\r\n method?: 'GET' | 'POST' | 'PATCH' | 'DELETE'\r\n /** Object that will be JSON.stringified into the body. Skip for GET/DELETE. */\r\n body?: unknown\r\n /** Extra headers merged into the defaults. */\r\n headers?: Record<string, string>\r\n /** Override the client default timeout for this single call. */\r\n timeoutMs?: number\r\n /** Whether this op is safe to retry on transient failure. Defaults\r\n * based on method: GET = yes, others = no. The caller can force\r\n * retry for idempotent POSTs (e.g. a poll loop). */\r\n retry?: boolean\r\n /** Query string params (URI-encoded automatically). */\r\n query?: Record<string, string | number | boolean | undefined | null>\r\n /** Optional AbortSignal for caller-side cancellation. */\r\n signal?: AbortSignal\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string\r\n /** Optional Cloud Browser key (`pcb_live_…`) — a separate key family used\r\n * only by the /api/v1/cloud-browser/* endpoints (sent as `x-api-key`). */\r\n public readonly cloudBrowserKey?: string\r\n private readonly baseUrl: string\r\n private readonly timeoutMs: number\r\n private readonly maxRetries: number\r\n private readonly defaultHeaders: Record<string, string>\r\n private readonly fetchImpl: typeof fetch\r\n\r\n constructor(opts: PrompteryxClientOptions) {\r\n if (!opts.apiKey) {\r\n throw new PrompteryxError('apiKey is required to construct a Prompteryx client')\r\n }\r\n this.apiKey = opts.apiKey\r\n this.cloudBrowserKey = opts.cloudBrowserKey\r\n this.baseUrl = (opts.baseUrl || DEFAULT_BASE_URL).replace(/\\/+$/, '')\r\n this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS\r\n this.maxRetries = opts.maxRetries ?? DEFAULT_MAX_RETRIES\r\n this.defaultHeaders = opts.defaultHeaders ?? {}\r\n const f = opts.fetch ?? globalThis.fetch\r\n if (!f) {\r\n throw new PrompteryxError(\r\n 'No fetch implementation found. Provide options.fetch or run on a runtime with global fetch (Node 18+, browser, Cloudflare Workers).',\r\n )\r\n }\r\n // Bind so `this` doesn't get lost on assignment.\r\n this.fetchImpl = f.bind(globalThis)\r\n }\r\n\r\n /** Returns the JSON-parsed body typed as T. Throws typed errors on non-2xx. */\r\n async request<T = unknown>(path: string, opts: RequestOptions = {}): Promise<T> {\r\n const res = await this.rawRequest(path, opts)\r\n const text = await res.text()\r\n if (!text) return undefined as T\r\n try {\r\n return JSON.parse(text) as T\r\n } catch {\r\n throw new ParseError(`Failed to parse JSON response from ${path}`, {\r\n status: res.status,\r\n raw: text.slice(0, 500),\r\n })\r\n }\r\n }\r\n\r\n /** Returns the raw Response. Throws typed errors on non-2xx, but does\r\n * not attempt to read the body. Useful for downloading binaries. */\r\n async rawRequest(path: string, opts: RequestOptions = {}): Promise<Response> {\r\n const method = opts.method ?? 'GET'\r\n const url = this.buildUrl(path, opts.query)\r\n const shouldRetry = opts.retry ?? (method === 'GET')\r\n const maxAttempts = shouldRetry ? this.maxRetries + 1 : 1\r\n let lastErr: unknown\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n try {\r\n const res = await this.sendOnce(url, method, opts)\r\n if (res.ok) return res\r\n // Map status → typed error. For 5xx / 429 with retries remaining,\r\n // throw a retryable subclass and try again.\r\n const err = await this.errorFromResponse(res)\r\n if (this.isRetryable(err) && attempt < maxAttempts - 1) {\r\n await this.backoff(attempt, err)\r\n lastErr = err\r\n continue\r\n }\r\n throw err\r\n } catch (e) {\r\n // Network / abort errors: treat as retryable when we have budget.\r\n if (e instanceof PrompteryxError) throw e\r\n const wrapped = this.wrapTransport(e)\r\n if (this.isRetryable(wrapped) && attempt < maxAttempts - 1) {\r\n await this.backoff(attempt, wrapped)\r\n lastErr = wrapped\r\n continue\r\n }\r\n throw wrapped\r\n }\r\n }\r\n // Shouldn't reach here, but TS likes a return.\r\n throw lastErr ?? new PrompteryxError('Unknown error after retries exhausted')\r\n }\r\n\r\n /**\r\n * Stream a Server-Sent Events response line-by-line as JSON-parsed\r\n * payloads. Yields each event's `data:` payload parsed as JSON. The\r\n * caller is responsible for breaking the loop / cancelling the\r\n * AbortSignal when done.\r\n */\r\n async *streamSse<T = unknown>(path: string, opts: RequestOptions = {}): AsyncGenerator<T, void, void> {\r\n const res = await this.rawRequest(path, {\r\n ...opts,\r\n headers: { ...opts.headers, Accept: 'text/event-stream' },\r\n })\r\n if (!res.body) return\r\n const reader = res.body.getReader()\r\n const decoder = new TextDecoder()\r\n let buf = ''\r\n while (true) {\r\n const { value, done } = await reader.read()\r\n if (done) break\r\n buf += decoder.decode(value, { stream: true })\r\n // SSE events separated by blank line. Each event has one or more\r\n // `data: ` lines we concatenate.\r\n let idx\r\n while ((idx = buf.indexOf('\\n\\n')) !== -1) {\r\n const raw = buf.slice(0, idx)\r\n buf = buf.slice(idx + 2)\r\n const dataLines = raw\r\n .split('\\n')\r\n .filter((l) => l.startsWith('data:'))\r\n .map((l) => l.slice(5).trim())\r\n if (dataLines.length === 0) continue\r\n const payload = dataLines.join('\\n')\r\n if (!payload) continue\r\n try {\r\n yield JSON.parse(payload) as T\r\n } catch {\r\n // Skip malformed events rather than dropping the whole stream.\r\n // Real-world SSE has occasional keepalive comments + heartbeat\r\n // lines we don't want to crash on.\r\n }\r\n }\r\n }\r\n }\r\n\r\n // ── internals ────────────────────────────────────────────────────────\r\n\r\n private async sendOnce(url: string, method: string, opts: RequestOptions): Promise<Response> {\r\n const timeoutMs = opts.timeoutMs ?? this.timeoutMs\r\n const ctl = new AbortController()\r\n const t = setTimeout(() => ctl.abort(), timeoutMs)\r\n // Combine caller signal with our timeout signal.\r\n if (opts.signal) {\r\n if (opts.signal.aborted) ctl.abort()\r\n else opts.signal.addEventListener('abort', () => ctl.abort(), { once: true })\r\n }\r\n try {\r\n const headers: Record<string, string> = {\r\n Authorization: `Bearer ${this.apiKey}`,\r\n Accept: 'application/json',\r\n ...this.defaultHeaders,\r\n ...(opts.headers ?? {}),\r\n }\r\n let body: BodyInit | undefined\r\n if (opts.body !== undefined) {\r\n headers['Content-Type'] = 'application/json'\r\n body = JSON.stringify(opts.body)\r\n }\r\n return await this.fetchImpl(url, {\r\n method,\r\n headers,\r\n body,\r\n signal: ctl.signal,\r\n })\r\n } finally {\r\n clearTimeout(t)\r\n }\r\n }\r\n\r\n private buildUrl(path: string, query?: RequestOptions['query']): string {\r\n const base = path.startsWith('http') ? path : `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`\r\n if (!query) return base\r\n const params = new URLSearchParams()\r\n for (const [k, v] of Object.entries(query)) {\r\n if (v === undefined || v === null) continue\r\n params.set(k, String(v))\r\n }\r\n const qs = params.toString()\r\n return qs ? `${base}${base.includes('?') ? '&' : '?'}${qs}` : base\r\n }\r\n\r\n private async errorFromResponse(res: Response): Promise<PrompteryxError> {\r\n let parsed: any = null\r\n try {\r\n const text = await res.text()\r\n parsed = text ? JSON.parse(text) : null\r\n } catch { /* ignore — body wasn't JSON */ }\r\n const message = parsed?.error?.message\r\n ?? parsed?.message\r\n ?? parsed?.error\r\n ?? `Request failed with ${res.status}`\r\n const code = parsed?.error?.code ?? parsed?.code\r\n const requestId = res.headers.get('x-request-id') ?? undefined\r\n const opts = { status: res.status, code, requestId, raw: parsed }\r\n switch (res.status) {\r\n case 401:\r\n case 403:\r\n return new AuthError(message, opts)\r\n case 402:\r\n return new QuotaError(message, { ...opts, resources: parsed?.error?.resources ?? parsed?.resources })\r\n case 404:\r\n return new NotFoundError(message, opts)\r\n case 422:\r\n return new ValidationError(message, opts)\r\n case 429: {\r\n const retryAfter = parseInt(res.headers.get('retry-after') ?? '0', 10)\r\n return new RateLimitError(message, { ...opts, retryAfterSeconds: Number.isFinite(retryAfter) ? retryAfter : undefined })\r\n }\r\n default:\r\n if (res.status >= 500) return new ServerError(message, opts)\r\n return new PrompteryxError(message, opts)\r\n }\r\n }\r\n\r\n private wrapTransport(e: unknown): PrompteryxError {\r\n const msg = e instanceof Error ? e.message : String(e)\r\n if (e instanceof Error && (e.name === 'AbortError' || msg.includes('aborted'))) {\r\n return new TimeoutError(`Request timed out: ${msg}`)\r\n }\r\n return new NetworkError(`Network error: ${msg}`)\r\n }\r\n\r\n private isRetryable(err: PrompteryxError): boolean {\r\n if (err instanceof ServerError) return true\r\n if (err instanceof RateLimitError) return true\r\n if (err instanceof NetworkError) return true\r\n if (err instanceof TimeoutError) return true\r\n return false\r\n }\r\n\r\n private async backoff(attempt: number, err: PrompteryxError): Promise<void> {\r\n // Honour `Retry-After` when the server provided one.\r\n const retryAfter = (err as RateLimitError).retryAfterSeconds\r\n if (retryAfter && retryAfter > 0) {\r\n return new Promise((r) => setTimeout(r, Math.min(retryAfter, 30) * 1000))\r\n }\r\n // Otherwise exponential backoff with jitter: 250ms, 500ms, 1s, 2s, ...\r\n const base = 250 * Math.pow(2, attempt)\r\n const jitter = Math.random() * 100\r\n return new Promise((r) => setTimeout(r, base + jitter))\r\n }\r\n}\r\n","/**\r\n * `px.autopilot.*` — autonomous browser agent.\r\n *\r\n * **Autopilot** is the autonomous, multi-step surface. You hand it\r\n * a goal in plain English; it drives the browser end-to-end and\r\n * returns a step-by-step trace. Counterpart to **Copilot** which\r\n * helps with one step at a time (see ../page.ts).\r\n *\r\n * Built on the existing AI Browser Agent runtime. Every option the\r\n * in-app UI exposes — model, max steps, system-prompt override,\r\n * tool restrictions, viewport, region, proxy, CAPTCHA, recording —\r\n * is available via the SDK. New options added to the runtime ride\r\n * through `passthrough` without an SDK release.\r\n *\r\n * **Action caching superpower** — set `saveAsWorkflow: true` and the\r\n * autopilot's discovered action sequence is captured as a permanent\r\n * Visual Studio workflow you can replay for free forever. The\r\n * response includes `savedWorkflowId`. Subsequent calls to\r\n * `px.workflows.run(savedWorkflowId)` cost no AI Credits and benefit\r\n * from multi-option-selector resilience to UI changes.\r\n */\r\n\r\nimport { ParseError, PrompteryxError } from '../errors'\r\nimport type { HttpClient } from '../client'\r\nimport type {\r\n AutopilotRunOptions,\r\n AutopilotRunResult,\r\n AutopilotStep,\r\n} from '../types'\r\n\r\nexport class AutopilotResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Run the autopilot. Blocks until the task finishes (success, step\r\n * limit, or error). Returns the trace plus optionally the saved\r\n * workflow id.\r\n *\r\n * ```ts\r\n * const result = await px.autopilot.run({\r\n * goal: 'Apply for the Senior Engineer role at OpenAI',\r\n * startUrl: 'https://openai.com/careers',\r\n * maxSteps: 40,\r\n * saveAsWorkflow: true, // Replay-forever, zero AI cost\r\n * session: { useProxy: true, useCaptcha: true },\r\n * })\r\n * if (result.savedWorkflowId) {\r\n * console.log('Saved as workflow:', result.savedWorkflowId)\r\n * // Run it later for free:\r\n * await px.workflows.run(result.savedWorkflowId)\r\n * }\r\n * ```\r\n */\r\n async run(opts: AutopilotRunOptions): Promise<AutopilotRunResult> {\r\n if (opts.target === 'local') {\r\n // Local Chrome autopilot (v0.3+): drive the user's OWN Chrome via the\r\n // Prompteryx desktop app on THIS machine. Zero cloud-browser minutes.\r\n // The SDK talks directly to the local runner (localhost:61337) — the\r\n // cloud API can't reach the user's machine — so requirements are: the\r\n // desktop app RUNNING + SIGNED IN, and your code on the same machine.\r\n return this.runLocal(opts)\r\n }\r\n // Multi-agent swarm runs server-side and returns a MERGED result in one\r\n // response — keep it on the single-request path (unchanged).\r\n if (opts.agents && opts.agents > 1) {\r\n return this.runSwarm(opts)\r\n }\r\n // Single cloud agent: ASYNC start → run(poll) so a LONG task (e.g. filling a\r\n // form once per CSV row) never runs in one synchronous request — which would\r\n // exceed the infra GATEWAY timeout and hand the caller an HTML error page that\r\n // res.json() chokes on. Each request stays short; we loop until the job is done.\r\n return this.runAsync(opts)\r\n }\r\n\r\n /** The task params shared by the sync, swarm, and async request bodies. */\r\n private cloudTaskBody(opts: AutopilotRunOptions): Record<string, unknown> {\r\n return {\r\n instruction: opts.goal,\r\n startUrl: opts.startUrl,\r\n maxSteps: opts.maxSteps,\r\n maxCredits: opts.maxCredits,\r\n model: opts.model,\r\n aiVision: opts.aiVision,\r\n finalStepVision: opts.finalStepVision,\r\n outputSchema: opts.outputSchema,\r\n costSaving: opts.costSaving,\r\n costSavingMaxBatch: opts.costSavingMaxBatch,\r\n carefulBatching: opts.carefulBatching,\r\n saveAsWorkflow: opts.saveAsWorkflow,\r\n savedWorkflowName: opts.savedWorkflowName,\r\n sessionId: opts.sessionId,\r\n systemPromptOverride: opts.systemPromptOverride,\r\n allowedTools: opts.allowedTools,\r\n viewport: opts.viewport,\r\n session: opts.session,\r\n // Settings parity (2026-07-15) — mirror the AI Browser Agent settings dialog.\r\n safetyConsent: opts.safetyConsent,\r\n confirmUnclear: opts.confirmUnclear,\r\n enableContextCompression: opts.enableContextCompression,\r\n compressionThreshold: opts.compressionThreshold,\r\n enableSessionReset: opts.enableSessionReset,\r\n sessionResetThreshold: opts.sessionResetThreshold,\r\n ...opts.passthrough,\r\n }\r\n }\r\n\r\n /** Multi-agent swarm — one synchronous request; the server merges all lanes. */\r\n private async runSwarm(opts: AutopilotRunOptions): Promise<AutopilotRunResult> {\r\n const env = await this.http.request<{ data?: unknown }>('/api/v1/ai-browser/execute', {\r\n method: 'POST',\r\n timeoutMs: opts.timeoutMs ?? 10 * 60_000,\r\n body: {\r\n ...this.cloudTaskBody(opts),\r\n agents: opts.agents,\r\n collaborate: opts.collaborate,\r\n attachmentContext: opts.attachmentContext,\r\n maxRunCredits: opts.maxRunCredits,\r\n },\r\n })\r\n return this.mapResult(env?.data ?? env)\r\n }\r\n\r\n /**\r\n * Async single-agent run: POST { mode:'start' } to set up the job (returns a\r\n * jobId immediately), then POST { mode:'run' } in a loop — each advances the job\r\n * for up to ~230s server-side and returns the current status — until the job is\r\n * terminal or `opts.timeoutMs` elapses. No single request is long, so the gateway\r\n * timeout is never hit. Same `AutopilotRunResult` shape as before.\r\n */\r\n private async runAsync(opts: AutopilotRunOptions): Promise<AutopilotRunResult> {\r\n const timeoutMs = opts.timeoutMs ?? 10 * 60_000\r\n const deadline = Date.now() + timeoutMs\r\n const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\r\n\r\n // 1) START — SETUP only. Short request; returns { jobId, sessionId }.\r\n const startEnv = await this.http.request<{ data?: any }>('/api/v1/ai-browser/execute', {\r\n method: 'POST',\r\n timeoutMs: 60_000,\r\n body: { ...this.cloudTaskBody(opts), mode: 'start' },\r\n })\r\n const jobId: string | undefined = startEnv?.data?.jobId\r\n if (!jobId) {\r\n // Back-compat: an OLDER server without async mode ran the whole task\r\n // synchronously for mode:'start', so the response IS a full result. Return it.\r\n return this.mapResult(startEnv?.data ?? startEnv)\r\n }\r\n\r\n // 2) RUN — advance in ≤230s chunks until terminal (or the SDK timeout). The\r\n // chunk itself is the wait; a transport blip on a chunk is safe to retry.\r\n let view: any = null\r\n while (Date.now() < deadline) {\r\n const runEnv = await this.http.request<{ data?: any }>('/api/v1/ai-browser/execute', {\r\n method: 'POST',\r\n timeoutMs: 250_000,\r\n retry: true,\r\n body: { jobId, mode: 'run', maxSteps: opts.maxSteps },\r\n })\r\n view = runEnv?.data ?? null\r\n if (!view || view.terminal || view.status !== 'running') break\r\n await sleep(500)\r\n }\r\n\r\n // 3) If we bailed on the SDK timeout while still running, one status read gives\r\n // the latest known state (and triggers server finalize if it's since ended).\r\n if (view && view.status === 'running') {\r\n try {\r\n const statusEnv = await this.http.request<{ data?: any }>('/api/v1/ai-browser/execute', {\r\n query: { jobId },\r\n timeoutMs: 30_000,\r\n })\r\n if (statusEnv?.data) view = statusEnv.data\r\n } catch { /* keep the last view */ }\r\n }\r\n\r\n return this.mapResult(view)\r\n }\r\n\r\n /** Map an execute-endpoint payload (sync result, swarm result, or async status\r\n * view — they share finalAnswer / steps / usage / savedWorkflowId / status) into\r\n * the public AutopilotRunResult shape. */\r\n private mapResult(data: any): AutopilotRunResult {\r\n const d = data || {}\r\n const status: string | undefined = d.status\r\n const success = status === 'completed' || status === 'max_steps_reached'\r\n const steps: AutopilotStep[] = Array.isArray(d.steps)\r\n ? d.steps.map((s: any, i: number) => ({\r\n step: i + 1,\r\n action: typeof s?.action === 'string' ? s.action : (s?.action?.name || 'action'),\r\n result: s?.details ?? s?.result,\r\n }))\r\n : []\r\n return {\r\n success,\r\n finalAnswer: d.finalAnswer,\r\n steps,\r\n savedWorkflowId: d.savedWorkflowId,\r\n usage: d.usage,\r\n swarm: d.swarm,\r\n }\r\n }\r\n\r\n /**\r\n * Local Chrome autopilot — talks DIRECTLY to the Prompteryx desktop app on\r\n * this machine (localhost:61337): opens your local Chrome, runs the agent\r\n * loop there, polls until done. Same options as `run` (model, aiVision\r\n * preset, maxSteps, maxCredits, costSaving). Credits still apply; cloud\r\n * minutes do not. The tab stays open after the run for follow-ups.\r\n */\r\n private async runLocal(opts: AutopilotRunOptions): Promise<AutopilotRunResult> {\r\n const fetchImpl: typeof fetch = (globalThis as any).fetch\r\n if (!fetchImpl) {\r\n throw new Error('[Prompteryx SDK] Local target needs a global fetch (Node 18+ / browser).')\r\n }\r\n const base = (opts.runnerUrl || 'http://localhost:61337').replace(/\\/$/, '')\r\n const sessionId = `sdk-local-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\r\n const goal = opts.startUrl\r\n ? `First, go to ${opts.startUrl}. Then: ${opts.goal}`\r\n : opts.goal\r\n\r\n const post = async (path: string, body: unknown) => {\r\n let r: Response\r\n try {\r\n r = await fetchImpl(`${base}${path}`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(body),\r\n })\r\n } catch (e) {\r\n throw new Error(\r\n `[Prompteryx SDK] Couldn't reach the desktop app at ${base}. ` +\r\n `Make sure the Prompteryx desktop app is running and signed in on this machine. (${(e as Error).message})`,\r\n )\r\n }\r\n if (!r.ok) {\r\n let msg = `${path} failed (${r.status})`\r\n try { const j = await r.json(); if ((j as any)?.error) msg = (j as any).error } catch { /* */ }\r\n throw new Error(`[Prompteryx SDK] ${msg}`)\r\n }\r\n return r.json().catch(() => ({}))\r\n }\r\n\r\n // 1) Open the local Chrome + create the agent session.\r\n await post('/launch-gemini-browser', {\r\n sessionId,\r\n profileId: (opts.session as any)?.profileId,\r\n enableRecording: false,\r\n })\r\n\r\n // 2) Start the agent loop with the same knobs as the cloud path.\r\n await post('/local-agent/start', {\r\n sessionId,\r\n task: goal,\r\n model: opts.model,\r\n aiVision: opts.aiVision, // preset slug — resolved app-side\r\n maxTurns: opts.maxSteps,\r\n maxCredits: opts.maxCredits,\r\n costSaving: (opts.passthrough as any)?.costSaving === true,\r\n costSavingMaxBatch: (opts.passthrough as any)?.costSavingMaxBatch,\r\n })\r\n\r\n // 3) Poll state until terminal (or the SDK timeout).\r\n const deadline = Date.now() + (opts.timeoutMs ?? 10 * 60_000)\r\n const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms))\r\n let state: any = null\r\n while (Date.now() < deadline) {\r\n await sleep(1200)\r\n const r = await fetchImpl(`${base}/local-agent/state/${encodeURIComponent(sessionId)}`).catch(() => null)\r\n if (!r || !r.ok) continue\r\n state = await r.json().catch(() => null)\r\n if (!state || state.found === false) continue\r\n if (state.status && state.status !== 'running') break\r\n }\r\n\r\n const status = state?.status\r\n return {\r\n success: status === 'done' || status === 'awaiting_input',\r\n finalAnswer: state?.answer,\r\n steps: (state?.steps || []).map((s: any, i: number) => ({\r\n step: i + 1,\r\n action: s?.name || s?.action?.name || 'action',\r\n result: s?.args || s?.action?.args,\r\n })),\r\n usage: {\r\n aiCredits: Math.max(0, Math.round((state?.costUSD || 0) / 0.01)),\r\n tokensIn: state?.inTokens || 0,\r\n tokensOut: state?.outTokens || 0,\r\n costUSD: state?.costUSD || 0,\r\n turns: state?.turns || 0,\r\n },\r\n }\r\n }\r\n\r\n /**\r\n * Ask a running async job to stop at its next step boundary\r\n * (`POST { jobId, mode: 'stop' }`). Use it to wind down a job you\r\n * started via the raw API (or a run you're abandoning) instead of\r\n * leaving it stepping against a dead browser session until the step\r\n * cap — an abandoned job burns a model call + timeout per step.\r\n *\r\n * ```ts\r\n * const { stopRequested, status } = await px.autopilot.stop(jobId)\r\n * ```\r\n */\r\n async stop(jobId: string): Promise<{ jobId: string; stopRequested: boolean; status?: string }> {\r\n const env = await this.http.request<{ data?: any }>('/api/v1/ai-browser/execute', {\r\n method: 'POST',\r\n timeoutMs: 30_000,\r\n body: { jobId, mode: 'stop' },\r\n })\r\n const d = env?.data ?? env ?? {}\r\n return { jobId: d.jobId ?? jobId, stopRequested: d.stopRequested === true, status: d.status }\r\n }\r\n\r\n /**\r\n * Run the autopilot over the keep-alive stream endpoint and yield the\r\n * step trace. Ends with a `{ step: -1, action: 'done' }` sentinel whose\r\n * `result` field carries the full `AutopilotRunResult`.\r\n *\r\n * ```ts\r\n * for await (const step of px.autopilot.stream({ goal: 'Buy a ticket' })) {\r\n * console.log('Step', step.step, '→', step.action)\r\n * if (step.action === 'done') break\r\n * }\r\n * ```\r\n *\r\n * PROTOCOL (matches /api/v1/ai-browser/execute-stream — it is NOT SSE):\r\n * the server emits a 1-space heartbeat every 15s while the run executes,\r\n * then the complete execute-route JSON as the final chunk, i.e. the body\r\n * is `<heartbeats>\\n<json>`. The heartbeats exist to defeat the ~300s\r\n * infra idle timeout on long synchronous runs; per-step live events are\r\n * not available on this route, so steps arrive together when the run\r\n * finishes. Prefer `run()` unless you specifically want the keep-alive\r\n * transport for a long single-request run.\r\n */\r\n async *stream(\r\n opts: AutopilotRunOptions & { signal?: AbortSignal },\r\n ): AsyncGenerator<AutopilotStep, void, void> {\r\n if (opts.target === 'local') {\r\n // Local streaming isn't wired — the local runner has no step emitter.\r\n // Use the blocking `run({ target: 'local' })` (its result includes\r\n // the full step list) for local Chrome today.\r\n throw new Error(\r\n '[Prompteryx SDK] Streaming is cloud-only. For local Chrome use ' +\r\n 'autopilot.run({ target: \"local\" }) — its result contains all steps.',\r\n )\r\n }\r\n const res = await this.http.rawRequest('/api/v1/ai-browser/execute-stream', {\r\n method: 'POST',\r\n timeoutMs: opts.timeoutMs ?? 15 * 60_000,\r\n body: this.cloudTaskBody(opts),\r\n signal: opts.signal,\r\n })\r\n // Accumulate the whole body: heartbeat spaces, then '\\n' + the JSON.\r\n let text = ''\r\n if (res.body) {\r\n const reader = res.body.getReader()\r\n const decoder = new TextDecoder()\r\n while (true) {\r\n const { value, done } = await reader.read()\r\n if (done) break\r\n if (value) text += decoder.decode(value, { stream: true })\r\n }\r\n text += decoder.decode()\r\n } else {\r\n text = await res.text()\r\n }\r\n // Strip the heartbeats — the JSON is always the last (and only) content.\r\n const payload = text.trim()\r\n let parsed: any\r\n try {\r\n parsed = JSON.parse(payload)\r\n } catch {\r\n throw new ParseError('execute-stream returned a non-JSON payload', {\r\n raw: payload.slice(0, 500),\r\n })\r\n }\r\n if (parsed && parsed.success === false) {\r\n const msg = parsed?.error?.message ?? parsed?.error ?? 'AI Browser Agent run failed'\r\n throw new PrompteryxError(String(msg), { code: parsed?.error?.code, raw: parsed })\r\n }\r\n const result = this.mapResult(parsed?.data ?? parsed)\r\n for (const step of result.steps) yield step\r\n yield { step: -1, action: 'done', result }\r\n }\r\n}\r\n","/**\n * `px.cloudBrowser.*` — sessions, one-shot fetch, search.\n *\n * The most-used path: `sessions.create()` returns a `connectUrl` you\n * pass to Playwright's `chromium.connectOverCDP(connectUrl)`. Your own\n * Playwright code drives the browser from there; we handle the\n * infrastructure (residential proxies, recording, persistence).\n *\n * ⚠️ KEY FAMILY (verified live 2026-09-03): every /api/v1/cloud-browser/*\n * route authenticates with a CLOUD BROWSER key (`pcb_live_…`) sent as\n * `x-api-key` — NOT the platform `px_live_…` Bearer key the rest of the\n * SDK uses. Pass it as `new Prompteryx({ apiKey, cloudBrowserKey })`;\n * calls throw a descriptive AuthError when it's missing.\n */\n\nimport type { HttpClient, RequestOptions } from '../client'\nimport { AuthError } from '../errors'\nimport type {\n CloudFetchOptions,\n CloudFetchResult,\n CloudSearchResult,\n CloudSession,\n CloudSessionSummary,\n CreateSessionOptions,\n} from '../types'\n\nconst MISSING_CB_KEY_MESSAGE =\n 'px.cloudBrowser.* uses a Cloud Browser API key (pcb_live_…), which is a ' +\n 'separate key family from the platform px_live_… key. Create one under ' +\n 'Cloud Platform → API Keys and pass it as ' +\n 'new Prompteryx({ apiKey, cloudBrowserKey }).'\n\n/** Sub-resource: cloud browser sessions. */\nexport class SessionsResource {\n constructor(private readonly http: HttpClient) {}\n\n /** Headers for the pcb_live_ key family (throws a clear error if absent). */\n private cbAuth(): Record<string, string> {\n const key = this.http.cloudBrowserKey\n if (!key) throw new AuthError(MISSING_CB_KEY_MESSAGE)\n return { 'x-api-key': key }\n }\n\n private cbRequest<T>(path: string, opts: RequestOptions = {}): Promise<T> {\n return this.http.request<T>(path, {\n ...opts,\n headers: { ...this.cbAuth(), ...(opts.headers ?? {}) },\n })\n }\n\n /** Create a new browser session.\n *\n * Cloud (default):\n * ```ts\n * const s = await px.cloudBrowser.sessions.create()\n * // s.connectUrl → Prompteryx Cloud CDP. Bills cloud-browser minutes.\n * ```\n *\n * Local — uses YOUR machine's Chrome via the Prompteryx plugin +\n * Electron runner. ZERO cloud-browser minutes. Requires the plugin\n * to be running on the same machine as the SDK consumer; the call\n * short-circuits to localhost and never reaches the API.\n * ```ts\n * const s = await px.cloudBrowser.sessions.create({ target: 'local' })\n * // s.connectUrl → http://localhost:9222 (your Chrome's debug port)\n * ```\n *\n * When `target: 'local'` is set, cloud-only fields (recordSession,\n * proxy, profileId) are ignored — you're driving your own Chrome\n * with whatever cookies/extensions you've already installed.\n */\n async create(opts: CreateSessionOptions = {}): Promise<CloudSession> {\n if (opts.target === 'local') {\n // Local mode short-circuit. We don't hit the API at all — the\n // session is just a thin wrapper over the user's local Chrome's\n // CDP endpoint (managed by the Prompteryx plugin). Saves cloud\n // minutes AND avoids a round-trip. Failure to connect is the\n // consumer's problem at .connectOverCDP() time.\n const localCdp = 'http://127.0.0.1:9222'\n const localId = `local_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`\n return {\n id: localId,\n connectUrl: localCdp,\n status: 'active',\n startedAt: new Date().toISOString(),\n recordSession: false,\n }\n }\n // Wire names match the route (proxy/country), while the SDK options keep\n // the friendlier useProxy/proxyLocation spelling.\n return this.cbRequest<CloudSession>('/api/v1/cloud-browser/sessions', {\n method: 'POST',\n body: {\n recordSession: opts.recordSession,\n captureDownloads: opts.captureDownloads,\n extensions: opts.extensions,\n proxy: opts.useProxy,\n country: opts.proxyLocation,\n sessionTimeoutMinutes: opts.sessionTimeoutMinutes,\n profileId: opts.profileId,\n persistContext: opts.persistContext,\n viewport: opts.viewport,\n ...(opts.passthrough || {}),\n },\n })\n }\n\n /** Retrieve a session's history record (status/duration/recording flag).\n * Note: this is durable history, not a live handle — it has no\n * `connectUrl`. Keep the `create()` response for connecting. */\n async get(sessionId: string): Promise<CloudSessionSummary> {\n return this.cbRequest(\n `/api/v1/cloud-browser/sessions/${encodeURIComponent(sessionId)}`,\n )\n }\n\n /** List recent sessions for your account, newest first. */\n async list(opts: { limit?: number } = {}): Promise<CloudSessionSummary[]> {\n const res = await this.cbRequest<{ sessions: CloudSessionSummary[] }>(\n '/api/v1/cloud-browser/sessions',\n { query: { limit: opts.limit } },\n )\n return res.sessions ?? []\n }\n\n /** Close a session, finalising the recording (if any) + releasing the\n * cloud-browser slot. Idempotent. No-op for local sessions\n * (target: 'local') — those don't have a slot to release. */\n async close(sessionId: string): Promise<{ ok: boolean; proxyMB?: number }> {\n // Local sessions are pure client-side handles — nothing to release.\n if (sessionId.startsWith('local_')) return { ok: true }\n return this.cbRequest(\n `/api/v1/cloud-browser/sessions/${encodeURIComponent(sessionId)}`,\n { method: 'DELETE' },\n )\n }\n}\n\nexport class CloudBrowserResource {\n readonly sessions: SessionsResource\n\n constructor(private readonly http: HttpClient) {\n this.sessions = new SessionsResource(http)\n }\n\n private cbAuth(): Record<string, string> {\n const key = this.http.cloudBrowserKey\n if (!key) throw new AuthError(MISSING_CB_KEY_MESSAGE)\n return { 'x-api-key': key }\n }\n\n /**\n * One-shot fetch through the cloud browser. Spins up a short-lived\n * session, loads the page in real Chromium (so JS-rendered sites work),\n * extracts the content, and tears down. Use this when you only need ONE\n * page and don't want to manage Playwright yourself.\n *\n * ```ts\n * const page = await px.cloudBrowser.fetch({\n * url: 'https://example.com/pricing',\n * format: 'markdown', // 'text' (default) | 'markdown' | 'html' | 'links'\n * waitForSelector: '.pricing-table', // for JS-rendered content\n * selectors: ['.pricing-table .plan'], // deterministic CSS extraction\n * })\n * // page.content, page.extracted, page.title, page.finalUrl …\n * ```\n */\n async fetch(opts: CloudFetchOptions): Promise<CloudFetchResult> {\n return this.http.request('/api/v1/cloud-browser/fetch', {\n method: 'POST',\n body: opts,\n headers: this.cbAuth(),\n timeoutMs: Math.max(90_000, (opts.timeoutMs ?? 30_000) + 30_000),\n })\n }\n\n /**\n * Search the web through the cloud browser and get structured results\n * (title/url/snippet). Runs the query against DuckDuckGo's server-rendered\n * HTML endpoint in a real browser — there is no engine choice today.\n */\n async search(opts: {\n query: string\n /** Max results, 1–25. Default 10. */\n limit?: number\n /** Route through a residential proxy. */\n proxy?: boolean\n /** Proxy exit country (with `proxy: true`), e.g. 'us'. */\n country?: string\n }): Promise<CloudSearchResult[]> {\n const res = await this.http.request<{ query: string; results: CloudSearchResult[] }>(\n '/api/v1/cloud-browser/search',\n { method: 'POST', body: opts, headers: this.cbAuth(), timeoutMs: 90_000 },\n )\n return res.results ?? []\n }\n}\n","/**\r\n * `px.executions.*` — status, logs (polled OR streamed), wait.\r\n */\r\n\r\nimport type { HttpClient } from '../client'\r\nimport { TimeoutError } from '../errors'\r\nimport type { ExecutionLogEvent, ExecutionRecord, ExecutionStatus } from '../types'\r\n\r\nconst TERMINAL_STATES: ExecutionStatus[] = [\r\n 'completed',\r\n 'failed',\r\n 'cancelled',\r\n 'timed_out',\r\n]\r\n\r\nexport class ExecutionsResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Get current execution record. */\r\n async get(executionId: string): Promise<ExecutionRecord> {\r\n return this.http.request(`/api/v1/executions/${encodeURIComponent(executionId)}`)\r\n }\r\n\r\n /**\r\n * Block until the execution reaches a terminal state. Polls every\r\n * `pollIntervalMs` (default 2s) until it's `completed`/`failed`/\r\n * `cancelled`/`timed_out`, OR until `timeoutMs` elapses (default 5min).\r\n *\r\n * Throws `TimeoutError` on timeout; otherwise returns the final record.\r\n */\r\n async wait(\r\n executionId: string,\r\n opts: { timeoutMs?: number; pollIntervalMs?: number; signal?: AbortSignal } = {},\r\n ): Promise<ExecutionRecord> {\r\n const timeoutMs = opts.timeoutMs ?? 5 * 60_000\r\n const pollIntervalMs = opts.pollIntervalMs ?? 2_000\r\n const deadline = Date.now() + timeoutMs\r\n while (true) {\r\n if (opts.signal?.aborted) throw new TimeoutError(`Wait cancelled for ${executionId}`)\r\n const exec = await this.get(executionId)\r\n if (TERMINAL_STATES.includes(exec.status)) return exec\r\n if (Date.now() > deadline) {\r\n throw new TimeoutError(`Execution ${executionId} did not finish within ${timeoutMs}ms`)\r\n }\r\n await new Promise((r) => setTimeout(r, pollIntervalMs))\r\n }\r\n }\r\n\r\n /**\r\n * Get the logs for a finished (or in-progress) execution as a one-shot\r\n * fetch. For real-time streaming use `stream(executionId)` instead.\r\n */\r\n async logs(executionId: string): Promise<ExecutionLogEvent[]> {\r\n const res = await this.http.request<{ logs: ExecutionLogEvent[] }>(\r\n `/api/v1/executions/${encodeURIComponent(executionId)}/logs`,\r\n )\r\n return res.logs ?? []\r\n }\r\n\r\n /**\r\n * Stream log events as they arrive. Async iterable:\r\n *\r\n * for await (const ev of px.executions.stream(execId)) {\r\n * console.log(ev.message)\r\n * if (ev.type === 'done') break\r\n * }\r\n */\r\n async *stream(\r\n executionId: string,\r\n opts: { signal?: AbortSignal } = {},\r\n ): AsyncGenerator<ExecutionLogEvent, void, void> {\r\n yield* this.http.streamSse<ExecutionLogEvent>(\r\n `/api/v1/executions/${encodeURIComponent(executionId)}/logs/stream`,\r\n { signal: opts.signal },\r\n )\r\n }\r\n\r\n /** Get a single node's output from a finished execution. */\r\n async getNodeOutput(executionId: string, nodeId: string): Promise<unknown> {\r\n return this.http.request(\r\n `/api/v1/executions/${encodeURIComponent(executionId)}/nodes/${encodeURIComponent(nodeId)}/output`,\r\n )\r\n }\r\n}\r\n","/**\r\n * `px.profiles.*` — Chrome profile management.\r\n *\r\n * Profiles are persistent browser identities — they store cookies,\r\n * local storage, extensions, and login state across sessions. Two\r\n * kinds:\r\n * • `cloud` — lives on the Prompteryx cloud browser infrastructure.\r\n * Accessible from any device, but starts logged out (you have to\r\n * log in once after creating).\r\n * • `local` — runs on the user's own Chrome via the Prompteryx\r\n * plugin. Reuses whatever Chrome profile the user is already\r\n * signed into (Gmail, banking, internal SSO). Cloud-only\r\n * workloads can't access this.\r\n */\r\n\r\nimport type { HttpClient } from '../client'\r\nimport type { ProfileSummary } from '../types'\r\n\r\nexport class ProfilesResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n async list(opts: { kind?: 'cloud' | 'local' } = {}): Promise<ProfileSummary[]> {\r\n const res = await this.http.request<{ profiles: ProfileSummary[] }>(\r\n '/api/v1/profiles',\r\n { query: { kind: opts.kind } },\r\n )\r\n return res.profiles ?? []\r\n }\r\n\r\n async get(profileId: string): Promise<ProfileSummary> {\r\n return this.http.request(`/api/v1/profiles/${encodeURIComponent(profileId)}`)\r\n }\r\n\r\n /** Create a new CLOUD profile. Local profiles are managed by the\r\n * plugin and cannot be created via the API. */\r\n async create(opts: { name: string }): Promise<ProfileSummary> {\r\n return this.http.request('/api/v1/profiles', {\r\n method: 'POST',\r\n body: { name: opts.name, kind: 'cloud' },\r\n })\r\n }\r\n\r\n async delete(profileId: string): Promise<{ ok: true }> {\r\n return this.http.request(`/api/v1/profiles/${encodeURIComponent(profileId)}`, {\r\n method: 'DELETE',\r\n })\r\n }\r\n}\r\n","/**\r\n * `px.schedules.*` — server-side workflow scheduling.\r\n *\r\n * Set a workflow to run on cron / interval; the platform's Cloud\r\n * Scheduler will fire it on schedule even when no client is connected.\r\n * Wraps the same scheduling primitive the Visual Studio \"Active\"\r\n * toggle uses.\r\n */\r\n\r\nimport type { HttpClient } from '../client'\r\nimport type { CreateScheduleOptions, ScheduleSummary } from '../types'\r\n\r\nexport class SchedulesResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n async list(opts: { active?: boolean; workflowId?: string } = {}): Promise<ScheduleSummary[]> {\r\n const res = await this.http.request<{ schedules: ScheduleSummary[] }>(\r\n '/api/v1/schedules',\r\n { query: { active: opts.active, workflowId: opts.workflowId } },\r\n )\r\n return res.schedules ?? []\r\n }\r\n\r\n async get(scheduleId: string): Promise<ScheduleSummary> {\r\n return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`)\r\n }\r\n\r\n /** Create a new schedule. Returns the created record. */\r\n async create(opts: CreateScheduleOptions): Promise<ScheduleSummary> {\r\n return this.http.request('/api/v1/schedules', {\r\n method: 'POST',\r\n body: opts,\r\n })\r\n }\r\n\r\n /** Pause / resume / change cron / timezone. */\r\n async update(scheduleId: string, patch: Partial<CreateScheduleOptions> & { active?: boolean }): Promise<ScheduleSummary> {\r\n return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`, {\r\n method: 'PATCH',\r\n body: patch,\r\n })\r\n }\r\n\r\n async delete(scheduleId: string): Promise<{ ok: true }> {\r\n return this.http.request(`/api/v1/schedules/${encodeURIComponent(scheduleId)}`, {\r\n method: 'DELETE',\r\n })\r\n }\r\n}\r\n","/**\r\n * `px.subscription.*` — plan + balance + usage telemetry.\r\n *\r\n * Programmatic access to the same numbers the in-app `/subscription`\r\n * and `/cloud-platform/plans` pages display. Use this to:\r\n * • Check the user's remaining AI Credits before kicking off a\r\n * long workflow.\r\n * • Read monthly execution counts for your own dashboards.\r\n * • Detect a plan downgrade and react in your code.\r\n */\r\n\r\nimport type { HttpClient } from '../client'\r\nimport type { SubscriptionStatus } from '../types'\r\n\r\nexport class SubscriptionResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /** Get the current plan + balances + usage. */\r\n async get(): Promise<SubscriptionStatus> {\r\n return this.http.request('/api/v1/subscription')\r\n }\r\n\r\n // NOT SHIPPED (2026-09-03, v0.4.0): usage() was removed — the route it\r\n // targeted (/api/v1/subscription/usage) does not exist on the live API\r\n // (the only usage route is /api/v1/usage, with a different shape).\r\n // Re-add once a real time-series endpoint ships.\r\n}\r\n","/**\r\n * `px.workflows.*` — Visual Studio workflows.\r\n *\r\n * Trigger workflows you (or anyone you share with) built in Visual\r\n * Studio. Workflows are first-class platform objects: they have\r\n * permanent IDs, can be scheduled, shared, templated, and edited\r\n * visually. Triggering one via the SDK is fully equivalent to\r\n * pressing Run in the UI — same runtime, same node executor, same\r\n * billing path.\r\n */\r\n\r\nimport type { HttpClient } from '../client'\r\nimport { TimeoutError } from '../errors'\r\nimport type {\r\n ExecutionRecord,\r\n RunWorkflowOptions,\r\n RunWorkflowResult,\r\n WorkflowSummary,\r\n} from '../types'\r\n\r\nexport class WorkflowsResource {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n async list(opts: { limit?: number; search?: string; tag?: string } = {}): Promise<WorkflowSummary[]> {\r\n const res = await this.http.request<{ workflows: WorkflowSummary[] }>(\r\n '/api/v1/workflows',\r\n { query: { limit: opts.limit, q: opts.search, tag: opts.tag } },\r\n )\r\n return res.workflows ?? []\r\n }\r\n\r\n async get(workflowId: string): Promise<WorkflowSummary & { nodes?: unknown[] }> {\r\n return this.http.request(`/api/v1/workflows/${encodeURIComponent(workflowId)}`)\r\n }\r\n\r\n /**\r\n * Trigger a workflow. Returns immediately with `executionId`. Use\r\n * `px.executions.wait(id)` to block until completion or\r\n * `px.executions.stream(id)` to follow log events live.\r\n *\r\n * The `execution` options override the workflow's saved settings\r\n * for this one run — you don't have to edit the workflow in VS to\r\n * change the proxy, region, profile, etc.\r\n */\r\n async run(workflowId: string, opts: RunWorkflowOptions = {}): Promise<RunWorkflowResult> {\r\n return this.http.request<RunWorkflowResult>(\r\n `/api/v1/workflows/${encodeURIComponent(workflowId)}/execute`,\r\n {\r\n method: 'POST',\r\n body: {\r\n variables: opts.input,\r\n executionOptions: opts.execution,\r\n },\r\n },\r\n )\r\n }\r\n\r\n /**\r\n * Run + block. Returns the final ExecutionRecord. Throws\r\n * `TimeoutError` if the run takes longer than `timeoutMs`\r\n * (default 5 minutes).\r\n */\r\n async runAndWait(\r\n workflowId: string,\r\n opts: RunWorkflowOptions & { timeoutMs?: number; pollIntervalMs?: number } = {},\r\n ): Promise<ExecutionRecord> {\r\n const started = await this.run(workflowId, opts)\r\n return this.waitInternal(started.executionId, opts.timeoutMs ?? 5 * 60_000, opts.pollIntervalMs ?? 2_000)\r\n }\r\n\r\n private async waitInternal(executionId: string, timeoutMs: number, pollIntervalMs: number): Promise<ExecutionRecord> {\r\n const deadline = Date.now() + timeoutMs\r\n while (true) {\r\n const exec = await this.http.request<ExecutionRecord>(\r\n `/api/v1/executions/${encodeURIComponent(executionId)}`,\r\n )\r\n if (['completed', 'failed', 'cancelled', 'timed_out'].includes(exec.status)) return exec\r\n if (Date.now() > deadline) {\r\n throw new TimeoutError(`Execution ${executionId} did not finish within ${timeoutMs}ms`)\r\n }\r\n await new Promise((r) => setTimeout(r, pollIntervalMs))\r\n }\r\n }\r\n}\r\n","/**\r\n * Copilot primitives — `do`, `read`, `scan` — operating on a Playwright\r\n * page.\r\n *\r\n * Two namespaces in the Prompteryx SDK:\r\n * • Copilot → SDK helps with ONE step you describe in plain English.\r\n * Your code drives Playwright; copilot just figures out\r\n * which selector to click / what data to pull / what's\r\n * discoverable on the current page.\r\n * • Autopilot → SDK runs an autonomous multi-step task with no per-\r\n * action involvement from you. See ./resources/autopilot.ts.\r\n *\r\n * The copilot primitives:\r\n * • `do(page, instruction)` — execute a single natural-language\r\n * action (\"click the Sign up button\", \"fill the email field with\r\n * hello@example.com\"). Returns a structured result describing\r\n * what was done.\r\n * • `read(page, schema)` — pull typed data from the page. Pass a\r\n * Zod schema or a raw JSON Schema; the SDK returns the populated\r\n * object validated against your schema.\r\n * • `scan(page, hint?)` — list discoverable actions on the page.\r\n * Useful as a pre-step to `do()` for resilient automations:\r\n * scan → pick the action whose description matches your intent →\r\n * do() against it.\r\n *\r\n * Architecturally the SDK never drives the browser server-side. The\r\n * server returns a structured plan and the SDK executes it locally\r\n * against your Playwright page, so your trace, debugger, and any\r\n * custom event handlers continue to work normally.\r\n */\r\n\r\nimport type { HttpClient } from './client'\r\nimport { ValidationError } from './errors'\r\nimport type { CopilotDoResult, DiscoveredAction } from './types'\r\n\r\n/** Minimal Page surface — anything satisfying this works (Playwright's\r\n * Page does, by structural typing, without an explicit import). */\r\nexport interface PageLike {\r\n url(): string\r\n title(): Promise<string>\r\n screenshot(opts?: { type?: 'png' | 'jpeg'; quality?: number; fullPage?: boolean }): Promise<Buffer | Uint8Array>\r\n evaluate<T>(fn: (...args: unknown[]) => T): Promise<T>\r\n click(selector: string, opts?: { timeout?: number }): Promise<void>\r\n fill(selector: string, value: string, opts?: { timeout?: number }): Promise<void>\r\n selectOption(selector: string, value: string | string[], opts?: { timeout?: number }): Promise<unknown>\r\n goto(url: string, opts?: { timeout?: number }): Promise<unknown>\r\n hover(selector: string, opts?: { timeout?: number }): Promise<void>\r\n keyboard: { press(key: string): Promise<void>; type(text: string, opts?: { delay?: number }): Promise<void> }\r\n // Used by the AI-vision fallback (when all ranked selectors fail). Playwright's\r\n // Page provides both; optional so a minimal page can still satisfy PageLike.\r\n mouse?: { click(x: number, y: number): Promise<void>; move?(x: number, y: number): Promise<void> }\r\n viewportSize?(): { width: number; height: number } | null\r\n locator(selector: string): {\r\n first(): { isVisible(opts?: { timeout?: number }): Promise<boolean>; textContent(opts?: { timeout?: number }): Promise<string | null> }\r\n }\r\n}\r\n\r\ninterface ZodLikeSchema<T> {\r\n parse(input: unknown): T\r\n _def?: unknown\r\n}\r\n\r\nexport class CopilotHelpers {\r\n constructor(private readonly http: HttpClient) {}\r\n\r\n /**\r\n * Execute a single natural-language action against the page.\r\n *\r\n * ```ts\r\n * await px.copilot.do(page, 'click the Sign up button')\r\n * await px.copilot.do(page, 'fill the email field with hello@example.com')\r\n * ```\r\n *\r\n * Internally: snapshot the page → POST `/api/v1/copilot/do` → server\r\n * returns a structured action plan (ranked selector + alternatives +\r\n * value + a normalised vision point) → SDK executes locally, trying the\r\n * ranked selectors in order, and ONLY if every selector fails, falling\r\n * back to an AI-vision coordinate click. Costs 1 AI Credit per call.\r\n *\r\n * This is the key resilience advantage over a pure-LLM `act()`: the cheap,\r\n * deterministic ranked selectors are tried first (no flakiness, no re-asking\r\n * the model); the vision fallback is a safety net, not the default path. Pass\r\n * `{ visionFallback: false }` to disable the fallback (selectors-only).\r\n */\r\n async do(page: PageLike, instruction: string, opts: { timeout?: number; visionFallback?: boolean } = {}): Promise<CopilotDoResult> {\r\n const start = Date.now()\r\n const snapshot = await this.snapshotPage(page)\r\n const plan = await this.http.request<{\r\n type: 'click' | 'fill' | 'select' | 'hover' | 'press_key' | 'goto'\r\n selector?: string\r\n alternativeSelectors?: string[]\r\n point?: { x: number; y: number }\r\n value?: string\r\n url?: string\r\n description: string\r\n }>('/api/v1/copilot/do', {\r\n method: 'POST',\r\n body: { instruction, snapshot },\r\n timeoutMs: 45_000,\r\n })\r\n const allowVision = opts.visionFallback !== false\r\n try {\r\n const usedVisionFallback = await this.runAction(page, plan, opts.timeout ?? 15_000, allowVision)\r\n return {\r\n success: true,\r\n action: plan.description,\r\n selector: plan.selector,\r\n usedVisionFallback,\r\n durationMs: Date.now() - start,\r\n }\r\n } catch (err) {\r\n return {\r\n success: false,\r\n action: plan.description,\r\n selector: plan.selector,\r\n durationMs: Date.now() - start,\r\n error: err instanceof Error ? err.message : String(err),\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Pull typed structured data from the page conforming to a schema.\r\n *\r\n * ```ts\r\n * import { z } from 'zod'\r\n * const product = await px.copilot.read(page, z.object({\r\n * name: z.string(),\r\n * pricePerMonth: z.number(),\r\n * features: z.array(z.string()),\r\n * }))\r\n * // product is fully typed; ValidationError is thrown if the model\r\n * // returns data that doesn't match the schema.\r\n * ```\r\n *\r\n * Accepts a Zod schema (preferred — gives you compile-time types)\r\n * OR a raw JSON Schema via `{ jsonSchema: ... }` if you don't want\r\n * a `zod` peer dep.\r\n */\r\n async read<T>(page: PageLike, schema: ZodLikeSchema<T> | { jsonSchema: unknown }): Promise<T> {\r\n const snapshot = await this.snapshotPage(page)\r\n const jsonSchema = 'jsonSchema' in schema\r\n ? (schema as { jsonSchema: unknown }).jsonSchema\r\n : this.zodToJsonSchema(schema as ZodLikeSchema<T>)\r\n const raw = await this.http.request<{ data: unknown }>(\r\n '/api/v1/copilot/read',\r\n { method: 'POST', body: { snapshot, jsonSchema }, timeoutMs: 60_000 },\r\n )\r\n if ('parse' in (schema as object) && typeof (schema as ZodLikeSchema<T>).parse === 'function') {\r\n try {\r\n return (schema as ZodLikeSchema<T>).parse(raw.data)\r\n } catch (e) {\r\n throw new ValidationError(\r\n `Extracted data didn't match the schema: ${e instanceof Error ? e.message : String(e)}`,\r\n { raw: raw.data },\r\n )\r\n }\r\n }\r\n return raw.data as T\r\n }\r\n\r\n /**\r\n * Scan the page for available actions. Returns a ranked list of\r\n * actions a user / agent could take next, with selectors + multi-\r\n * option fallbacks + human-readable descriptions.\r\n *\r\n * Useful as a pre-step to `do()` for resilient automations:\r\n * const actions = await px.copilot.scan(page, 'sign up flow')\r\n * const target = actions.find(a => a.description.includes('Sign up'))\r\n * if (target) await px.copilot.do(page, target.example ?? `click ${target.description}`)\r\n */\r\n async scan(page: PageLike, hint?: string): Promise<DiscoveredAction[]> {\r\n const snapshot = await this.snapshotPage(page)\r\n const res = await this.http.request<{ actions: DiscoveredAction[] }>(\r\n '/api/v1/copilot/scan',\r\n { method: 'POST', body: { snapshot, hint }, timeoutMs: 45_000 },\r\n )\r\n return res.actions ?? []\r\n }\r\n\r\n // ── internals ────────────────────────────────────────────────────────\r\n\r\n private async snapshotPage(page: PageLike): Promise<{ url: string; title: string; screenshot: string }> {\r\n const buf = await page.screenshot({ type: 'jpeg', quality: 60, fullPage: false })\r\n const screenshot = bufferToBase64(buf)\r\n return {\r\n url: page.url(),\r\n title: await page.title().catch(() => ''),\r\n screenshot,\r\n }\r\n }\r\n\r\n /** Execute the plan. Returns true if the AI-vision fallback was used. */\r\n private async runAction(\r\n page: PageLike,\r\n plan: {\r\n type: 'click' | 'fill' | 'select' | 'hover' | 'press_key' | 'goto'\r\n selector?: string\r\n alternativeSelectors?: string[]\r\n point?: { x: number; y: number }\r\n value?: string\r\n url?: string\r\n },\r\n timeout: number,\r\n allowVision: boolean,\r\n ): Promise<boolean> {\r\n if (plan.type === 'press_key' && plan.value) {\r\n await page.keyboard.press(plan.value)\r\n return false\r\n }\r\n if (plan.type === 'goto' && plan.url) {\r\n await page.goto(plan.url, { timeout })\r\n return false\r\n }\r\n const candidates = [plan.selector, ...(plan.alternativeSelectors ?? [])].filter(\r\n (s): s is string => typeof s === 'string' && s.length > 0,\r\n )\r\n // 1) Try the ranked selectors in order (cheap + deterministic).\r\n let lastErr: unknown\r\n for (const sel of candidates) {\r\n try {\r\n switch (plan.type) {\r\n case 'click': await page.click(sel, { timeout }); return false\r\n case 'fill': await page.fill(sel, plan.value ?? '', { timeout }); return false\r\n case 'select': await page.selectOption(sel, plan.value ?? '', { timeout }); return false\r\n case 'hover': await page.hover(sel, { timeout }); return false\r\n default: throw new Error(`Unsupported action type: ${plan.type}`)\r\n }\r\n } catch (e) {\r\n lastErr = e\r\n }\r\n }\r\n // 2) AI-vision fallback: every selector failed → click the model's\r\n // normalised point. <select> can't be operated by a coordinate, so it's\r\n // selectors-only. Requires page.mouse (Playwright provides it).\r\n if (allowVision && plan.point && plan.type !== 'select' && page.mouse) {\r\n const vp = page.viewportSize?.() || { width: 1280, height: 800 }\r\n const x = Math.round((plan.point.x / 1000) * vp.width)\r\n const y = Math.round((plan.point.y / 1000) * vp.height)\r\n await page.mouse.click(x, y)\r\n if (plan.type === 'fill' && plan.value) await page.keyboard.type(plan.value, { delay: 20 })\r\n // hover via mouse.move when available, else the click above is close enough.\r\n if (plan.type === 'hover' && page.mouse.move) await page.mouse.move(x, y)\r\n return true\r\n }\r\n if (candidates.length === 0) throw new Error(`No selector or vision point returned for action ${plan.type}`)\r\n throw lastErr ?? new Error(`No selector worked for ${plan.type} (and vision fallback unavailable)`)\r\n }\r\n\r\n private zodToJsonSchema<T>(schema: ZodLikeSchema<T>): unknown {\r\n return { type: 'object', _zodHint: String(schema) }\r\n }\r\n}\r\n\r\nfunction bufferToBase64(buf: Buffer | Uint8Array): string {\r\n if (typeof Buffer !== 'undefined' && buf instanceof Buffer) {\r\n return buf.toString('base64')\r\n }\r\n let binary = ''\r\n const bytes = buf as Uint8Array\r\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\r\n const g = globalThis as any\r\n return g.btoa ? g.btoa(binary) : Buffer.from(binary, 'binary').toString('base64')\r\n}\r\n","/**\n * Browser-agent model catalog — the ids `px.autopilot.run({ model })` accepts.\n *\n * ⚠️ MUST MIRROR `components/unified-chat-v2/browser-models.ts`\n * `V2_BROWSER_MODELS` in the platform repo — that file is the canonical\n * catalog the server validates against (an unknown id hard-400s with\n * `UNSUPPORTED_MODEL` under strict validation). When that list changes,\n * regenerate this one. Last synced: 2026-09-03 — 32 ids.\n *\n * The type stays open (`| (string & {})`) so a model the server adds\n * tomorrow works without an SDK release, while editors still autocomplete\n * the known catalog.\n */\n\nexport const AUTOPILOT_MODELS = [\n // ── Standard (Gemini native Computer Use) ────────────────────────────────\n 'gemini-3.5-flash', // Recommended — fast and cheap. THE DEFAULT.\n 'gemini-3.7-flash', // Newest GA Flash — Google-recommended for computer use\n 'gemini-3.6-flash', // Newest Flash (Computer Use preview)\n 'gemini-default', // Gemini 2.5 Computer Use (legacy)\n // ── Experimental (Gemini) ────────────────────────────────────────────────\n 'gemini-3-flash-preview',\n 'gemini-3.5-flash-lite',\n // Harness aliases — resolved server-side to an underlying brain + prompt.\n 'model-a',\n 'model-a1',\n 'model-b',\n 'model-j',\n 'model-k',\n 'model-k37',\n // ── Anthropic / OpenAI native Computer Use ───────────────────────────────\n 'claude-sonnet-4-6',\n 'claude-opus-4-8',\n 'gpt-5.6-terra',\n 'gpt-5.6-sol',\n 'gpt-5.5',\n // ── Generic Vision Loop (standard chat models on screenshots) ────────────\n 'claude-fable-5-vision',\n 'claude-opus-5-vision',\n 'claude-sonnet-5-vision',\n 'claude-sonnet-4-6-vision',\n 'gpt-5.6-luna-vision',\n 'gpt-5.4-vision',\n 'gpt-4o-vision',\n 'kimi-k3-vision',\n // ── Experimental server-side harness engines ─────────────────────────────\n 'modelc',\n 'model-d',\n 'model-d1',\n 'model-e',\n 'model-f',\n 'model-h',\n 'model-i',\n] as const\n\n/** A model id from the known catalog. */\nexport type AutopilotModelId = (typeof AUTOPILOT_MODELS)[number]\n\n/** Open union: known ids autocomplete, forward-compatible strings still pass. */\nexport type AutopilotModel = AutopilotModelId | (string & {})\n\n/** The platform default when `model` is omitted. */\nexport const DEFAULT_AUTOPILOT_MODEL = 'gemini-3.5-flash'\n"],"mappings":"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","names":[]}