ql-agent-sdk 1.1.0 → 1.3.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/README.md +48 -1
- package/dist/index.cjs +36 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +158 -1
- package/dist/index.d.ts +158 -1
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ Create keys in your Quanton Labs dashboard → **API Keys** page. Each key is sc
|
|
|
74
74
|
|
|
75
75
|
| Scope | Grants access to |
|
|
76
76
|
|-------|-----------------|
|
|
77
|
-
| `workspace` | `ql.workspace.get()` |
|
|
77
|
+
| `workspace` | `ql.workspace.get()`, `ql.workspace.getModels()`, `ql.workspace.update()`, `ql.workspace.updateModels()`, `ql.workspace.listCatalogModels()`, `ql.workspace.verifyOpenRouterKey()`, `ql.workspace.listKeys()` |
|
|
78
78
|
| `agents` | `ql.agents.list()`, `ql.agents.get()` |
|
|
79
79
|
| `capabilities` | `ql.agents.capabilities()`, `ql.agents.runCapability()` |
|
|
80
80
|
| `chat` | `ql.agents.chat()`, `ql.agents.chatStream()` |
|
|
@@ -133,6 +133,53 @@ ws.plan; // "standard" | "premium" | "enterprise" | undefined
|
|
|
133
133
|
ws.createdAt; // string (ISO 8601)
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
+
#### `ql.workspace.getModels()` → `Promise<WorkspaceModelsResult>`
|
|
137
|
+
|
|
138
|
+
**Scope:** `workspace`
|
|
139
|
+
|
|
140
|
+
Returns the per-role model configuration (director panel): defaults for
|
|
141
|
+
`reasoning`, `instruct`, `response`, `vision`, `image`, `video` plus ordered
|
|
142
|
+
fallback lists. The OpenRouter key is always masked (`keyMasked`).
|
|
143
|
+
|
|
144
|
+
#### `ql.workspace.update(input)` / `ql.workspace.updateModels(input)` → `Promise<Workspace>`
|
|
145
|
+
|
|
146
|
+
**Scope:** `workspace`
|
|
147
|
+
|
|
148
|
+
Partially updates the workspace. `update()` accepts `{ name?, config?: { openrouter? } }`;
|
|
149
|
+
`updateModels()` is a shortcut that only touches `config.openrouter`. Model fields may be
|
|
150
|
+
set to `""` to clear a default; each `fallbacks.<role>` list holds at most 3 model ids.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
await ql.workspace.update({ name: "Robinson Mfg. Co., Inc." });
|
|
154
|
+
await ql.workspace.updateModels({
|
|
155
|
+
reasoning: "deepseek/deepseek-v4-flash-0731",
|
|
156
|
+
vision: "anthropic/claude-sonnet-5.5",
|
|
157
|
+
fallbacks: { reasoning: ["openai/gpt-oss-20b"] },
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `ql.workspace.listCatalogModels()` → `Promise<CatalogResult>`
|
|
162
|
+
|
|
163
|
+
**Scope:** `workspace`
|
|
164
|
+
|
|
165
|
+
OpenRouter model catalog (`{ id, name, contextLength, promptPrice, completionPrice }[]`),
|
|
166
|
+
cached server-side for 10 minutes. May return `stale: true` when upstream is down.
|
|
167
|
+
|
|
168
|
+
#### `ql.workspace.verifyOpenRouterKey(key, model?, baseUrl?)` → `Promise<VerifyKeyResult>`
|
|
169
|
+
|
|
170
|
+
**Scope:** `workspace`
|
|
171
|
+
|
|
172
|
+
Checks an OpenRouter key with a 1-token completion (default model
|
|
173
|
+
`openai/gpt-oss-20b`). Returns `{ valid: true }` or `{ valid: false, error }`.
|
|
174
|
+
|
|
175
|
+
#### `ql.workspace.listKeys()` → `Promise<KeysResult>`
|
|
176
|
+
|
|
177
|
+
**Scope:** `workspace`
|
|
178
|
+
|
|
179
|
+
Lists the workspace's v1 API keys with rotation metadata. Every key is auto-deleted
|
|
180
|
+
`lifetimeDays` (90) days after creation; `rotatesAt`/`daysLeft` show time remaining.
|
|
181
|
+
Mint replacements from the Quanton Labs site when one expires.
|
|
182
|
+
|
|
136
183
|
---
|
|
137
184
|
|
|
138
185
|
### Agents
|
package/dist/index.cjs
CHANGED
|
@@ -438,6 +438,42 @@ var WorkspaceApi = class {
|
|
|
438
438
|
get() {
|
|
439
439
|
return this.t.json("GET", "/api/v1/workspace");
|
|
440
440
|
}
|
|
441
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
442
|
+
getModels() {
|
|
443
|
+
return this.t.json("GET", "/api/v1/workspace/models");
|
|
444
|
+
}
|
|
445
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
446
|
+
update(input) {
|
|
447
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: input });
|
|
448
|
+
}
|
|
449
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
450
|
+
updateModels(input) {
|
|
451
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: { config: { openrouter: input } } });
|
|
452
|
+
}
|
|
453
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
454
|
+
listCatalogModels() {
|
|
455
|
+
return this.t.json("GET", "/api/v1/workspace/models/catalog");
|
|
456
|
+
}
|
|
457
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
458
|
+
verifyOpenRouterKey(key, model, baseUrl) {
|
|
459
|
+
return this.t.json("POST", "/api/v1/workspace/models/verify", { body: { key, model, baseUrl } });
|
|
460
|
+
}
|
|
461
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
462
|
+
listKeys() {
|
|
463
|
+
return this.t.json("GET", "/api/v1/workspace/keys");
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* POST /api/v1/workspace/keys — mint a new API key for the workspace.
|
|
467
|
+
* All expired, non-revoked keys (issued and legacy) are discarded first, so a
|
|
468
|
+
* rotation is one call. The raw `secret` is returned exactly once.
|
|
469
|
+
*/
|
|
470
|
+
createKey(input) {
|
|
471
|
+
return this.t.json("POST", "/api/v1/workspace/keys", { body: input ?? {} });
|
|
472
|
+
}
|
|
473
|
+
/** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */
|
|
474
|
+
deleteKey(keyId) {
|
|
475
|
+
return this.t.json("DELETE", `/api/v1/workspace/keys/${encodeURIComponent(keyId)}`);
|
|
476
|
+
}
|
|
441
477
|
};
|
|
442
478
|
var AgentsApi = class {
|
|
443
479
|
constructor(t) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/sse.ts","../src/task.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["/**\n * ql-agent-sdk — TypeScript SDK for the Quanton Labs agent platform API (v1).\n *\n * Quick start:\n * import { QLClient } from \"ql-agent-sdk\";\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY! });\n * const agents = await ql.agents.list();\n */\n\nexport { QLClient, WorkspaceApi, AgentsApi, WorkflowsApi, TasksApi, ImagesApi, VideosApi, AudioApi, FilesApi, DEFAULT_BASE_URL } from \"./client.js\";\nexport type { QLClientOptions } from \"./client.js\";\n\nexport { QLError } from \"./errors.js\";\nexport type { QLErrorContext } from \"./errors.js\";\n\nexport { TaskHandle, VideoTaskHandle, isTerminalTaskStatus } from \"./task.js\";\n\nexport { API_ERROR_CODES } from \"./types.js\";\nexport type {\n ApiErrorCode,\n ChatMessage,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n StreamOptions,\n MessageItem,\n HistoryPage,\n HistoryParams,\n AgentSummary,\n AgentListResult,\n CapParamKind,\n CapabilityParam,\n CapabilityTemplate,\n CapabilityInfo,\n AgentDetail,\n CapabilitiesResult,\n RunCapabilityInput,\n CapabilityResult,\n RunCapabilityResult,\n Workspace,\n WorkflowRunInput,\n WorkflowRunStart,\n WorkflowRunStatus,\n WorkflowRun,\n ImageTier,\n ImagePricingEntry,\n ImageModelInfo,\n ImageModelsResult,\n ImageReferenceInput,\n ImageGenerateInput,\n GeneratedImage,\n ImageUsage,\n ImageGenerateResult,\n TaskPriority,\n TaskCreateInput,\n TaskCreated,\n TaskStatus,\n Task,\n WaitOptions,\n VideoTier,\n VideoPricingEntry,\n VideoModelInfo,\n VideoModelsResult,\n VideoGenerateInput,\n VideoTaskCreated,\n VideoTaskStatus,\n VideoTask,\n VideoWaitOptions,\n TtsInput,\n TtsResult,\n VoiceInfo,\n VoicesResult,\n UploadedFile,\n FileUploadOptions,\n} from \"./types.js\";\n","import type { ApiErrorCode } from \"./types.js\";\n\nexport interface QLErrorContext {\n method?: string;\n url?: string;\n}\n\n/**\n * Error thrown by the SDK for any failed API interaction.\n *\n * - `status`: HTTP status code (when the failure came from an HTTP response).\n * - `code`: stable API error code when provided by the backend, otherwise a\n * synthesized one derived from the status, or a synthetic transport\n * code such as \"aborted\" / \"timeout\" / \"network\".\n * - `message`: human-readable description. The API key is never included.\n */\nexport class QLError extends Error {\n readonly status?: number;\n readonly code: string;\n readonly method?: string;\n readonly url?: string;\n /** The raw parsed error body (if any), for advanced inspection. */\n readonly details?: unknown;\n\n constructor(message: string, opts: { status?: number; code: string; context?: QLErrorContext; details?: unknown } = { code: \"internal_error\" }) {\n super(message);\n this.name = \"QLError\";\n this.status = opts.status;\n this.code = opts.code;\n this.method = opts.context?.method;\n this.url = opts.context?.url;\n this.details = opts.details;\n // Restore prototype chain (required when targeting ES5-ish runtimes).\n Object.setPrototypeOf(this, QLError.prototype);\n }\n\n /** True for 401/403 or unauthorized/forbidden codes. */\n get isAuthError(): boolean {\n return this.code === \"unauthorized\" || this.code === \"forbidden\" || this.status === 401 || this.status === 403;\n }\n\n /** True when the request was aborted by the caller. */\n get isAborted(): boolean {\n return this.code === \"aborted\";\n }\n\n /** True when a wait() call exceeded its timeout. */\n get isTimeout(): boolean {\n return this.code === \"timeout\";\n }\n\n /** True for transient network failures (no HTTP response received). */\n get isNetworkError(): boolean {\n return this.code === \"network\";\n }\n}\n\n/** Map an HTTP status to a stable API error code when the body has none. */\nexport function codeFromStatus(status: number): ApiErrorCode | \"conflict\" {\n switch (status) {\n case 400:\n return \"validation_error\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 409:\n return \"conflict\";\n default:\n return status >= 500 ? \"internal_error\" : \"validation_error\";\n }\n}\n\ninterface ParsedErrorBody {\n ok?: boolean;\n error?: { code?: string; message?: string } | string;\n message?: string;\n}\n\n/** Build a QLError from a non-2xx HTTP response. Never includes the API key. */\nexport function toHttpError(status: number, text: string | undefined, ctx: QLErrorContext): QLError {\n let parsed: ParsedErrorBody | null = null;\n if (text) {\n try {\n const j = JSON.parse(text);\n if (j && typeof j === \"object\") parsed = j as ParsedErrorBody;\n } catch {\n parsed = null;\n }\n }\n\n const bodyErr = parsed?.error;\n let code: string | undefined;\n let message: string | undefined;\n if (typeof bodyErr === \"string\") {\n message = bodyErr;\n } else if (bodyErr && typeof bodyErr === \"object\") {\n code = typeof bodyErr.code === \"string\" ? bodyErr.code : undefined;\n message = typeof bodyErr.message === \"string\" ? bodyErr.message : undefined;\n }\n if (!code) code = codeFromStatus(status);\n if (!message) message = (typeof parsed?.message === \"string\" ? parsed.message : undefined) ?? `Request failed with status ${status}`;\n\n return new QLError(message, { status, code, context: ctx, details: parsed ?? undefined });\n}\n\n/** Wrap a low-level fetch/network failure (no HTTP response). */\nexport function toNetworkError(cause: unknown, ctx: QLErrorContext): QLError {\n const aborted = isAbortCause(cause);\n if (aborted) {\n return new QLError(\"Request aborted\", { code: \"aborted\", context: ctx });\n }\n const msg = cause instanceof Error ? cause.message : String(cause);\n return new QLError(`Network error: ${msg}`, { code: \"network\", context: ctx, details: cause });\n}\n\nfunction isAbortCause(cause: unknown): boolean {\n if (!cause) return false;\n if (typeof cause === \"object\") {\n const c = cause as { name?: string; type?: string };\n if (c.name === \"AbortError\" || c.type === \"aborted\") return true;\n }\n return false;\n}\n\n/** Build an abort error for wait()/stream cancellation. */\nexport function abortError(): QLError {\n return new QLError(\"Operation aborted\", { code: \"aborted\" });\n}\n\n/** Build a timeout error for wait(). */\nexport function timeoutError(timeoutMs: number): QLError {\n return new QLError(`Timed out after ${timeoutMs}ms`, { code: \"timeout\" });\n}\n","import { QLError, toHttpError, toNetworkError } from \"./errors.js\";\nimport type { ApiErrorCode } from \"./types.js\";\n\nexport interface TransportOptions {\n apiKey: string;\n baseUrl: string;\n fetchImpl: typeof fetch;\n}\n\nexport interface JsonRequestOptions {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport interface FormRequestOptions {\n form: FormData;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * Internal transport used by the API namespaces. Keeps the API key inside a\n * closure (never exposed) and normalizes responses/errors for the caller.\n */\nexport interface Transport {\n /** Perform a JSON request and return the unwrapped `data` payload. */\n json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;\n /** Perform a multipart/form-data request and return the unwrapped `data` payload. */\n form<T>(path: string, opts: FormRequestOptions): Promise<T>;\n /**\n * Perform a request expected to stream SSE. Returns the response body stream\n * after verifying a 2xx + text/event-stream; throws QLError otherwise.\n */\n stream(method: string, path: string, opts?: JsonRequestOptions & { acceptStream?: boolean }): Promise<ReadableStream<Uint8Array>>;\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n const { apiKey, baseUrl, fetchImpl } = opts;\n\n return {\n async json<T>(method: string, path: string, reqOpts: JsonRequestOptions = {}) {\n const res = await doFetch(method, path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });\n return unwrap<T>(text, { method, url: res.url });\n },\n\n async form<T>(path: string, reqOpts: FormRequestOptions) {\n const res = await doFormFetch(path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method: \"POST\", url: res.url });\n return unwrap<T>(text, { method: \"POST\", url: res.url });\n },\n\n async stream(method, path, reqOpts = {}) {\n const res = await doFetch(method, path, {\n ...reqOpts,\n headers: { accept: \"text/event-stream\", ...(reqOpts.headers ?? {}) },\n });\n if (!res.ok) {\n const text = await res.text().catch(() => undefined);\n throw toHttpError(res.status, text, { method, url: res.url });\n }\n const ctype = (res.headers.get(\"content-type\") || \"\").toLowerCase();\n if (!ctype.includes(\"text/event-stream\")) {\n // The endpoint returned a non-SSE body (e.g. an error envelope). Surface it.\n const text = await res.text().catch(() => undefined);\n throw new QLError(`Expected text/event-stream but got \"${ctype || \"unknown\"}\"`, {\n status: res.status,\n code: \"internal_error\",\n context: { method, url: res.url },\n details: safeParse(text),\n });\n }\n if (!res.body) throw new QLError(\"Response has no readable body stream\", { code: \"network\", context: { method, url: res.url } });\n return res.body;\n },\n };\n\n function doFetch(method: string, path: string, reqOpts: JsonRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path, reqOpts.query);\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method,\n headers,\n body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method, url });\n });\n }\n\n function doFormFetch(path: string, reqOpts: FormRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path);\n // No content-type header here — fetch sets the multipart boundary itself.\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method: \"POST\",\n headers,\n body: reqOpts.form,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method: \"POST\", url });\n });\n }\n}\n\nfunction unwrap<T>(text: string, ctx: { method?: string; url?: string }): T {\n const parsed = safeParse(text);\n if (parsed && typeof parsed === \"object\" && \"ok\" in (parsed as Record<string, unknown>)) {\n const env = parsed as { ok: boolean; data?: unknown; error?: { code?: string; message?: string } };\n if (env.ok === true) return env.data as T;\n // ok:false on a 2xx — treat as an application error.\n throw new QLError(env.error?.message || \"Request failed\", {\n code: (env.error?.code as ApiErrorCode) || \"internal_error\",\n context: ctx,\n details: env,\n });\n }\n // Non-enveloped payload (legacy shapes): return as-is.\n return parsed as T;\n}\n\nfunction safeParse(text?: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Join base + path and append a query string (skipping undefined values). */\nexport function buildUrl(baseUrl: string, path: string, query?: Record<string, string | number | undefined>): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const p = path.startsWith(\"/\") ? path : `/${path}`;\n let url = `${base}${p}`;\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n }\n return url;\n}\n\n/** Normalize a base URL: trim whitespace and drop any trailing slash. */\nexport function normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n","/**\n * Minimal, dependency-free Server-Sent Events reader built on Web Streams.\n *\n * Handles the cases that commonly break naive parsers:\n * - a `data:` line split across two TCP chunks (chunk boundaries)\n * - multiple events arriving in a single chunk\n * - both CRLF and LF line endings (and lone CR)\n * - a final event that is not terminated by a trailing newline\n * - the `[DONE]` terminator\n * - abort signals\n */\n\nexport interface SSEEvent {\n /** The concatenated `data:` payload for this event (trimmed of the leading space). */\n data: string;\n}\n\ninterface ReadOptions {\n signal?: AbortSignal;\n /** When true, stop after the first `[DONE]` data value. Default true. */\n stopOnDone?: boolean;\n}\n\n/**\n * Read raw SSE events from a `ReadableStream<Uint8Array>`.\n * Yields one object per event with its combined `data` payload.\n */\nexport async function* readSSEEvents(\n body: ReadableStream<Uint8Array>,\n opts: ReadOptions = {},\n): AsyncGenerator<SSEEvent, void, unknown> {\n const stopOnDone = opts.stopOnDone ?? true;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let dataLines: string[] = [];\n\n // Abort wiring: cancel the underlying stream promptly when the signal fires.\n const onAbort = () => {\n void reader.cancel().catch(() => {});\n };\n if (opts.signal) {\n if (opts.signal.aborted) {\n await reader.cancel().catch(() => {});\n return;\n }\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n const dispatch = (): SSEEvent | null => {\n if (dataLines.length === 0) return null;\n const data = dataLines.join(\"\\n\");\n dataLines = [];\n return { data };\n };\n\n const processLine = (line: string): SSEEvent | null => {\n if (line === \"\") return dispatch(); // blank line = event boundary\n if (line.startsWith(\":\")) return null; // comment\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) value = value.slice(1);\n dataLines.push(value);\n return null;\n }\n // Ignore event:/id:/retry: and unknown fields.\n return null;\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let s = splitFirstLine(buffer);\n while (s !== null) {\n const ev = processLine(s.line);\n if (ev) {\n if (stopOnDone && ev.data.trim() === \"[DONE]\") return;\n yield ev;\n }\n buffer = s.rest;\n s = splitFirstLine(buffer);\n }\n }\n\n // Flush any bytes still held by the decoder.\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const ev = processLine(buffer);\n if (ev && !(stopOnDone && ev.data.trim() === \"[DONE]\")) yield ev;\n }\n // Flush a final event that had no terminating blank line.\n const tail = dispatch();\n if (tail && !(stopOnDone && tail.data.trim() === \"[DONE]\")) yield tail;\n } finally {\n if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n try {\n reader.releaseLock();\n } catch {\n /* already released */\n }\n }\n}\n\n/** Split the first complete line (LF, CRLF, or lone CR) out of `buf`. */\nfunction splitFirstLine(buf: string): { line: string; rest: string } | null {\n const nl = buf.indexOf(\"\\n\");\n const cr = buf.indexOf(\"\\r\");\n let end = -1;\n let termLen = 0;\n if (nl !== -1 && (cr === -1 || nl < cr)) {\n end = nl;\n termLen = 1;\n } else if (cr !== -1) {\n end = cr;\n termLen = buf[cr + 1] === \"\\n\" ? 2 : 1;\n }\n if (end === -1) return null;\n return { line: buf.slice(0, end), rest: buf.slice(end + termLen) };\n}\n\n/** Parse a single SSE `data` payload as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n const trimmed = data.trim();\n if (trimmed === \"\" || trimmed === \"[DONE]\") return null;\n try {\n return JSON.parse(trimmed) as T;\n } catch {\n return null; // malformed JSON is skipped, not fatal\n }\n}\n","import type { Transport } from \"./http.js\";\nimport { abortError, timeoutError } from \"./errors.js\";\nimport type { Task, WaitOptions, VideoTask, VideoWaitOptions } from \"./types.js\";\n\n/** Statuses at which a job will not change again (shared by tasks and video jobs). */\nconst TERMINAL_TASK_STATUSES = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\nexport function isTerminalTaskStatus(status: string): boolean {\n return TERMINAL_TASK_STATUSES.has(status);\n}\n\ninterface PollOptions {\n intervalMs?: number;\n maxIntervalMs?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Shared polling loop used by TaskHandle.wait() and VideoTaskHandle.wait().\n *\n * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.\n * - Throws a QLError with code \"timeout\" if `timeoutMs` elapses first.\n * - Throws a QLError with code \"aborted\" if `signal` aborts.\n */\nasync function pollUntilTerminal<T>(\n fetchSnapshot: (signal?: AbortSignal) => Promise<T>,\n isTerminal: (snapshot: T) => boolean,\n onTick: ((snapshot: T) => void) | undefined,\n opts: PollOptions,\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? 2000;\n const maxIntervalMs = opts.maxIntervalMs ?? 15000;\n const signal = opts.signal;\n const startedAt = Date.now();\n let delay = intervalMs;\n\n for (;;) {\n if (signal?.aborted) throw abortError();\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n const snapshot = await fetchSnapshot(signal);\n onTick?.(snapshot);\n if (isTerminal(snapshot)) return snapshot;\n\n // Recompute timeout after the poll so a slow request doesn't overshoot silently.\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n await sleep(delay, signal);\n delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));\n }\n}\n\n/**\n * A handle to a background task created via `tasks.create`.\n *\n * NOTE on execution: creating a task only enqueues it. It may stay in the\n * `queued` state until an existing worker/execution mechanism processes it —\n * this SDK does not trigger execution. `wait()` simply polls until the task\n * reaches a terminal status (or you time out / abort).\n */\nexport class TaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current task snapshot (single request). */\n get(signal?: AbortSignal): Promise<Task> {\n return this.transport.json<Task>(\"GET\", `/api/v1/tasks/${this.taskId}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<Task> {\n return this.get(signal);\n }\n\n /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */\n async wait(opts: WaitOptions = {}): Promise<Task> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/**\n * A handle to a video job created via `videos.generate`.\n * Polls the video-tasks endpoint until the job reaches a terminal status.\n */\nexport class VideoTaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current job snapshot (single request). */\n get(signal?: AbortSignal): Promise<VideoTask> {\n return this.transport.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<VideoTask> {\n return this.get(signal);\n }\n\n /** Poll until the job reaches a terminal status (completed/failed/cancelled). */\n async wait(opts: VideoWaitOptions = {}): Promise<VideoTask> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/** Abort-aware sleep. Rejects with an abort error if `signal` fires first. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n };\n if (signal) signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { createTransport, normalizeUrl, type Transport } from \"./http.js\";\nimport { QLError } from \"./errors.js\";\nimport { readSSEEvents, parseSSEData } from \"./sse.js\";\nimport { TaskHandle, VideoTaskHandle } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CapabilitiesResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelsResult,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n TtsInput,\n TtsResult,\n UploadedFile,\n FileUploadOptions,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n VideoGenerateInput,\n VideoModelsResult,\n VideoTask,\n VideoTaskCreated,\n VoicesResult,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\n/** Videos namespace (tiered video generation: submit → poll). */\nexport class VideosApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/videos/models — list tiered video models + engine availability. */\n listModels(): Promise<VideoModelsResult> {\n return this.t.json<VideoModelsResult>(\"GET\", \"/api/v1/videos/models\");\n }\n\n /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */\n generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated> {\n return this.t.json<VideoTaskCreated>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });\n }\n\n /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */\n getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */\n cancelTask(taskId: string): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"DELETE\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);\n }\n\n /** Get a handle for polling / waiting on a video job (poll(), wait()). */\n handle(taskId: string): VideoTaskHandle {\n return new VideoTaskHandle(this.t, taskId);\n }\n}\n\n/** Audio namespace (text-to-speech). */\nexport class AudioApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/audio/voices — list available TTS voices. */\n voices(): Promise<VoicesResult> {\n return this.t.json<VoicesResult>(\"GET\", \"/api/v1/audio/voices\");\n }\n\n /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */\n textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult> {\n return this.t.json<TtsResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });\n }\n}\n\n/** Files namespace (media uploads). */\nexport class FilesApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/files — upload a media file (multipart field \"file\"). */\n async upload(file: Blob, opts: FileUploadOptions = {}): Promise<UploadedFile> {\n const form = new FormData();\n if (opts.filename !== undefined) {\n form.append(\"file\", file, opts.filename);\n } else {\n form.append(\"file\", file);\n }\n // Coarse progress only: fetch does not expose upload byte progress.\n opts.onProgress?.(0);\n const result = await this.t.form<UploadedFile>(\"/api/v1/files\", { form });\n opts.onProgress?.(100);\n return result;\n }\n}\n\nfunction readEnvBaseUrl(): string | undefined {\n try {\n if (typeof process !== \"undefined\" && process?.env) {\n return process.env.QL_BASE_URL || undefined;\n }\n } catch {\n /* non-Node runtime */\n }\n return undefined;\n}\n\n/**\n * The public client. Example:\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });\n * const agents = await ql.agents.list();\n */\nexport class QLClient {\n readonly workspace: WorkspaceApi;\n readonly agents: AgentsApi;\n readonly workflows: WorkflowsApi;\n readonly tasks: TasksApi;\n readonly images: ImagesApi;\n readonly videos: VideosApi;\n readonly audio: AudioApi;\n readonly files: FilesApi;\n\n private readonly transport: Transport;\n private readonly base: string;\n\n constructor(opts: QLClientOptions) {\n if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.length === 0) {\n throw new QLError(\"apiKey is required\", { code: \"validation_error\" });\n }\n this.base = normalizeUrl(opts.baseUrl ?? readEnvBaseUrl() ?? DEFAULT_BASE_URL);\n const fetchImpl = (opts.fetch ?? globalThis.fetch).bind(globalThis);\n this.transport = createTransport({ apiKey: opts.apiKey, baseUrl: this.base, fetchImpl });\n this.workspace = new WorkspaceApi(this.transport);\n this.agents = new AgentsApi(this.transport);\n this.workflows = new WorkflowsApi(this.transport);\n this.tasks = new TasksApi(this.transport);\n this.images = new ImagesApi(this.transport);\n this.videos = new VideosApi(this.transport);\n this.audio = new AudioApi(this.transport);\n this.files = new FilesApi(this.transport);\n }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Videos — tiered video generation (async: submit → poll)\n// ---------------------------------------------------------------------------\n\nexport type VideoTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for a video model. */\nexport interface VideoPricingEntry {\n /** What is billed, e.g. \"output_video\" / \"voiceover\". */\n billable: string;\n /** Billing unit: per rendered second, or flat per request. */\n unit: \"second\" | \"request\";\n costUsd: number;\n}\n\n/** A tiered video-generation model as returned by `videos.listModels`. */\nexport interface VideoModelInfo {\n id: string;\n name: string;\n tier: VideoTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n /** Execution engine (e.g. \"motion-graphics\"). */\n engine: string;\n supportsProductImages: boolean;\n maxReferenceImages: number;\n supportsReferenceVideos: boolean;\n maxReferenceVideos: number;\n supportedAspectRatios: string[];\n supportedResolutions: string[];\n /** Inclusive [min, max] duration in seconds. */\n durationRange: [number, number];\n voiceoverSupport: boolean;\n pricing: {\n summary: string;\n entries: VideoPricingEntry[];\n };\n recommended: boolean;\n enabled: boolean;\n /** Runtime engine availability (render toolchain present). */\n available: boolean;\n}\n\n/** Result of `videos.listModels`. */\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n}\n\n/** Input for `videos.generate`. */\nexport interface VideoGenerateInput {\n /** The creative brief / script for the video. */\n prompt: string;\n /** Explicit registry model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: VideoTier | string;\n /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */\n images_list?: string[];\n /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */\n video_files?: string[];\n /** e.g. \"16:9\", \"9:16\", \"1:1\". Default \"16:9\". */\n aspect_ratio?: string;\n /** Duration in seconds (must be within the model's durationRange). */\n duration?: number;\n /** e.g. \"720p\" | \"1080p\". Default \"720p\". */\n resolution?: string;\n /** Bake an ElevenLabs voiceover into the render (requires `narration`). */\n generate_audio?: boolean;\n /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */\n narration?: string;\n}\n\n/** Returned when a video job is created (HTTP 202). */\nexport interface VideoTaskCreated {\n taskId: string;\n status: \"queued\";\n}\n\nexport type VideoTaskStatus =\n | \"queued\"\n | \"rendering\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A video job snapshot, as returned by `videos.getTask`. */\nexport interface VideoTask {\n taskId: string;\n status: VideoTaskStatus;\n progress?: {\n current: number;\n total: number;\n message?: string;\n };\n /** Served media path (e.g. /generated/video-….mp4) once completed. */\n outputUrl?: string;\n mime?: string;\n ext?: string;\n /** Actual rendered duration in seconds. */\n durationSec?: number;\n error?: string;\n model?: string;\n tier?: string;\n latencyMs?: number;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a video job. */\nexport interface VideoWaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest job snapshot. */\n onTick?: (task: VideoTask) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Audio — text-to-speech\n// ---------------------------------------------------------------------------\n\n/** Input for `audio.textToSpeech`. */\nexport interface TtsInput {\n /** Text to synthesize (max 3000 chars). */\n text: string;\n /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */\n voiceId?: string;\n /** Voice stability 0..1 (default 0.5). */\n stability?: number;\n /** Similarity boost 0..1 (default 0.75). */\n similarityBoost?: number;\n}\n\n/** Result of `audio.textToSpeech`. */\nexport interface TtsResult {\n /** Served audio path (e.g. /generated/tts-….mp3). */\n url: string;\n voiceId: string;\n modelId: string;\n bytes: number;\n latencyMs: number;\n}\n\n/** A single ElevenLabs voice as returned by `audio.voices`. */\nexport interface VoiceInfo {\n id: string;\n name: string;\n}\n\n/** Result of `audio.voices`. */\nexport interface VoicesResult {\n voices: VoiceInfo[];\n /** \"live\" = fetched from the provider; \"none\" = no provider key configured. */\n source: \"live\" | \"none\";\n note?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Files — media uploads\n// ---------------------------------------------------------------------------\n\n/** Result of `files.upload`. */\nexport interface UploadedFile {\n /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */\n url: string;\n filename: string;\n size: number;\n contentType: string;\n}\n\n/** Options for `files.upload`. */\nexport interface FileUploadOptions {\n /** Override the stored display name (extension is kept from the file). */\n filename?: string;\n /**\n * Coarse progress callback. Fetch does not expose upload byte progress, so this\n * reports 0 at start and 100 on completion.\n */\n onProgress?: (percent: number) => void;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgBO,IAAM,UAAN,MAAM,iBAAgB,MAAM;AAAA,EAQjC,YAAY,SAAiB,OAAuF,EAAE,MAAM,iBAAiB,GAAG;AAC9I,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,OAAO,KAAK;AACjB,SAAK,SAAS,KAAK,SAAS;AAC5B,SAAK,MAAM,KAAK,SAAS;AACzB,SAAK,UAAU,KAAK;AAEpB,WAAO,eAAe,MAAM,SAAQ,SAAS;AAAA,EAC/C;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK,SAAS,kBAAkB,KAAK,SAAS,eAAe,KAAK,WAAW,OAAO,KAAK,WAAW;AAAA,EAC7G;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,iBAA0B;AAC5B,WAAO,KAAK,SAAS;AAAA,EACvB;AACF;AAGO,SAAS,eAAe,QAA2C;AACxE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,UAAU,MAAM,mBAAmB;AAAA,EAC9C;AACF;AASO,SAAS,YAAY,QAAgB,MAA0B,KAA8B;AAClG,MAAI,SAAiC;AACrC,MAAI,MAAM;AACR,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,IAAI;AACzB,UAAI,KAAK,OAAO,MAAM,SAAU,UAAS;AAAA,IAC3C,QAAQ;AACN,eAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ;AACxB,MAAI;AACJ,MAAI;AACJ,MAAI,OAAO,YAAY,UAAU;AAC/B,cAAU;AAAA,EACZ,WAAW,WAAW,OAAO,YAAY,UAAU;AACjD,WAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AACzD,cAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAAA,EACpE;AACA,MAAI,CAAC,KAAM,QAAO,eAAe,MAAM;AACvC,MAAI,CAAC,QAAS,YAAW,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU,WAAc,8BAA8B,MAAM;AAElI,SAAO,IAAI,QAAQ,SAAS,EAAE,QAAQ,MAAM,SAAS,KAAK,SAAS,UAAU,OAAU,CAAC;AAC1F;AAGO,SAAS,eAAe,OAAgB,KAA8B;AAC3E,QAAM,UAAU,aAAa,KAAK;AAClC,MAAI,SAAS;AACX,WAAO,IAAI,QAAQ,mBAAmB,EAAE,MAAM,WAAW,SAAS,IAAI,CAAC;AAAA,EACzE;AACA,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,SAAO,IAAI,QAAQ,kBAAkB,GAAG,IAAI,EAAE,MAAM,WAAW,SAAS,KAAK,SAAS,MAAM,CAAC;AAC/F;AAEA,SAAS,aAAa,OAAyB;AAC7C,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,gBAAgB,EAAE,SAAS,UAAW,QAAO;AAAA,EAC9D;AACA,SAAO;AACT;AAGO,SAAS,aAAsB;AACpC,SAAO,IAAI,QAAQ,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAC7D;AAGO,SAAS,aAAa,WAA4B;AACvD,SAAO,IAAI,QAAQ,mBAAmB,SAAS,MAAM,EAAE,MAAM,UAAU,CAAC;AAC1E;;;ACjGO,SAAS,gBAAgB,MAAmC;AACjE,QAAM,EAAE,QAAQ,SAAS,UAAU,IAAI;AAEvC,SAAO;AAAA,IACL,MAAM,KAAQ,QAAgB,MAAc,UAA8B,CAAC,GAAG;AAC5E,YAAM,MAAM,MAAM,QAAQ,QAAQ,MAAM,OAAO;AAC/C,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,OAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AACzE,aAAO,OAAU,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,IACjD;AAAA,IAEA,MAAM,KAAQ,MAAc,SAA6B;AACvD,YAAM,MAAM,MAAM,YAAY,MAAM,OAAO;AAC3C,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,OAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,QAAQ,KAAK,IAAI,IAAI,CAAC;AACjF,aAAO,OAAU,MAAM,EAAE,QAAQ,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,IACzD;AAAA,IAEA,MAAM,OAAO,QAAQ,MAAM,UAAU,CAAC,GAAG;AACvC,YAAM,MAAM,MAAM,QAAQ,QAAQ,MAAM;AAAA,QACtC,GAAG;AAAA,QACH,SAAS,EAAE,QAAQ,qBAAqB,GAAI,QAAQ,WAAW,CAAC,EAAG;AAAA,MACrE,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,MAAS;AACnD,cAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,MAC9D;AACA,YAAM,SAAS,IAAI,QAAQ,IAAI,cAAc,KAAK,IAAI,YAAY;AAClE,UAAI,CAAC,MAAM,SAAS,mBAAmB,GAAG;AAExC,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,MAAS;AACnD,cAAM,IAAI,QAAQ,uCAAuC,SAAS,SAAS,KAAK;AAAA,UAC9E,QAAQ,IAAI;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,EAAE,QAAQ,KAAK,IAAI,IAAI;AAAA,UAChC,SAAS,UAAU,IAAI;AAAA,QACzB,CAAC;AAAA,MACH;AACA,UAAI,CAAC,IAAI,KAAM,OAAM,IAAI,QAAQ,wCAAwC,EAAE,MAAM,WAAW,SAAS,EAAE,QAAQ,KAAK,IAAI,IAAI,EAAE,CAAC;AAC/H,aAAO,IAAI;AAAA,IACb;AAAA,EACF;AAEA,WAAS,QAAQ,QAAgB,MAAc,SAAgD;AAC7F,UAAM,MAAM,SAAS,SAAS,MAAM,QAAQ,KAAK;AACjD,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,MAAM;AAAA,MAC/B,QAAQ;AAAA,MACR,GAAI,QAAQ,SAAS,SAAY,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,MAC3E,GAAI,QAAQ,WAAW,CAAC;AAAA,IAC1B;AACA,WAAO,UAAU,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,MAClE,QAAQ,QAAQ;AAAA,IAClB,CAAC,EAAE,MAAM,CAAC,QAAQ;AAChB,YAAM,eAAe,KAAK,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,WAAS,YAAY,MAAc,SAAgD;AACjF,UAAM,MAAM,SAAS,SAAS,IAAI;AAElC,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,MAAM;AAAA,MAC/B,QAAQ;AAAA,MACR,GAAI,QAAQ,WAAW,CAAC;AAAA,IAC1B;AACA,WAAO,UAAU,KAAK;AAAA,MACpB,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,IAClB,CAAC,EAAE,MAAM,CAAC,QAAQ;AAChB,YAAM,eAAe,KAAK,EAAE,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AACF;AAEA,SAAS,OAAU,MAAc,KAA2C;AAC1E,QAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,UAAU,OAAO,WAAW,YAAY,QAAS,QAAoC;AACvF,UAAM,MAAM;AACZ,QAAI,IAAI,OAAO,KAAM,QAAO,IAAI;AAEhC,UAAM,IAAI,QAAQ,IAAI,OAAO,WAAW,kBAAkB;AAAA,MACxD,MAAO,IAAI,OAAO,QAAyB;AAAA,MAC3C,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,UAAU,MAAwB;AACzC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,SAAS,SAAiB,MAAc,OAA6D;AACnH,QAAM,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACvC,QAAM,IAAI,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAChD,MAAI,MAAM,GAAG,IAAI,GAAG,CAAC;AACrB,MAAI,OAAO;AACT,UAAM,SAAS,IAAI,gBAAgB;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAI,UAAU,UAAa,UAAU,KAAM,QAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAC1E;AACA,UAAM,KAAK,OAAO,SAAS;AAC3B,QAAI,GAAI,QAAO,IAAI,EAAE;AAAA,EACvB;AACA,SAAO;AACT;AAGO,SAAS,aAAa,KAAqB;AAChD,SAAO,IAAI,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACtC;;;ACvIA,gBAAuB,cACrB,MACA,OAAoB,CAAC,GACoB;AACzC,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,MAAI,YAAsB,CAAC;AAG3B,QAAM,UAAU,MAAM;AACpB,SAAK,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACrC;AACA,MAAI,KAAK,QAAQ;AACf,QAAI,KAAK,OAAO,SAAS;AACvB,YAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpC;AAAA,IACF;AACA,SAAK,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC/D;AAEA,QAAM,WAAW,MAAuB;AACtC,QAAI,UAAU,WAAW,EAAG,QAAO;AACnC,UAAM,OAAO,UAAU,KAAK,IAAI;AAChC,gBAAY,CAAC;AACb,WAAO,EAAE,KAAK;AAAA,EAChB;AAEA,QAAM,cAAc,CAAC,SAAkC;AACrD,QAAI,SAAS,GAAI,QAAO,SAAS;AACjC,QAAI,KAAK,WAAW,GAAG,EAAG,QAAO;AACjC,QAAI,KAAK,WAAW,OAAO,GAAG;AAC5B,UAAI,QAAQ,KAAK,MAAM,CAAC;AACxB,UAAI,MAAM,WAAW,GAAG,EAAG,SAAQ,MAAM,MAAM,CAAC;AAChD,gBAAU,KAAK,KAAK;AACpB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,MAAI;AACF,eAAS;AACP,UAAI,KAAK,QAAQ,QAAS;AAC1B,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,UAAI,IAAI,eAAe,MAAM;AAC7B,aAAO,MAAM,MAAM;AACjB,cAAM,KAAK,YAAY,EAAE,IAAI;AAC7B,YAAI,IAAI;AACN,cAAI,cAAc,GAAG,KAAK,KAAK,MAAM,SAAU;AAC/C,gBAAM;AAAA,QACR;AACA,iBAAS,EAAE;AACX,YAAI,eAAe,MAAM;AAAA,MAC3B;AAAA,IACF;AAGA,cAAU,QAAQ,OAAO;AACzB,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,KAAK,YAAY,MAAM;AAC7B,UAAI,MAAM,EAAE,cAAc,GAAG,KAAK,KAAK,MAAM,UAAW,OAAM;AAAA,IAChE;AAEA,UAAM,OAAO,SAAS;AACtB,QAAI,QAAQ,EAAE,cAAc,KAAK,KAAK,KAAK,MAAM,UAAW,OAAM;AAAA,EACpE,UAAE;AACA,QAAI,KAAK,OAAQ,MAAK,OAAO,oBAAoB,SAAS,OAAO;AACjE,QAAI;AACF,aAAO,YAAY;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAGA,SAAS,eAAe,KAAoD;AAC1E,QAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,QAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,MAAI,MAAM;AACV,MAAI,UAAU;AACd,MAAI,OAAO,OAAO,OAAO,MAAM,KAAK,KAAK;AACvC,UAAM;AACN,cAAU;AAAA,EACZ,WAAW,OAAO,IAAI;AACpB,UAAM;AACN,cAAU,IAAI,KAAK,CAAC,MAAM,OAAO,IAAI;AAAA,EACvC;AACA,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO,EAAE,MAAM,IAAI,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,MAAM,MAAM,OAAO,EAAE;AACnE;AAGO,SAAS,aAA0B,MAAwB;AAChE,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,MAAM,YAAY,SAAU,QAAO;AACnD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AChIA,IAAM,yBAAyB,oBAAI,IAAI,CAAC,aAAa,UAAU,WAAW,CAAC;AAEpE,SAAS,qBAAqB,QAAyB;AAC5D,SAAO,uBAAuB,IAAI,MAAM;AAC1C;AAgBA,eAAe,kBACb,eACA,YACA,QACA,MACY;AACZ,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,gBAAgB,KAAK,iBAAiB;AAC5C,QAAM,SAAS,KAAK;AACpB,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI,QAAQ;AAEZ,aAAS;AACP,QAAI,QAAQ,QAAS,OAAM,WAAW;AACtC,QAAI,KAAK,cAAc,UAAa,KAAK,IAAI,IAAI,aAAa,KAAK,WAAW;AAC5E,YAAM,aAAa,KAAK,SAAS;AAAA,IACnC;AAEA,UAAM,WAAW,MAAM,cAAc,MAAM;AAC3C,aAAS,QAAQ;AACjB,QAAI,WAAW,QAAQ,EAAG,QAAO;AAGjC,QAAI,KAAK,cAAc,UAAa,KAAK,IAAI,IAAI,aAAa,KAAK,WAAW;AAC5E,YAAM,aAAa,KAAK,SAAS;AAAA,IACnC;AAEA,UAAM,MAAM,OAAO,MAAM;AACzB,YAAQ,KAAK,IAAI,eAAe,KAAK,MAAM,QAAQ,GAAG,CAAC;AAAA,EACzD;AACF;AAUO,IAAM,aAAN,MAAiB;AAAA,EACtB,YACmB,WACD,QAChB;AAFiB;AACD;AAAA,EACf;AAAA;AAAA,EAGH,IAAI,QAAqC;AACvC,WAAO,KAAK,UAAU,KAAW,OAAO,iBAAiB,KAAK,MAAM,IAAI,EAAE,OAAO,CAAC;AAAA,EACpF;AAAA;AAAA,EAGA,KAAK,QAAqC;AACxC,WAAO,KAAK,IAAI,MAAM;AAAA,EACxB;AAAA;AAAA,EAGA,MAAM,KAAK,OAAoB,CAAC,GAAkB;AAChD,WAAO;AAAA,MACL,CAAC,WAAW,KAAK,IAAI,MAAM;AAAA,MAC3B,CAAC,SAAS,qBAAqB,KAAK,MAAM;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACmB,WACD,QAChB;AAFiB;AACD;AAAA,EACf;AAAA;AAAA,EAGH,IAAI,QAA0C;AAC5C,WAAO,KAAK,UAAU,KAAgB,OAAO,uBAAuB,mBAAmB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EACnH;AAAA;AAAA,EAGA,KAAK,QAA0C;AAC7C,WAAO,KAAK,IAAI,MAAM;AAAA,EACxB;AAAA;AAAA,EAGA,MAAM,KAAK,OAAyB,CAAC,GAAuB;AAC1D,WAAO;AAAA,MACL,CAAC,WAAW,KAAK,IAAI,MAAM;AAAA,MAC3B,CAAC,SAAS,qBAAqB,KAAK,MAAM;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,MAAM,IAAY,QAAqC;AAC9D,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,QAAI,QAAQ,SAAS;AACnB,aAAO,WAAW,CAAC;AACnB;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ;AACR,cAAQ;AAAA,IACV,GAAG,EAAE;AACL,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,cAAQ;AACR,aAAO,WAAW,CAAC;AAAA,IACrB;AACA,UAAM,UAAU,MAAM;AACpB,UAAI,OAAQ,QAAO,oBAAoB,SAAS,OAAO;AAAA,IACzD;AACA,QAAI,OAAQ,QAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EACtE,CAAC;AACH;;;AC3GO,IAAM,mBAAmB;AAYzB,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAE5C,MAA0B;AACxB,WAAO,KAAK,EAAE,KAAgB,OAAO,mBAAmB;AAAA,EAC1D;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,OAAiC;AAC/B,WAAO,KAAK,EAAE,KAAsB,OAAO,gBAAgB;AAAA,EAC7D;AAAA;AAAA,EAGA,IAAI,SAAuC;AACzC,WAAO,KAAK,EAAE,KAAkB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,EAAE;AAAA,EACxF;AAAA;AAAA,EAGA,aAAa,SAA8C;AACzD,WAAO,KAAK,EAAE,KAAyB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,eAAe;AAAA,EAC5G;AAAA;AAAA,EAGA,cAAc,SAAiB,OAAyD;AACtF,WAAO,KAAK,EAAE,KAA0B,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,qBAAqB;AAAA,MAChH,MAAM,EAAE,OAAO,MAAM,OAAO,QAAQ,MAAM,UAAU,CAAC,EAAE;AAAA,IACzD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KAAK,OAAuC;AAC1C,WAAO,KAAK,EAAE,KAAiB,QAAQ,uBAAuB,EAAE,MAAM,MAAM,CAAC;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,OAAkB,OAAsB,CAAC,GAAmC;AACrF,WAAO,KAAK,eAAe,OAAO,IAAI;AAAA,EACxC;AAAA;AAAA,EAGA,QAAQ,SAAiB,SAAwB,CAAC,GAAyB;AACzE,WAAO,KAAK,EAAE,KAAkB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,aAAa;AAAA,MAC/F,OAAO,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,eAAe,OAAkB,MAAsD;AACpG,UAAM,OAAO,MAAM,KAAK,EAAE,OAAO,QAAQ,8BAA8B,EAAE,MAAM,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC3G,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,qBAAiB,MAAM,cAAc,MAAM,EAAE,QAAQ,KAAK,OAAO,CAAC,GAAG;AACnE,YAAM,UAAU,aAA+G,GAAG,IAAI;AACtI,UAAI,CAAC,QAAS;AACd,YAAM,QAAQ,QAAQ,UAAU,CAAC,GAAG;AACpC,YAAM,OAAO,OAAO,OAAO,YAAY,WAAW,MAAM,UAAU;AAClE,YAAM,SACJ,OAAO,OAAO,cAAc,WACxB,MAAM,YACN,OAAO,OAAO,sBAAsB,WAClC,MAAM,oBACN;AACR,UAAI,KAAM,YAAW;AACrB,UAAI,OAAQ,cAAa;AACzB,UAAI,QAAQ,OAAQ,OAAM,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,OAAO;AAAA,IAC9E;AACA,UAAM,EAAE,MAAM,QAAQ,SAAS,WAAW,aAAa,OAAU;AAAA,EACnE;AACF;AAGO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,IAAI,YAAoB,QAA0B,CAAC,GAA8B;AAC/E,WAAO,KAAK,EAAE,KAAuB,QAAQ,qBAAqB,mBAAmB,UAAU,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,EACzH;AAAA;AAAA,EAGA,OAAO,OAAqC;AAC1C,WAAO,KAAK,EAAE,KAAkB,OAAO,yBAAyB,mBAAmB,KAAK,CAAC,EAAE;AAAA,EAC7F;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,OAAO,OAA8C;AACnD,WAAO,KAAK,EAAE,KAAkB,QAAQ,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAAA,EAC1E;AAAA;AAAA,EAGA,IAAI,QAAgB,QAAqC;AACvD,WAAO,KAAK,EAAE,KAAW,OAAO,iBAAiB,mBAAmB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,OAAO,QAA4B;AACjC,WAAO,IAAI,WAAW,KAAK,GAAG,MAAM;AAAA,EACtC;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,aAAyC;AACvC,WAAO,KAAK,EAAE,KAAwB,OAAO,uBAAuB;AAAA,EACtE;AAAA;AAAA,EAGA,SAAS,SAAiB,OAAyD;AACjF,WAAO,KAAK,EAAE,KAA0B,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;AAAA,EACzH;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,aAAyC;AACvC,WAAO,KAAK,EAAE,KAAwB,OAAO,uBAAuB;AAAA,EACtE;AAAA;AAAA,EAGA,SAAS,SAAiB,OAAsD;AAC9E,WAAO,KAAK,EAAE,KAAuB,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;AAAA,EACtH;AAAA;AAAA,EAGA,QAAQ,QAAgB,QAA0C;AAChE,WAAO,KAAK,EAAE,KAAgB,OAAO,uBAAuB,mBAAmB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EACtG;AAAA;AAAA,EAGA,WAAW,QAAoC;AAC7C,WAAO,KAAK,EAAE,KAAgB,UAAU,uBAAuB,mBAAmB,MAAM,CAAC,EAAE;AAAA,EAC7F;AAAA;AAAA,EAGA,OAAO,QAAiC;AACtC,WAAO,IAAI,gBAAgB,KAAK,GAAG,MAAM;AAAA,EAC3C;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,SAAgC;AAC9B,WAAO,KAAK,EAAE,KAAmB,OAAO,sBAAsB;AAAA,EAChE;AAAA;AAAA,EAGA,aAAa,SAAiB,OAAqC;AACjE,WAAO,KAAK,EAAE,KAAgB,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,EAC5G;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,MAAM,OAAO,MAAY,OAA0B,CAAC,GAA0B;AAC5E,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,KAAK,aAAa,QAAW;AAC/B,WAAK,OAAO,QAAQ,MAAM,KAAK,QAAQ;AAAA,IACzC,OAAO;AACL,WAAK,OAAO,QAAQ,IAAI;AAAA,IAC1B;AAEA,SAAK,aAAa,CAAC;AACnB,UAAM,SAAS,MAAM,KAAK,EAAE,KAAmB,iBAAiB,EAAE,KAAK,CAAC;AACxE,SAAK,aAAa,GAAG;AACrB,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAqC;AAC5C,MAAI;AACF,QAAI,OAAO,YAAY,eAAe,SAAS,KAAK;AAClD,aAAO,QAAQ,IAAI,eAAe;AAAA,IACpC;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAOO,IAAM,WAAN,MAAe;AAAA,EAapB,YAAY,MAAuB;AACjC,QAAI,CAAC,QAAQ,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,WAAW,GAAG;AACxE,YAAM,IAAI,QAAQ,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAAA,IACtE;AACA,SAAK,OAAO,aAAa,KAAK,WAAW,eAAe,KAAK,gBAAgB;AAC7E,UAAM,aAAa,KAAK,SAAS,WAAW,OAAO,KAAK,UAAU;AAClE,SAAK,YAAY,gBAAgB,EAAE,QAAQ,KAAK,QAAQ,SAAS,KAAK,MAAM,UAAU,CAAC;AACvF,SAAK,YAAY,IAAI,aAAa,KAAK,SAAS;AAChD,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,YAAY,IAAI,aAAa,KAAK,SAAS;AAChD,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AACxC,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AACxC,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;;;AC5RO,IAAM,kBAAkB;AAAA,EAC7B,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,eAAe;AACjB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/sse.ts","../src/task.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["/**\n * ql-agent-sdk — TypeScript SDK for the Quanton Labs agent platform API (v1).\n *\n * Quick start:\n * import { QLClient } from \"ql-agent-sdk\";\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY! });\n * const agents = await ql.agents.list();\n */\n\nexport { QLClient, WorkspaceApi, AgentsApi, WorkflowsApi, TasksApi, ImagesApi, VideosApi, AudioApi, FilesApi, DEFAULT_BASE_URL } from \"./client.js\";\nexport type { QLClientOptions } from \"./client.js\";\n\nexport { QLError } from \"./errors.js\";\nexport type { QLErrorContext } from \"./errors.js\";\n\nexport { TaskHandle, VideoTaskHandle, isTerminalTaskStatus } from \"./task.js\";\n\nexport { API_ERROR_CODES } from \"./types.js\";\nexport type {\n ApiErrorCode,\n CreateKeyInput,\n CreateKeyResult,\n DeleteKeyResult,\n DiscardedKey,\n MintedKey,\n ChatMessage,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n StreamOptions,\n MessageItem,\n HistoryPage,\n HistoryParams,\n AgentSummary,\n AgentListResult,\n CapParamKind,\n CapabilityParam,\n CapabilityTemplate,\n CapabilityInfo,\n AgentDetail,\n CapabilitiesResult,\n RunCapabilityInput,\n CapabilityResult,\n RunCapabilityResult,\n Workspace,\n WorkflowRunInput,\n WorkflowRunStart,\n WorkflowRunStatus,\n WorkflowRun,\n ImageTier,\n ImagePricingEntry,\n ImageModelInfo,\n ImageModelsResult,\n ImageReferenceInput,\n ImageGenerateInput,\n GeneratedImage,\n ImageUsage,\n ImageGenerateResult,\n TaskPriority,\n TaskCreateInput,\n TaskCreated,\n TaskStatus,\n Task,\n WaitOptions,\n VideoTier,\n VideoPricingEntry,\n VideoModelInfo,\n VideoModelsResult,\n VideoGenerateInput,\n VideoTaskCreated,\n VideoTaskStatus,\n VideoTask,\n VideoWaitOptions,\n TtsInput,\n TtsResult,\n VoiceInfo,\n VoicesResult,\n UploadedFile,\n FileUploadOptions,\n} from \"./types.js\";\n","import type { ApiErrorCode } from \"./types.js\";\n\nexport interface QLErrorContext {\n method?: string;\n url?: string;\n}\n\n/**\n * Error thrown by the SDK for any failed API interaction.\n *\n * - `status`: HTTP status code (when the failure came from an HTTP response).\n * - `code`: stable API error code when provided by the backend, otherwise a\n * synthesized one derived from the status, or a synthetic transport\n * code such as \"aborted\" / \"timeout\" / \"network\".\n * - `message`: human-readable description. The API key is never included.\n */\nexport class QLError extends Error {\n readonly status?: number;\n readonly code: string;\n readonly method?: string;\n readonly url?: string;\n /** The raw parsed error body (if any), for advanced inspection. */\n readonly details?: unknown;\n\n constructor(message: string, opts: { status?: number; code: string; context?: QLErrorContext; details?: unknown } = { code: \"internal_error\" }) {\n super(message);\n this.name = \"QLError\";\n this.status = opts.status;\n this.code = opts.code;\n this.method = opts.context?.method;\n this.url = opts.context?.url;\n this.details = opts.details;\n // Restore prototype chain (required when targeting ES5-ish runtimes).\n Object.setPrototypeOf(this, QLError.prototype);\n }\n\n /** True for 401/403 or unauthorized/forbidden codes. */\n get isAuthError(): boolean {\n return this.code === \"unauthorized\" || this.code === \"forbidden\" || this.status === 401 || this.status === 403;\n }\n\n /** True when the request was aborted by the caller. */\n get isAborted(): boolean {\n return this.code === \"aborted\";\n }\n\n /** True when a wait() call exceeded its timeout. */\n get isTimeout(): boolean {\n return this.code === \"timeout\";\n }\n\n /** True for transient network failures (no HTTP response received). */\n get isNetworkError(): boolean {\n return this.code === \"network\";\n }\n}\n\n/** Map an HTTP status to a stable API error code when the body has none. */\nexport function codeFromStatus(status: number): ApiErrorCode | \"conflict\" {\n switch (status) {\n case 400:\n return \"validation_error\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 409:\n return \"conflict\";\n default:\n return status >= 500 ? \"internal_error\" : \"validation_error\";\n }\n}\n\ninterface ParsedErrorBody {\n ok?: boolean;\n error?: { code?: string; message?: string } | string;\n message?: string;\n}\n\n/** Build a QLError from a non-2xx HTTP response. Never includes the API key. */\nexport function toHttpError(status: number, text: string | undefined, ctx: QLErrorContext): QLError {\n let parsed: ParsedErrorBody | null = null;\n if (text) {\n try {\n const j = JSON.parse(text);\n if (j && typeof j === \"object\") parsed = j as ParsedErrorBody;\n } catch {\n parsed = null;\n }\n }\n\n const bodyErr = parsed?.error;\n let code: string | undefined;\n let message: string | undefined;\n if (typeof bodyErr === \"string\") {\n message = bodyErr;\n } else if (bodyErr && typeof bodyErr === \"object\") {\n code = typeof bodyErr.code === \"string\" ? bodyErr.code : undefined;\n message = typeof bodyErr.message === \"string\" ? bodyErr.message : undefined;\n }\n if (!code) code = codeFromStatus(status);\n if (!message) message = (typeof parsed?.message === \"string\" ? parsed.message : undefined) ?? `Request failed with status ${status}`;\n\n return new QLError(message, { status, code, context: ctx, details: parsed ?? undefined });\n}\n\n/** Wrap a low-level fetch/network failure (no HTTP response). */\nexport function toNetworkError(cause: unknown, ctx: QLErrorContext): QLError {\n const aborted = isAbortCause(cause);\n if (aborted) {\n return new QLError(\"Request aborted\", { code: \"aborted\", context: ctx });\n }\n const msg = cause instanceof Error ? cause.message : String(cause);\n return new QLError(`Network error: ${msg}`, { code: \"network\", context: ctx, details: cause });\n}\n\nfunction isAbortCause(cause: unknown): boolean {\n if (!cause) return false;\n if (typeof cause === \"object\") {\n const c = cause as { name?: string; type?: string };\n if (c.name === \"AbortError\" || c.type === \"aborted\") return true;\n }\n return false;\n}\n\n/** Build an abort error for wait()/stream cancellation. */\nexport function abortError(): QLError {\n return new QLError(\"Operation aborted\", { code: \"aborted\" });\n}\n\n/** Build a timeout error for wait(). */\nexport function timeoutError(timeoutMs: number): QLError {\n return new QLError(`Timed out after ${timeoutMs}ms`, { code: \"timeout\" });\n}\n","import { QLError, toHttpError, toNetworkError } from \"./errors.js\";\nimport type { ApiErrorCode } from \"./types.js\";\n\nexport interface TransportOptions {\n apiKey: string;\n baseUrl: string;\n fetchImpl: typeof fetch;\n}\n\nexport interface JsonRequestOptions {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport interface FormRequestOptions {\n form: FormData;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * Internal transport used by the API namespaces. Keeps the API key inside a\n * closure (never exposed) and normalizes responses/errors for the caller.\n */\nexport interface Transport {\n /** Perform a JSON request and return the unwrapped `data` payload. */\n json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;\n /** Perform a multipart/form-data request and return the unwrapped `data` payload. */\n form<T>(path: string, opts: FormRequestOptions): Promise<T>;\n /**\n * Perform a request expected to stream SSE. Returns the response body stream\n * after verifying a 2xx + text/event-stream; throws QLError otherwise.\n */\n stream(method: string, path: string, opts?: JsonRequestOptions & { acceptStream?: boolean }): Promise<ReadableStream<Uint8Array>>;\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n const { apiKey, baseUrl, fetchImpl } = opts;\n\n return {\n async json<T>(method: string, path: string, reqOpts: JsonRequestOptions = {}) {\n const res = await doFetch(method, path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });\n return unwrap<T>(text, { method, url: res.url });\n },\n\n async form<T>(path: string, reqOpts: FormRequestOptions) {\n const res = await doFormFetch(path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method: \"POST\", url: res.url });\n return unwrap<T>(text, { method: \"POST\", url: res.url });\n },\n\n async stream(method, path, reqOpts = {}) {\n const res = await doFetch(method, path, {\n ...reqOpts,\n headers: { accept: \"text/event-stream\", ...(reqOpts.headers ?? {}) },\n });\n if (!res.ok) {\n const text = await res.text().catch(() => undefined);\n throw toHttpError(res.status, text, { method, url: res.url });\n }\n const ctype = (res.headers.get(\"content-type\") || \"\").toLowerCase();\n if (!ctype.includes(\"text/event-stream\")) {\n // The endpoint returned a non-SSE body (e.g. an error envelope). Surface it.\n const text = await res.text().catch(() => undefined);\n throw new QLError(`Expected text/event-stream but got \"${ctype || \"unknown\"}\"`, {\n status: res.status,\n code: \"internal_error\",\n context: { method, url: res.url },\n details: safeParse(text),\n });\n }\n if (!res.body) throw new QLError(\"Response has no readable body stream\", { code: \"network\", context: { method, url: res.url } });\n return res.body;\n },\n };\n\n function doFetch(method: string, path: string, reqOpts: JsonRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path, reqOpts.query);\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method,\n headers,\n body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method, url });\n });\n }\n\n function doFormFetch(path: string, reqOpts: FormRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path);\n // No content-type header here — fetch sets the multipart boundary itself.\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method: \"POST\",\n headers,\n body: reqOpts.form,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method: \"POST\", url });\n });\n }\n}\n\nfunction unwrap<T>(text: string, ctx: { method?: string; url?: string }): T {\n const parsed = safeParse(text);\n if (parsed && typeof parsed === \"object\" && \"ok\" in (parsed as Record<string, unknown>)) {\n const env = parsed as { ok: boolean; data?: unknown; error?: { code?: string; message?: string } };\n if (env.ok === true) return env.data as T;\n // ok:false on a 2xx — treat as an application error.\n throw new QLError(env.error?.message || \"Request failed\", {\n code: (env.error?.code as ApiErrorCode) || \"internal_error\",\n context: ctx,\n details: env,\n });\n }\n // Non-enveloped payload (legacy shapes): return as-is.\n return parsed as T;\n}\n\nfunction safeParse(text?: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Join base + path and append a query string (skipping undefined values). */\nexport function buildUrl(baseUrl: string, path: string, query?: Record<string, string | number | undefined>): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const p = path.startsWith(\"/\") ? path : `/${path}`;\n let url = `${base}${p}`;\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n }\n return url;\n}\n\n/** Normalize a base URL: trim whitespace and drop any trailing slash. */\nexport function normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n","/**\n * Minimal, dependency-free Server-Sent Events reader built on Web Streams.\n *\n * Handles the cases that commonly break naive parsers:\n * - a `data:` line split across two TCP chunks (chunk boundaries)\n * - multiple events arriving in a single chunk\n * - both CRLF and LF line endings (and lone CR)\n * - a final event that is not terminated by a trailing newline\n * - the `[DONE]` terminator\n * - abort signals\n */\n\nexport interface SSEEvent {\n /** The concatenated `data:` payload for this event (trimmed of the leading space). */\n data: string;\n}\n\ninterface ReadOptions {\n signal?: AbortSignal;\n /** When true, stop after the first `[DONE]` data value. Default true. */\n stopOnDone?: boolean;\n}\n\n/**\n * Read raw SSE events from a `ReadableStream<Uint8Array>`.\n * Yields one object per event with its combined `data` payload.\n */\nexport async function* readSSEEvents(\n body: ReadableStream<Uint8Array>,\n opts: ReadOptions = {},\n): AsyncGenerator<SSEEvent, void, unknown> {\n const stopOnDone = opts.stopOnDone ?? true;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let dataLines: string[] = [];\n\n // Abort wiring: cancel the underlying stream promptly when the signal fires.\n const onAbort = () => {\n void reader.cancel().catch(() => {});\n };\n if (opts.signal) {\n if (opts.signal.aborted) {\n await reader.cancel().catch(() => {});\n return;\n }\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n const dispatch = (): SSEEvent | null => {\n if (dataLines.length === 0) return null;\n const data = dataLines.join(\"\\n\");\n dataLines = [];\n return { data };\n };\n\n const processLine = (line: string): SSEEvent | null => {\n if (line === \"\") return dispatch(); // blank line = event boundary\n if (line.startsWith(\":\")) return null; // comment\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) value = value.slice(1);\n dataLines.push(value);\n return null;\n }\n // Ignore event:/id:/retry: and unknown fields.\n return null;\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let s = splitFirstLine(buffer);\n while (s !== null) {\n const ev = processLine(s.line);\n if (ev) {\n if (stopOnDone && ev.data.trim() === \"[DONE]\") return;\n yield ev;\n }\n buffer = s.rest;\n s = splitFirstLine(buffer);\n }\n }\n\n // Flush any bytes still held by the decoder.\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const ev = processLine(buffer);\n if (ev && !(stopOnDone && ev.data.trim() === \"[DONE]\")) yield ev;\n }\n // Flush a final event that had no terminating blank line.\n const tail = dispatch();\n if (tail && !(stopOnDone && tail.data.trim() === \"[DONE]\")) yield tail;\n } finally {\n if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n try {\n reader.releaseLock();\n } catch {\n /* already released */\n }\n }\n}\n\n/** Split the first complete line (LF, CRLF, or lone CR) out of `buf`. */\nfunction splitFirstLine(buf: string): { line: string; rest: string } | null {\n const nl = buf.indexOf(\"\\n\");\n const cr = buf.indexOf(\"\\r\");\n let end = -1;\n let termLen = 0;\n if (nl !== -1 && (cr === -1 || nl < cr)) {\n end = nl;\n termLen = 1;\n } else if (cr !== -1) {\n end = cr;\n termLen = buf[cr + 1] === \"\\n\" ? 2 : 1;\n }\n if (end === -1) return null;\n return { line: buf.slice(0, end), rest: buf.slice(end + termLen) };\n}\n\n/** Parse a single SSE `data` payload as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n const trimmed = data.trim();\n if (trimmed === \"\" || trimmed === \"[DONE]\") return null;\n try {\n return JSON.parse(trimmed) as T;\n } catch {\n return null; // malformed JSON is skipped, not fatal\n }\n}\n","import type { Transport } from \"./http.js\";\nimport { abortError, timeoutError } from \"./errors.js\";\nimport type { Task, WaitOptions, VideoTask, VideoWaitOptions } from \"./types.js\";\n\n/** Statuses at which a job will not change again (shared by tasks and video jobs). */\nconst TERMINAL_TASK_STATUSES = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\nexport function isTerminalTaskStatus(status: string): boolean {\n return TERMINAL_TASK_STATUSES.has(status);\n}\n\ninterface PollOptions {\n intervalMs?: number;\n maxIntervalMs?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Shared polling loop used by TaskHandle.wait() and VideoTaskHandle.wait().\n *\n * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.\n * - Throws a QLError with code \"timeout\" if `timeoutMs` elapses first.\n * - Throws a QLError with code \"aborted\" if `signal` aborts.\n */\nasync function pollUntilTerminal<T>(\n fetchSnapshot: (signal?: AbortSignal) => Promise<T>,\n isTerminal: (snapshot: T) => boolean,\n onTick: ((snapshot: T) => void) | undefined,\n opts: PollOptions,\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? 2000;\n const maxIntervalMs = opts.maxIntervalMs ?? 15000;\n const signal = opts.signal;\n const startedAt = Date.now();\n let delay = intervalMs;\n\n for (;;) {\n if (signal?.aborted) throw abortError();\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n const snapshot = await fetchSnapshot(signal);\n onTick?.(snapshot);\n if (isTerminal(snapshot)) return snapshot;\n\n // Recompute timeout after the poll so a slow request doesn't overshoot silently.\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n await sleep(delay, signal);\n delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));\n }\n}\n\n/**\n * A handle to a background task created via `tasks.create`.\n *\n * NOTE on execution: creating a task only enqueues it. It may stay in the\n * `queued` state until an existing worker/execution mechanism processes it —\n * this SDK does not trigger execution. `wait()` simply polls until the task\n * reaches a terminal status (or you time out / abort).\n */\nexport class TaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current task snapshot (single request). */\n get(signal?: AbortSignal): Promise<Task> {\n return this.transport.json<Task>(\"GET\", `/api/v1/tasks/${this.taskId}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<Task> {\n return this.get(signal);\n }\n\n /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */\n async wait(opts: WaitOptions = {}): Promise<Task> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/**\n * A handle to a video job created via `videos.generate`.\n * Polls the video-tasks endpoint until the job reaches a terminal status.\n */\nexport class VideoTaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current job snapshot (single request). */\n get(signal?: AbortSignal): Promise<VideoTask> {\n return this.transport.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<VideoTask> {\n return this.get(signal);\n }\n\n /** Poll until the job reaches a terminal status (completed/failed/cancelled). */\n async wait(opts: VideoWaitOptions = {}): Promise<VideoTask> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/** Abort-aware sleep. Rejects with an abort error if `signal` fires first. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n };\n if (signal) signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { createTransport, normalizeUrl, type Transport } from \"./http.js\";\nimport { QLError } from \"./errors.js\";\nimport { readSSEEvents, parseSSEData } from \"./sse.js\";\nimport { TaskHandle, VideoTaskHandle } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CatalogResult,\n CapabilitiesResult,\n CreateKeyInput,\n CreateKeyResult,\n DeleteKeyResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelsResult,\n KeysResult,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n TtsInput,\n TtsResult,\n UploadedFile,\n FileUploadOptions,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n VerifyKeyResult,\n VideoGenerateInput,\n VideoModelsResult,\n VideoTask,\n VideoTaskCreated,\n VoicesResult,\n WorkspaceModelsResult,\n WorkspaceModelsUpdateInput,\n WorkspaceUpdateInput,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n\n /** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */\n getModels(): Promise<WorkspaceModelsResult> {\n return this.t.json<WorkspaceModelsResult>(\"GET\", \"/api/v1/workspace/models\");\n }\n\n /** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */\n update(input: WorkspaceUpdateInput): Promise<Workspace> {\n return this.t.json<Workspace>(\"PATCH\", \"/api/v1/workspace\", { body: input });\n }\n\n /** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */\n updateModels(input: WorkspaceModelsUpdateInput): Promise<Workspace> {\n return this.t.json<Workspace>(\"PATCH\", \"/api/v1/workspace\", { body: { config: { openrouter: input } } });\n }\n\n /** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */\n listCatalogModels(): Promise<CatalogResult> {\n return this.t.json<CatalogResult>(\"GET\", \"/api/v1/workspace/models/catalog\");\n }\n\n /** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */\n verifyOpenRouterKey(key: string, model?: string, baseUrl?: string): Promise<VerifyKeyResult> {\n return this.t.json<VerifyKeyResult>(\"POST\", \"/api/v1/workspace/models/verify\", { body: { key, model, baseUrl } });\n }\n\n /** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */\n listKeys(): Promise<KeysResult> {\n return this.t.json<KeysResult>(\"GET\", \"/api/v1/workspace/keys\");\n }\n\n /**\n * POST /api/v1/workspace/keys — mint a new API key for the workspace.\n * All expired, non-revoked keys (issued and legacy) are discarded first, so a\n * rotation is one call. The raw `secret` is returned exactly once.\n */\n createKey(input?: CreateKeyInput): Promise<CreateKeyResult> {\n return this.t.json<CreateKeyResult>(\"POST\", \"/api/v1/workspace/keys\", { body: input ?? {} });\n }\n\n /** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */\n deleteKey(keyId: string): Promise<DeleteKeyResult> {\n return this.t.json<DeleteKeyResult>(\"DELETE\", `/api/v1/workspace/keys/${encodeURIComponent(keyId)}`);\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\n/** Videos namespace (tiered video generation: submit → poll). */\nexport class VideosApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/videos/models — list tiered video models + engine availability. */\n listModels(): Promise<VideoModelsResult> {\n return this.t.json<VideoModelsResult>(\"GET\", \"/api/v1/videos/models\");\n }\n\n /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */\n generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated> {\n return this.t.json<VideoTaskCreated>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });\n }\n\n /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */\n getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */\n cancelTask(taskId: string): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"DELETE\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);\n }\n\n /** Get a handle for polling / waiting on a video job (poll(), wait()). */\n handle(taskId: string): VideoTaskHandle {\n return new VideoTaskHandle(this.t, taskId);\n }\n}\n\n/** Audio namespace (text-to-speech). */\nexport class AudioApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/audio/voices — list available TTS voices. */\n voices(): Promise<VoicesResult> {\n return this.t.json<VoicesResult>(\"GET\", \"/api/v1/audio/voices\");\n }\n\n /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */\n textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult> {\n return this.t.json<TtsResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });\n }\n}\n\n/** Files namespace (media uploads). */\nexport class FilesApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/files — upload a media file (multipart field \"file\"). */\n async upload(file: Blob, opts: FileUploadOptions = {}): Promise<UploadedFile> {\n const form = new FormData();\n if (opts.filename !== undefined) {\n form.append(\"file\", file, opts.filename);\n } else {\n form.append(\"file\", file);\n }\n // Coarse progress only: fetch does not expose upload byte progress.\n opts.onProgress?.(0);\n const result = await this.t.form<UploadedFile>(\"/api/v1/files\", { form });\n opts.onProgress?.(100);\n return result;\n }\n}\n\nfunction readEnvBaseUrl(): string | undefined {\n try {\n if (typeof process !== \"undefined\" && process?.env) {\n return process.env.QL_BASE_URL || undefined;\n }\n } catch {\n /* non-Node runtime */\n }\n return undefined;\n}\n\n/**\n * The public client. Example:\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });\n * const agents = await ql.agents.list();\n */\nexport class QLClient {\n readonly workspace: WorkspaceApi;\n readonly agents: AgentsApi;\n readonly workflows: WorkflowsApi;\n readonly tasks: TasksApi;\n readonly images: ImagesApi;\n readonly videos: VideosApi;\n readonly audio: AudioApi;\n readonly files: FilesApi;\n\n private readonly transport: Transport;\n private readonly base: string;\n\n constructor(opts: QLClientOptions) {\n if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.length === 0) {\n throw new QLError(\"apiKey is required\", { code: \"validation_error\" });\n }\n this.base = normalizeUrl(opts.baseUrl ?? readEnvBaseUrl() ?? DEFAULT_BASE_URL);\n const fetchImpl = (opts.fetch ?? globalThis.fetch).bind(globalThis);\n this.transport = createTransport({ apiKey: opts.apiKey, baseUrl: this.base, fetchImpl });\n this.workspace = new WorkspaceApi(this.transport);\n this.agents = new AgentsApi(this.transport);\n this.workflows = new WorkflowsApi(this.transport);\n this.tasks = new TasksApi(this.transport);\n this.images = new ImagesApi(this.transport);\n this.videos = new VideosApi(this.transport);\n this.audio = new AudioApi(this.transport);\n this.files = new FilesApi(this.transport);\n }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter model id override — wins over the workspace director-panel default. */\n modelId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */\n modelId?: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Videos — tiered video generation (async: submit → poll)\n// ---------------------------------------------------------------------------\n\nexport type VideoTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for a video model. */\nexport interface VideoPricingEntry {\n /** What is billed, e.g. \"output_video\" / \"voiceover\". */\n billable: string;\n /** Billing unit: per rendered second, or flat per request. */\n unit: \"second\" | \"request\";\n costUsd: number;\n}\n\n/** A tiered video-generation model as returned by `videos.listModels`. */\nexport interface VideoModelInfo {\n id: string;\n name: string;\n tier: VideoTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n /** Execution engine (e.g. \"motion-graphics\"). */\n engine: string;\n supportsProductImages: boolean;\n maxReferenceImages: number;\n supportsReferenceVideos: boolean;\n maxReferenceVideos: number;\n supportedAspectRatios: string[];\n supportedResolutions: string[];\n /** Inclusive [min, max] duration in seconds. */\n durationRange: [number, number];\n voiceoverSupport: boolean;\n pricing: {\n summary: string;\n entries: VideoPricingEntry[];\n };\n recommended: boolean;\n enabled: boolean;\n /** Runtime engine availability (render toolchain present). */\n available: boolean;\n}\n\n/** Result of `videos.listModels`. */\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n}\n\n/** Input for `videos.generate`. */\nexport interface VideoGenerateInput {\n /** The creative brief / script for the video. */\n prompt: string;\n /** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */\n modelId?: string;\n /** Explicit registry model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: VideoTier | string;\n /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */\n images_list?: string[];\n /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */\n video_files?: string[];\n /** e.g. \"16:9\", \"9:16\", \"1:1\". Default \"16:9\". */\n aspect_ratio?: string;\n /** Duration in seconds (must be within the model's durationRange). */\n duration?: number;\n /** e.g. \"720p\" | \"1080p\". Default \"720p\". */\n resolution?: string;\n /** Bake an ElevenLabs voiceover into the render (requires `narration`). */\n generate_audio?: boolean;\n /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */\n narration?: string;\n}\n\n/** Returned when a video job is created (HTTP 202). */\nexport interface VideoTaskCreated {\n taskId: string;\n status: \"queued\";\n}\n\nexport type VideoTaskStatus =\n | \"queued\"\n | \"rendering\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A video job snapshot, as returned by `videos.getTask`. */\nexport interface VideoTask {\n taskId: string;\n status: VideoTaskStatus;\n progress?: {\n current: number;\n total: number;\n message?: string;\n };\n /** Served media path (e.g. /generated/video-….mp4) once completed. */\n outputUrl?: string;\n mime?: string;\n ext?: string;\n /** Actual rendered duration in seconds. */\n durationSec?: number;\n error?: string;\n model?: string;\n tier?: string;\n latencyMs?: number;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a video job. */\nexport interface VideoWaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest job snapshot. */\n onTick?: (task: VideoTask) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Audio — text-to-speech\n// ---------------------------------------------------------------------------\n\n// ─── Workspace model configuration (director panel) ──────────────────────\n\n/** Per-role model defaults as configured in the director panel. */\nexport interface WorkspaceModelConfig {\n status: \"active\" | \"inactive\";\n /** Masked OpenRouter key — the raw key is never returned by the API. */\n keyMasked: string;\n /** Optional chat-completions base URL override (empty = public OpenRouter API). */\n baseUrl: string;\n reasoning: string;\n instruct: string;\n response: string;\n vision: string;\n image: string;\n video: string;\n /** Ordered per-role fallback model ids (max 3 each), tried on provider failure. */\n fallbacks: {\n reasoning: string[];\n instruct: string[];\n response: string[];\n vision: string[];\n image: string[];\n video: string[];\n };\n}\n\n/** Result of `workspace.getModels`. */\nexport interface WorkspaceModelsResult {\n openrouter: WorkspaceModelConfig;\n}\n\n/** Partial model-config update for `workspace.update` / `workspace.updateModels`. */\nexport interface WorkspaceModelsUpdateInput {\n status?: \"active\" | \"inactive\";\n /** Full OpenRouter API key to store/rotate. Omit to leave unchanged. */\n key?: string;\n /** Optional chat-completions base URL override (defaults to the public OpenRouter API). */\n baseUrl?: string;\n reasoning?: string;\n instruct?: string;\n response?: string;\n vision?: string;\n image?: string;\n video?: string;\n /** Ordered per-role fallback model ids (max 3 each). */\n fallbacks?: {\n reasoning?: string[];\n instruct?: string[];\n response?: string[];\n vision?: string[];\n image?: string[];\n video?: string[];\n };\n}\n\n/** Input for `workspace.update`. */\nexport interface WorkspaceUpdateInput {\n name?: string;\n config?: { openrouter?: WorkspaceModelsUpdateInput };\n}\n\n/** A single OpenRouter catalog model. */\nexport interface CatalogModel {\n id: string;\n name: string;\n contextLength: number | null;\n promptPrice: number | null;\n completionPrice: number | null;\n}\n\n/** Result of `workspace.listCatalogModels`. */\nexport interface CatalogResult {\n models: CatalogModel[];\n /** True when the upstream fetch failed and a cached snapshot was served. */\n stale?: boolean;\n}\n\n/** Result of `workspace.verifyOpenRouterKey`. */\nexport interface VerifyKeyResult {\n valid: boolean;\n error?: string;\n}\n\n/** A v1 API key with rotation metadata (hashes never leave the server). */\nexport interface ApiKeyInfo {\n _id: string;\n name: string;\n prefix: string;\n scopes: string[];\n createdAt: string | Date;\n lastUsedAt: string | Date | null;\n revokedAt: string | Date | null;\n /** When the key is auto-deleted (createdAt + lifetime). */\n rotatesAt: string | Date;\n /** Whole days remaining until rotation (0 when expired). */\n daysLeft: number;\n}\n\n/** Result of `workspace.listKeys`. */\nexport interface KeysResult {\n /** Key lifetime in days before auto-deletion. */\n lifetimeDays: number;\n keys: ApiKeyInfo[];\n}\n\n/** Input for `workspace.createKey`. */\nexport interface CreateKeyInput {\n /** Display name for the key (defaults to \"API Key\" server-side). */\n name?: string;\n}\n\n/** A freshly minted key. `secret` is the raw key — shown exactly once, never stored in plaintext. */\nexport interface MintedKey {\n id: string;\n name: string;\n prefix: string;\n secret: string;\n}\n\n/** An expired key that was discarded automatically when a new key was minted. */\nexport interface DiscardedKey {\n _id?: string;\n name: string;\n prefix: string;\n /** True when the key was embedded on the workspace document (pre-ApiKey-collection era). */\n legacy: boolean;\n}\n\n/** Result of `workspace.createKey`. */\nexport interface CreateKeyResult {\n key: MintedKey;\n /** Expired, non-revoked keys discarded as part of the rotation. */\n discarded: DiscardedKey[];\n}\n\n/** Result of `workspace.deleteKey`. */\nexport interface DeleteKeyResult {\n deleted: {\n id: string;\n name: string;\n prefix: string;\n legacy: boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n\n/** Input for `audio.textToSpeech`. */\nexport interface TtsInput {\n /** Text to synthesize (max 3000 chars). */\n text: string;\n /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */\n voiceId?: string;\n /** Voice stability 0..1 (default 0.5). */\n stability?: number;\n /** Similarity boost 0..1 (default 0.75). */\n similarityBoost?: number;\n}\n\n/** Result of `audio.textToSpeech`. */\nexport interface TtsResult {\n /** Served audio path (e.g. /generated/tts-….mp3). */\n url: string;\n voiceId: string;\n modelId: string;\n bytes: number;\n latencyMs: number;\n}\n\n/** A single ElevenLabs voice as returned by `audio.voices`. */\nexport interface VoiceInfo {\n id: string;\n name: string;\n}\n\n/** Result of `audio.voices`. */\nexport interface VoicesResult {\n voices: VoiceInfo[];\n /** \"live\" = fetched from the provider; \"none\" = no provider key configured. */\n source: \"live\" | \"none\";\n note?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Files — media uploads\n// ---------------------------------------------------------------------------\n\n/** Result of `files.upload`. */\nexport interface UploadedFile {\n /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */\n url: string;\n filename: string;\n size: number;\n contentType: string;\n}\n\n/** Options for `files.upload`. */\nexport interface FileUploadOptions {\n /** Override the stored display name (extension is kept from the file). */\n filename?: string;\n /**\n * Coarse progress callback. Fetch does not expose upload byte progress, so this\n * reports 0 at start and 100 on completion.\n */\n onProgress?: (percent: number) => void;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,8 @@ interface ChatInput {
|
|
|
56
56
|
messages: ChatMessage[];
|
|
57
57
|
/** Optional internal user id; defaults to the key's workspace when omitted. */
|
|
58
58
|
userId?: string;
|
|
59
|
+
/** Optional OpenRouter model id override — wins over the workspace director-panel default. */
|
|
60
|
+
modelId?: string;
|
|
59
61
|
/** Optional OpenRouter response-format hint (e.g. `{ type: "json_object" }`). */
|
|
60
62
|
response_format?: Record<string, unknown>;
|
|
61
63
|
}
|
|
@@ -335,6 +337,8 @@ interface ImageReferenceInput {
|
|
|
335
337
|
/** Input for `images.generate`. */
|
|
336
338
|
interface ImageGenerateInput {
|
|
337
339
|
prompt: string;
|
|
340
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
341
|
+
modelId?: string;
|
|
338
342
|
/** Explicit OpenRouter model id (wins over `tier`). */
|
|
339
343
|
model?: string;
|
|
340
344
|
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
@@ -415,6 +419,8 @@ interface VideoModelsResult {
|
|
|
415
419
|
interface VideoGenerateInput {
|
|
416
420
|
/** The creative brief / script for the video. */
|
|
417
421
|
prompt: string;
|
|
422
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
423
|
+
modelId?: string;
|
|
418
424
|
/** Explicit registry model id (wins over `tier`). */
|
|
419
425
|
model?: string;
|
|
420
426
|
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
@@ -475,6 +481,137 @@ interface VideoWaitOptions {
|
|
|
475
481
|
/** Called after each poll with the latest job snapshot. */
|
|
476
482
|
onTick?: (task: VideoTask) => void;
|
|
477
483
|
}
|
|
484
|
+
/** Per-role model defaults as configured in the director panel. */
|
|
485
|
+
interface WorkspaceModelConfig {
|
|
486
|
+
status: "active" | "inactive";
|
|
487
|
+
/** Masked OpenRouter key — the raw key is never returned by the API. */
|
|
488
|
+
keyMasked: string;
|
|
489
|
+
/** Optional chat-completions base URL override (empty = public OpenRouter API). */
|
|
490
|
+
baseUrl: string;
|
|
491
|
+
reasoning: string;
|
|
492
|
+
instruct: string;
|
|
493
|
+
response: string;
|
|
494
|
+
vision: string;
|
|
495
|
+
image: string;
|
|
496
|
+
video: string;
|
|
497
|
+
/** Ordered per-role fallback model ids (max 3 each), tried on provider failure. */
|
|
498
|
+
fallbacks: {
|
|
499
|
+
reasoning: string[];
|
|
500
|
+
instruct: string[];
|
|
501
|
+
response: string[];
|
|
502
|
+
vision: string[];
|
|
503
|
+
image: string[];
|
|
504
|
+
video: string[];
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/** Result of `workspace.getModels`. */
|
|
508
|
+
interface WorkspaceModelsResult {
|
|
509
|
+
openrouter: WorkspaceModelConfig;
|
|
510
|
+
}
|
|
511
|
+
/** Partial model-config update for `workspace.update` / `workspace.updateModels`. */
|
|
512
|
+
interface WorkspaceModelsUpdateInput {
|
|
513
|
+
status?: "active" | "inactive";
|
|
514
|
+
/** Full OpenRouter API key to store/rotate. Omit to leave unchanged. */
|
|
515
|
+
key?: string;
|
|
516
|
+
/** Optional chat-completions base URL override (defaults to the public OpenRouter API). */
|
|
517
|
+
baseUrl?: string;
|
|
518
|
+
reasoning?: string;
|
|
519
|
+
instruct?: string;
|
|
520
|
+
response?: string;
|
|
521
|
+
vision?: string;
|
|
522
|
+
image?: string;
|
|
523
|
+
video?: string;
|
|
524
|
+
/** Ordered per-role fallback model ids (max 3 each). */
|
|
525
|
+
fallbacks?: {
|
|
526
|
+
reasoning?: string[];
|
|
527
|
+
instruct?: string[];
|
|
528
|
+
response?: string[];
|
|
529
|
+
vision?: string[];
|
|
530
|
+
image?: string[];
|
|
531
|
+
video?: string[];
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** Input for `workspace.update`. */
|
|
535
|
+
interface WorkspaceUpdateInput {
|
|
536
|
+
name?: string;
|
|
537
|
+
config?: {
|
|
538
|
+
openrouter?: WorkspaceModelsUpdateInput;
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
/** A single OpenRouter catalog model. */
|
|
542
|
+
interface CatalogModel {
|
|
543
|
+
id: string;
|
|
544
|
+
name: string;
|
|
545
|
+
contextLength: number | null;
|
|
546
|
+
promptPrice: number | null;
|
|
547
|
+
completionPrice: number | null;
|
|
548
|
+
}
|
|
549
|
+
/** Result of `workspace.listCatalogModels`. */
|
|
550
|
+
interface CatalogResult {
|
|
551
|
+
models: CatalogModel[];
|
|
552
|
+
/** True when the upstream fetch failed and a cached snapshot was served. */
|
|
553
|
+
stale?: boolean;
|
|
554
|
+
}
|
|
555
|
+
/** Result of `workspace.verifyOpenRouterKey`. */
|
|
556
|
+
interface VerifyKeyResult {
|
|
557
|
+
valid: boolean;
|
|
558
|
+
error?: string;
|
|
559
|
+
}
|
|
560
|
+
/** A v1 API key with rotation metadata (hashes never leave the server). */
|
|
561
|
+
interface ApiKeyInfo {
|
|
562
|
+
_id: string;
|
|
563
|
+
name: string;
|
|
564
|
+
prefix: string;
|
|
565
|
+
scopes: string[];
|
|
566
|
+
createdAt: string | Date;
|
|
567
|
+
lastUsedAt: string | Date | null;
|
|
568
|
+
revokedAt: string | Date | null;
|
|
569
|
+
/** When the key is auto-deleted (createdAt + lifetime). */
|
|
570
|
+
rotatesAt: string | Date;
|
|
571
|
+
/** Whole days remaining until rotation (0 when expired). */
|
|
572
|
+
daysLeft: number;
|
|
573
|
+
}
|
|
574
|
+
/** Result of `workspace.listKeys`. */
|
|
575
|
+
interface KeysResult {
|
|
576
|
+
/** Key lifetime in days before auto-deletion. */
|
|
577
|
+
lifetimeDays: number;
|
|
578
|
+
keys: ApiKeyInfo[];
|
|
579
|
+
}
|
|
580
|
+
/** Input for `workspace.createKey`. */
|
|
581
|
+
interface CreateKeyInput {
|
|
582
|
+
/** Display name for the key (defaults to "API Key" server-side). */
|
|
583
|
+
name?: string;
|
|
584
|
+
}
|
|
585
|
+
/** A freshly minted key. `secret` is the raw key — shown exactly once, never stored in plaintext. */
|
|
586
|
+
interface MintedKey {
|
|
587
|
+
id: string;
|
|
588
|
+
name: string;
|
|
589
|
+
prefix: string;
|
|
590
|
+
secret: string;
|
|
591
|
+
}
|
|
592
|
+
/** An expired key that was discarded automatically when a new key was minted. */
|
|
593
|
+
interface DiscardedKey {
|
|
594
|
+
_id?: string;
|
|
595
|
+
name: string;
|
|
596
|
+
prefix: string;
|
|
597
|
+
/** True when the key was embedded on the workspace document (pre-ApiKey-collection era). */
|
|
598
|
+
legacy: boolean;
|
|
599
|
+
}
|
|
600
|
+
/** Result of `workspace.createKey`. */
|
|
601
|
+
interface CreateKeyResult {
|
|
602
|
+
key: MintedKey;
|
|
603
|
+
/** Expired, non-revoked keys discarded as part of the rotation. */
|
|
604
|
+
discarded: DiscardedKey[];
|
|
605
|
+
}
|
|
606
|
+
/** Result of `workspace.deleteKey`. */
|
|
607
|
+
interface DeleteKeyResult {
|
|
608
|
+
deleted: {
|
|
609
|
+
id: string;
|
|
610
|
+
name: string;
|
|
611
|
+
prefix: string;
|
|
612
|
+
legacy: boolean;
|
|
613
|
+
};
|
|
614
|
+
}
|
|
478
615
|
/** Input for `audio.textToSpeech`. */
|
|
479
616
|
interface TtsInput {
|
|
480
617
|
/** Text to synthesize (max 3000 chars). */
|
|
@@ -577,6 +714,26 @@ declare class WorkspaceApi {
|
|
|
577
714
|
constructor(t: Transport);
|
|
578
715
|
/** GET /api/v1/workspace */
|
|
579
716
|
get(): Promise<Workspace>;
|
|
717
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
718
|
+
getModels(): Promise<WorkspaceModelsResult>;
|
|
719
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
720
|
+
update(input: WorkspaceUpdateInput): Promise<Workspace>;
|
|
721
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
722
|
+
updateModels(input: WorkspaceModelsUpdateInput): Promise<Workspace>;
|
|
723
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
724
|
+
listCatalogModels(): Promise<CatalogResult>;
|
|
725
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
726
|
+
verifyOpenRouterKey(key: string, model?: string, baseUrl?: string): Promise<VerifyKeyResult>;
|
|
727
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
728
|
+
listKeys(): Promise<KeysResult>;
|
|
729
|
+
/**
|
|
730
|
+
* POST /api/v1/workspace/keys — mint a new API key for the workspace.
|
|
731
|
+
* All expired, non-revoked keys (issued and legacy) are discarded first, so a
|
|
732
|
+
* rotation is one call. The raw `secret` is returned exactly once.
|
|
733
|
+
*/
|
|
734
|
+
createKey(input?: CreateKeyInput): Promise<CreateKeyResult>;
|
|
735
|
+
/** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */
|
|
736
|
+
deleteKey(keyId: string): Promise<DeleteKeyResult>;
|
|
580
737
|
}
|
|
581
738
|
/** Agents namespace. */
|
|
582
739
|
declare class AgentsApi {
|
|
@@ -721,4 +878,4 @@ declare class QLError extends Error {
|
|
|
721
878
|
get isNetworkError(): boolean;
|
|
722
879
|
}
|
|
723
880
|
|
|
724
|
-
export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, DEFAULT_BASE_URL, type FileUploadOptions, FilesApi, type GeneratedImage, type HistoryPage, type HistoryParams, type ImageGenerateInput, type ImageGenerateResult, type ImageModelInfo, type ImageModelsResult, type ImagePricingEntry, type ImageReferenceInput, type ImageTier, type ImageUsage, ImagesApi, type MessageItem, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type TtsInput, type TtsResult, type UploadedFile, type VideoGenerateInput, type VideoModelInfo, type VideoModelsResult, type VideoPricingEntry, type VideoTask, type VideoTaskCreated, VideoTaskHandle, type VideoTaskStatus, type VideoTier, type VideoWaitOptions, VideosApi, type VoiceInfo, type VoicesResult, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
|
|
881
|
+
export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, type CreateKeyInput, type CreateKeyResult, DEFAULT_BASE_URL, type DeleteKeyResult, type DiscardedKey, type FileUploadOptions, FilesApi, type GeneratedImage, type HistoryPage, type HistoryParams, type ImageGenerateInput, type ImageGenerateResult, type ImageModelInfo, type ImageModelsResult, type ImagePricingEntry, type ImageReferenceInput, type ImageTier, type ImageUsage, ImagesApi, type MessageItem, type MintedKey, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type TtsInput, type TtsResult, type UploadedFile, type VideoGenerateInput, type VideoModelInfo, type VideoModelsResult, type VideoPricingEntry, type VideoTask, type VideoTaskCreated, VideoTaskHandle, type VideoTaskStatus, type VideoTier, type VideoWaitOptions, VideosApi, type VoiceInfo, type VoicesResult, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ interface ChatInput {
|
|
|
56
56
|
messages: ChatMessage[];
|
|
57
57
|
/** Optional internal user id; defaults to the key's workspace when omitted. */
|
|
58
58
|
userId?: string;
|
|
59
|
+
/** Optional OpenRouter model id override — wins over the workspace director-panel default. */
|
|
60
|
+
modelId?: string;
|
|
59
61
|
/** Optional OpenRouter response-format hint (e.g. `{ type: "json_object" }`). */
|
|
60
62
|
response_format?: Record<string, unknown>;
|
|
61
63
|
}
|
|
@@ -335,6 +337,8 @@ interface ImageReferenceInput {
|
|
|
335
337
|
/** Input for `images.generate`. */
|
|
336
338
|
interface ImageGenerateInput {
|
|
337
339
|
prompt: string;
|
|
340
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
341
|
+
modelId?: string;
|
|
338
342
|
/** Explicit OpenRouter model id (wins over `tier`). */
|
|
339
343
|
model?: string;
|
|
340
344
|
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
@@ -415,6 +419,8 @@ interface VideoModelsResult {
|
|
|
415
419
|
interface VideoGenerateInput {
|
|
416
420
|
/** The creative brief / script for the video. */
|
|
417
421
|
prompt: string;
|
|
422
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
423
|
+
modelId?: string;
|
|
418
424
|
/** Explicit registry model id (wins over `tier`). */
|
|
419
425
|
model?: string;
|
|
420
426
|
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
@@ -475,6 +481,137 @@ interface VideoWaitOptions {
|
|
|
475
481
|
/** Called after each poll with the latest job snapshot. */
|
|
476
482
|
onTick?: (task: VideoTask) => void;
|
|
477
483
|
}
|
|
484
|
+
/** Per-role model defaults as configured in the director panel. */
|
|
485
|
+
interface WorkspaceModelConfig {
|
|
486
|
+
status: "active" | "inactive";
|
|
487
|
+
/** Masked OpenRouter key — the raw key is never returned by the API. */
|
|
488
|
+
keyMasked: string;
|
|
489
|
+
/** Optional chat-completions base URL override (empty = public OpenRouter API). */
|
|
490
|
+
baseUrl: string;
|
|
491
|
+
reasoning: string;
|
|
492
|
+
instruct: string;
|
|
493
|
+
response: string;
|
|
494
|
+
vision: string;
|
|
495
|
+
image: string;
|
|
496
|
+
video: string;
|
|
497
|
+
/** Ordered per-role fallback model ids (max 3 each), tried on provider failure. */
|
|
498
|
+
fallbacks: {
|
|
499
|
+
reasoning: string[];
|
|
500
|
+
instruct: string[];
|
|
501
|
+
response: string[];
|
|
502
|
+
vision: string[];
|
|
503
|
+
image: string[];
|
|
504
|
+
video: string[];
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/** Result of `workspace.getModels`. */
|
|
508
|
+
interface WorkspaceModelsResult {
|
|
509
|
+
openrouter: WorkspaceModelConfig;
|
|
510
|
+
}
|
|
511
|
+
/** Partial model-config update for `workspace.update` / `workspace.updateModels`. */
|
|
512
|
+
interface WorkspaceModelsUpdateInput {
|
|
513
|
+
status?: "active" | "inactive";
|
|
514
|
+
/** Full OpenRouter API key to store/rotate. Omit to leave unchanged. */
|
|
515
|
+
key?: string;
|
|
516
|
+
/** Optional chat-completions base URL override (defaults to the public OpenRouter API). */
|
|
517
|
+
baseUrl?: string;
|
|
518
|
+
reasoning?: string;
|
|
519
|
+
instruct?: string;
|
|
520
|
+
response?: string;
|
|
521
|
+
vision?: string;
|
|
522
|
+
image?: string;
|
|
523
|
+
video?: string;
|
|
524
|
+
/** Ordered per-role fallback model ids (max 3 each). */
|
|
525
|
+
fallbacks?: {
|
|
526
|
+
reasoning?: string[];
|
|
527
|
+
instruct?: string[];
|
|
528
|
+
response?: string[];
|
|
529
|
+
vision?: string[];
|
|
530
|
+
image?: string[];
|
|
531
|
+
video?: string[];
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** Input for `workspace.update`. */
|
|
535
|
+
interface WorkspaceUpdateInput {
|
|
536
|
+
name?: string;
|
|
537
|
+
config?: {
|
|
538
|
+
openrouter?: WorkspaceModelsUpdateInput;
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
/** A single OpenRouter catalog model. */
|
|
542
|
+
interface CatalogModel {
|
|
543
|
+
id: string;
|
|
544
|
+
name: string;
|
|
545
|
+
contextLength: number | null;
|
|
546
|
+
promptPrice: number | null;
|
|
547
|
+
completionPrice: number | null;
|
|
548
|
+
}
|
|
549
|
+
/** Result of `workspace.listCatalogModels`. */
|
|
550
|
+
interface CatalogResult {
|
|
551
|
+
models: CatalogModel[];
|
|
552
|
+
/** True when the upstream fetch failed and a cached snapshot was served. */
|
|
553
|
+
stale?: boolean;
|
|
554
|
+
}
|
|
555
|
+
/** Result of `workspace.verifyOpenRouterKey`. */
|
|
556
|
+
interface VerifyKeyResult {
|
|
557
|
+
valid: boolean;
|
|
558
|
+
error?: string;
|
|
559
|
+
}
|
|
560
|
+
/** A v1 API key with rotation metadata (hashes never leave the server). */
|
|
561
|
+
interface ApiKeyInfo {
|
|
562
|
+
_id: string;
|
|
563
|
+
name: string;
|
|
564
|
+
prefix: string;
|
|
565
|
+
scopes: string[];
|
|
566
|
+
createdAt: string | Date;
|
|
567
|
+
lastUsedAt: string | Date | null;
|
|
568
|
+
revokedAt: string | Date | null;
|
|
569
|
+
/** When the key is auto-deleted (createdAt + lifetime). */
|
|
570
|
+
rotatesAt: string | Date;
|
|
571
|
+
/** Whole days remaining until rotation (0 when expired). */
|
|
572
|
+
daysLeft: number;
|
|
573
|
+
}
|
|
574
|
+
/** Result of `workspace.listKeys`. */
|
|
575
|
+
interface KeysResult {
|
|
576
|
+
/** Key lifetime in days before auto-deletion. */
|
|
577
|
+
lifetimeDays: number;
|
|
578
|
+
keys: ApiKeyInfo[];
|
|
579
|
+
}
|
|
580
|
+
/** Input for `workspace.createKey`. */
|
|
581
|
+
interface CreateKeyInput {
|
|
582
|
+
/** Display name for the key (defaults to "API Key" server-side). */
|
|
583
|
+
name?: string;
|
|
584
|
+
}
|
|
585
|
+
/** A freshly minted key. `secret` is the raw key — shown exactly once, never stored in plaintext. */
|
|
586
|
+
interface MintedKey {
|
|
587
|
+
id: string;
|
|
588
|
+
name: string;
|
|
589
|
+
prefix: string;
|
|
590
|
+
secret: string;
|
|
591
|
+
}
|
|
592
|
+
/** An expired key that was discarded automatically when a new key was minted. */
|
|
593
|
+
interface DiscardedKey {
|
|
594
|
+
_id?: string;
|
|
595
|
+
name: string;
|
|
596
|
+
prefix: string;
|
|
597
|
+
/** True when the key was embedded on the workspace document (pre-ApiKey-collection era). */
|
|
598
|
+
legacy: boolean;
|
|
599
|
+
}
|
|
600
|
+
/** Result of `workspace.createKey`. */
|
|
601
|
+
interface CreateKeyResult {
|
|
602
|
+
key: MintedKey;
|
|
603
|
+
/** Expired, non-revoked keys discarded as part of the rotation. */
|
|
604
|
+
discarded: DiscardedKey[];
|
|
605
|
+
}
|
|
606
|
+
/** Result of `workspace.deleteKey`. */
|
|
607
|
+
interface DeleteKeyResult {
|
|
608
|
+
deleted: {
|
|
609
|
+
id: string;
|
|
610
|
+
name: string;
|
|
611
|
+
prefix: string;
|
|
612
|
+
legacy: boolean;
|
|
613
|
+
};
|
|
614
|
+
}
|
|
478
615
|
/** Input for `audio.textToSpeech`. */
|
|
479
616
|
interface TtsInput {
|
|
480
617
|
/** Text to synthesize (max 3000 chars). */
|
|
@@ -577,6 +714,26 @@ declare class WorkspaceApi {
|
|
|
577
714
|
constructor(t: Transport);
|
|
578
715
|
/** GET /api/v1/workspace */
|
|
579
716
|
get(): Promise<Workspace>;
|
|
717
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
718
|
+
getModels(): Promise<WorkspaceModelsResult>;
|
|
719
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
720
|
+
update(input: WorkspaceUpdateInput): Promise<Workspace>;
|
|
721
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
722
|
+
updateModels(input: WorkspaceModelsUpdateInput): Promise<Workspace>;
|
|
723
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
724
|
+
listCatalogModels(): Promise<CatalogResult>;
|
|
725
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
726
|
+
verifyOpenRouterKey(key: string, model?: string, baseUrl?: string): Promise<VerifyKeyResult>;
|
|
727
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
728
|
+
listKeys(): Promise<KeysResult>;
|
|
729
|
+
/**
|
|
730
|
+
* POST /api/v1/workspace/keys — mint a new API key for the workspace.
|
|
731
|
+
* All expired, non-revoked keys (issued and legacy) are discarded first, so a
|
|
732
|
+
* rotation is one call. The raw `secret` is returned exactly once.
|
|
733
|
+
*/
|
|
734
|
+
createKey(input?: CreateKeyInput): Promise<CreateKeyResult>;
|
|
735
|
+
/** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */
|
|
736
|
+
deleteKey(keyId: string): Promise<DeleteKeyResult>;
|
|
580
737
|
}
|
|
581
738
|
/** Agents namespace. */
|
|
582
739
|
declare class AgentsApi {
|
|
@@ -721,4 +878,4 @@ declare class QLError extends Error {
|
|
|
721
878
|
get isNetworkError(): boolean;
|
|
722
879
|
}
|
|
723
880
|
|
|
724
|
-
export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, DEFAULT_BASE_URL, type FileUploadOptions, FilesApi, type GeneratedImage, type HistoryPage, type HistoryParams, type ImageGenerateInput, type ImageGenerateResult, type ImageModelInfo, type ImageModelsResult, type ImagePricingEntry, type ImageReferenceInput, type ImageTier, type ImageUsage, ImagesApi, type MessageItem, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type TtsInput, type TtsResult, type UploadedFile, type VideoGenerateInput, type VideoModelInfo, type VideoModelsResult, type VideoPricingEntry, type VideoTask, type VideoTaskCreated, VideoTaskHandle, type VideoTaskStatus, type VideoTier, type VideoWaitOptions, VideosApi, type VoiceInfo, type VoicesResult, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
|
|
881
|
+
export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, type CreateKeyInput, type CreateKeyResult, DEFAULT_BASE_URL, type DeleteKeyResult, type DiscardedKey, type FileUploadOptions, FilesApi, type GeneratedImage, type HistoryPage, type HistoryParams, type ImageGenerateInput, type ImageGenerateResult, type ImageModelInfo, type ImageModelsResult, type ImagePricingEntry, type ImageReferenceInput, type ImageTier, type ImageUsage, ImagesApi, type MessageItem, type MintedKey, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type TtsInput, type TtsResult, type UploadedFile, type VideoGenerateInput, type VideoModelInfo, type VideoModelsResult, type VideoPricingEntry, type VideoTask, type VideoTaskCreated, VideoTaskHandle, type VideoTaskStatus, type VideoTier, type VideoWaitOptions, VideosApi, type VoiceInfo, type VoicesResult, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
|
package/dist/index.js
CHANGED
|
@@ -398,6 +398,42 @@ var WorkspaceApi = class {
|
|
|
398
398
|
get() {
|
|
399
399
|
return this.t.json("GET", "/api/v1/workspace");
|
|
400
400
|
}
|
|
401
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
402
|
+
getModels() {
|
|
403
|
+
return this.t.json("GET", "/api/v1/workspace/models");
|
|
404
|
+
}
|
|
405
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
406
|
+
update(input) {
|
|
407
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: input });
|
|
408
|
+
}
|
|
409
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
410
|
+
updateModels(input) {
|
|
411
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: { config: { openrouter: input } } });
|
|
412
|
+
}
|
|
413
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
414
|
+
listCatalogModels() {
|
|
415
|
+
return this.t.json("GET", "/api/v1/workspace/models/catalog");
|
|
416
|
+
}
|
|
417
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
418
|
+
verifyOpenRouterKey(key, model, baseUrl) {
|
|
419
|
+
return this.t.json("POST", "/api/v1/workspace/models/verify", { body: { key, model, baseUrl } });
|
|
420
|
+
}
|
|
421
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
422
|
+
listKeys() {
|
|
423
|
+
return this.t.json("GET", "/api/v1/workspace/keys");
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* POST /api/v1/workspace/keys — mint a new API key for the workspace.
|
|
427
|
+
* All expired, non-revoked keys (issued and legacy) are discarded first, so a
|
|
428
|
+
* rotation is one call. The raw `secret` is returned exactly once.
|
|
429
|
+
*/
|
|
430
|
+
createKey(input) {
|
|
431
|
+
return this.t.json("POST", "/api/v1/workspace/keys", { body: input ?? {} });
|
|
432
|
+
}
|
|
433
|
+
/** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */
|
|
434
|
+
deleteKey(keyId) {
|
|
435
|
+
return this.t.json("DELETE", `/api/v1/workspace/keys/${encodeURIComponent(keyId)}`);
|
|
436
|
+
}
|
|
401
437
|
};
|
|
402
438
|
var AgentsApi = class {
|
|
403
439
|
constructor(t) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/sse.ts","../src/task.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["import type { ApiErrorCode } from \"./types.js\";\n\nexport interface QLErrorContext {\n method?: string;\n url?: string;\n}\n\n/**\n * Error thrown by the SDK for any failed API interaction.\n *\n * - `status`: HTTP status code (when the failure came from an HTTP response).\n * - `code`: stable API error code when provided by the backend, otherwise a\n * synthesized one derived from the status, or a synthetic transport\n * code such as \"aborted\" / \"timeout\" / \"network\".\n * - `message`: human-readable description. The API key is never included.\n */\nexport class QLError extends Error {\n readonly status?: number;\n readonly code: string;\n readonly method?: string;\n readonly url?: string;\n /** The raw parsed error body (if any), for advanced inspection. */\n readonly details?: unknown;\n\n constructor(message: string, opts: { status?: number; code: string; context?: QLErrorContext; details?: unknown } = { code: \"internal_error\" }) {\n super(message);\n this.name = \"QLError\";\n this.status = opts.status;\n this.code = opts.code;\n this.method = opts.context?.method;\n this.url = opts.context?.url;\n this.details = opts.details;\n // Restore prototype chain (required when targeting ES5-ish runtimes).\n Object.setPrototypeOf(this, QLError.prototype);\n }\n\n /** True for 401/403 or unauthorized/forbidden codes. */\n get isAuthError(): boolean {\n return this.code === \"unauthorized\" || this.code === \"forbidden\" || this.status === 401 || this.status === 403;\n }\n\n /** True when the request was aborted by the caller. */\n get isAborted(): boolean {\n return this.code === \"aborted\";\n }\n\n /** True when a wait() call exceeded its timeout. */\n get isTimeout(): boolean {\n return this.code === \"timeout\";\n }\n\n /** True for transient network failures (no HTTP response received). */\n get isNetworkError(): boolean {\n return this.code === \"network\";\n }\n}\n\n/** Map an HTTP status to a stable API error code when the body has none. */\nexport function codeFromStatus(status: number): ApiErrorCode | \"conflict\" {\n switch (status) {\n case 400:\n return \"validation_error\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 409:\n return \"conflict\";\n default:\n return status >= 500 ? \"internal_error\" : \"validation_error\";\n }\n}\n\ninterface ParsedErrorBody {\n ok?: boolean;\n error?: { code?: string; message?: string } | string;\n message?: string;\n}\n\n/** Build a QLError from a non-2xx HTTP response. Never includes the API key. */\nexport function toHttpError(status: number, text: string | undefined, ctx: QLErrorContext): QLError {\n let parsed: ParsedErrorBody | null = null;\n if (text) {\n try {\n const j = JSON.parse(text);\n if (j && typeof j === \"object\") parsed = j as ParsedErrorBody;\n } catch {\n parsed = null;\n }\n }\n\n const bodyErr = parsed?.error;\n let code: string | undefined;\n let message: string | undefined;\n if (typeof bodyErr === \"string\") {\n message = bodyErr;\n } else if (bodyErr && typeof bodyErr === \"object\") {\n code = typeof bodyErr.code === \"string\" ? bodyErr.code : undefined;\n message = typeof bodyErr.message === \"string\" ? bodyErr.message : undefined;\n }\n if (!code) code = codeFromStatus(status);\n if (!message) message = (typeof parsed?.message === \"string\" ? parsed.message : undefined) ?? `Request failed with status ${status}`;\n\n return new QLError(message, { status, code, context: ctx, details: parsed ?? undefined });\n}\n\n/** Wrap a low-level fetch/network failure (no HTTP response). */\nexport function toNetworkError(cause: unknown, ctx: QLErrorContext): QLError {\n const aborted = isAbortCause(cause);\n if (aborted) {\n return new QLError(\"Request aborted\", { code: \"aborted\", context: ctx });\n }\n const msg = cause instanceof Error ? cause.message : String(cause);\n return new QLError(`Network error: ${msg}`, { code: \"network\", context: ctx, details: cause });\n}\n\nfunction isAbortCause(cause: unknown): boolean {\n if (!cause) return false;\n if (typeof cause === \"object\") {\n const c = cause as { name?: string; type?: string };\n if (c.name === \"AbortError\" || c.type === \"aborted\") return true;\n }\n return false;\n}\n\n/** Build an abort error for wait()/stream cancellation. */\nexport function abortError(): QLError {\n return new QLError(\"Operation aborted\", { code: \"aborted\" });\n}\n\n/** Build a timeout error for wait(). */\nexport function timeoutError(timeoutMs: number): QLError {\n return new QLError(`Timed out after ${timeoutMs}ms`, { code: \"timeout\" });\n}\n","import { QLError, toHttpError, toNetworkError } from \"./errors.js\";\nimport type { ApiErrorCode } from \"./types.js\";\n\nexport interface TransportOptions {\n apiKey: string;\n baseUrl: string;\n fetchImpl: typeof fetch;\n}\n\nexport interface JsonRequestOptions {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport interface FormRequestOptions {\n form: FormData;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * Internal transport used by the API namespaces. Keeps the API key inside a\n * closure (never exposed) and normalizes responses/errors for the caller.\n */\nexport interface Transport {\n /** Perform a JSON request and return the unwrapped `data` payload. */\n json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;\n /** Perform a multipart/form-data request and return the unwrapped `data` payload. */\n form<T>(path: string, opts: FormRequestOptions): Promise<T>;\n /**\n * Perform a request expected to stream SSE. Returns the response body stream\n * after verifying a 2xx + text/event-stream; throws QLError otherwise.\n */\n stream(method: string, path: string, opts?: JsonRequestOptions & { acceptStream?: boolean }): Promise<ReadableStream<Uint8Array>>;\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n const { apiKey, baseUrl, fetchImpl } = opts;\n\n return {\n async json<T>(method: string, path: string, reqOpts: JsonRequestOptions = {}) {\n const res = await doFetch(method, path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });\n return unwrap<T>(text, { method, url: res.url });\n },\n\n async form<T>(path: string, reqOpts: FormRequestOptions) {\n const res = await doFormFetch(path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method: \"POST\", url: res.url });\n return unwrap<T>(text, { method: \"POST\", url: res.url });\n },\n\n async stream(method, path, reqOpts = {}) {\n const res = await doFetch(method, path, {\n ...reqOpts,\n headers: { accept: \"text/event-stream\", ...(reqOpts.headers ?? {}) },\n });\n if (!res.ok) {\n const text = await res.text().catch(() => undefined);\n throw toHttpError(res.status, text, { method, url: res.url });\n }\n const ctype = (res.headers.get(\"content-type\") || \"\").toLowerCase();\n if (!ctype.includes(\"text/event-stream\")) {\n // The endpoint returned a non-SSE body (e.g. an error envelope). Surface it.\n const text = await res.text().catch(() => undefined);\n throw new QLError(`Expected text/event-stream but got \"${ctype || \"unknown\"}\"`, {\n status: res.status,\n code: \"internal_error\",\n context: { method, url: res.url },\n details: safeParse(text),\n });\n }\n if (!res.body) throw new QLError(\"Response has no readable body stream\", { code: \"network\", context: { method, url: res.url } });\n return res.body;\n },\n };\n\n function doFetch(method: string, path: string, reqOpts: JsonRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path, reqOpts.query);\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method,\n headers,\n body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method, url });\n });\n }\n\n function doFormFetch(path: string, reqOpts: FormRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path);\n // No content-type header here — fetch sets the multipart boundary itself.\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method: \"POST\",\n headers,\n body: reqOpts.form,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method: \"POST\", url });\n });\n }\n}\n\nfunction unwrap<T>(text: string, ctx: { method?: string; url?: string }): T {\n const parsed = safeParse(text);\n if (parsed && typeof parsed === \"object\" && \"ok\" in (parsed as Record<string, unknown>)) {\n const env = parsed as { ok: boolean; data?: unknown; error?: { code?: string; message?: string } };\n if (env.ok === true) return env.data as T;\n // ok:false on a 2xx — treat as an application error.\n throw new QLError(env.error?.message || \"Request failed\", {\n code: (env.error?.code as ApiErrorCode) || \"internal_error\",\n context: ctx,\n details: env,\n });\n }\n // Non-enveloped payload (legacy shapes): return as-is.\n return parsed as T;\n}\n\nfunction safeParse(text?: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Join base + path and append a query string (skipping undefined values). */\nexport function buildUrl(baseUrl: string, path: string, query?: Record<string, string | number | undefined>): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const p = path.startsWith(\"/\") ? path : `/${path}`;\n let url = `${base}${p}`;\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n }\n return url;\n}\n\n/** Normalize a base URL: trim whitespace and drop any trailing slash. */\nexport function normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n","/**\n * Minimal, dependency-free Server-Sent Events reader built on Web Streams.\n *\n * Handles the cases that commonly break naive parsers:\n * - a `data:` line split across two TCP chunks (chunk boundaries)\n * - multiple events arriving in a single chunk\n * - both CRLF and LF line endings (and lone CR)\n * - a final event that is not terminated by a trailing newline\n * - the `[DONE]` terminator\n * - abort signals\n */\n\nexport interface SSEEvent {\n /** The concatenated `data:` payload for this event (trimmed of the leading space). */\n data: string;\n}\n\ninterface ReadOptions {\n signal?: AbortSignal;\n /** When true, stop after the first `[DONE]` data value. Default true. */\n stopOnDone?: boolean;\n}\n\n/**\n * Read raw SSE events from a `ReadableStream<Uint8Array>`.\n * Yields one object per event with its combined `data` payload.\n */\nexport async function* readSSEEvents(\n body: ReadableStream<Uint8Array>,\n opts: ReadOptions = {},\n): AsyncGenerator<SSEEvent, void, unknown> {\n const stopOnDone = opts.stopOnDone ?? true;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let dataLines: string[] = [];\n\n // Abort wiring: cancel the underlying stream promptly when the signal fires.\n const onAbort = () => {\n void reader.cancel().catch(() => {});\n };\n if (opts.signal) {\n if (opts.signal.aborted) {\n await reader.cancel().catch(() => {});\n return;\n }\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n const dispatch = (): SSEEvent | null => {\n if (dataLines.length === 0) return null;\n const data = dataLines.join(\"\\n\");\n dataLines = [];\n return { data };\n };\n\n const processLine = (line: string): SSEEvent | null => {\n if (line === \"\") return dispatch(); // blank line = event boundary\n if (line.startsWith(\":\")) return null; // comment\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) value = value.slice(1);\n dataLines.push(value);\n return null;\n }\n // Ignore event:/id:/retry: and unknown fields.\n return null;\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let s = splitFirstLine(buffer);\n while (s !== null) {\n const ev = processLine(s.line);\n if (ev) {\n if (stopOnDone && ev.data.trim() === \"[DONE]\") return;\n yield ev;\n }\n buffer = s.rest;\n s = splitFirstLine(buffer);\n }\n }\n\n // Flush any bytes still held by the decoder.\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const ev = processLine(buffer);\n if (ev && !(stopOnDone && ev.data.trim() === \"[DONE]\")) yield ev;\n }\n // Flush a final event that had no terminating blank line.\n const tail = dispatch();\n if (tail && !(stopOnDone && tail.data.trim() === \"[DONE]\")) yield tail;\n } finally {\n if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n try {\n reader.releaseLock();\n } catch {\n /* already released */\n }\n }\n}\n\n/** Split the first complete line (LF, CRLF, or lone CR) out of `buf`. */\nfunction splitFirstLine(buf: string): { line: string; rest: string } | null {\n const nl = buf.indexOf(\"\\n\");\n const cr = buf.indexOf(\"\\r\");\n let end = -1;\n let termLen = 0;\n if (nl !== -1 && (cr === -1 || nl < cr)) {\n end = nl;\n termLen = 1;\n } else if (cr !== -1) {\n end = cr;\n termLen = buf[cr + 1] === \"\\n\" ? 2 : 1;\n }\n if (end === -1) return null;\n return { line: buf.slice(0, end), rest: buf.slice(end + termLen) };\n}\n\n/** Parse a single SSE `data` payload as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n const trimmed = data.trim();\n if (trimmed === \"\" || trimmed === \"[DONE]\") return null;\n try {\n return JSON.parse(trimmed) as T;\n } catch {\n return null; // malformed JSON is skipped, not fatal\n }\n}\n","import type { Transport } from \"./http.js\";\nimport { abortError, timeoutError } from \"./errors.js\";\nimport type { Task, WaitOptions, VideoTask, VideoWaitOptions } from \"./types.js\";\n\n/** Statuses at which a job will not change again (shared by tasks and video jobs). */\nconst TERMINAL_TASK_STATUSES = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\nexport function isTerminalTaskStatus(status: string): boolean {\n return TERMINAL_TASK_STATUSES.has(status);\n}\n\ninterface PollOptions {\n intervalMs?: number;\n maxIntervalMs?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Shared polling loop used by TaskHandle.wait() and VideoTaskHandle.wait().\n *\n * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.\n * - Throws a QLError with code \"timeout\" if `timeoutMs` elapses first.\n * - Throws a QLError with code \"aborted\" if `signal` aborts.\n */\nasync function pollUntilTerminal<T>(\n fetchSnapshot: (signal?: AbortSignal) => Promise<T>,\n isTerminal: (snapshot: T) => boolean,\n onTick: ((snapshot: T) => void) | undefined,\n opts: PollOptions,\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? 2000;\n const maxIntervalMs = opts.maxIntervalMs ?? 15000;\n const signal = opts.signal;\n const startedAt = Date.now();\n let delay = intervalMs;\n\n for (;;) {\n if (signal?.aborted) throw abortError();\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n const snapshot = await fetchSnapshot(signal);\n onTick?.(snapshot);\n if (isTerminal(snapshot)) return snapshot;\n\n // Recompute timeout after the poll so a slow request doesn't overshoot silently.\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n await sleep(delay, signal);\n delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));\n }\n}\n\n/**\n * A handle to a background task created via `tasks.create`.\n *\n * NOTE on execution: creating a task only enqueues it. It may stay in the\n * `queued` state until an existing worker/execution mechanism processes it —\n * this SDK does not trigger execution. `wait()` simply polls until the task\n * reaches a terminal status (or you time out / abort).\n */\nexport class TaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current task snapshot (single request). */\n get(signal?: AbortSignal): Promise<Task> {\n return this.transport.json<Task>(\"GET\", `/api/v1/tasks/${this.taskId}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<Task> {\n return this.get(signal);\n }\n\n /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */\n async wait(opts: WaitOptions = {}): Promise<Task> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/**\n * A handle to a video job created via `videos.generate`.\n * Polls the video-tasks endpoint until the job reaches a terminal status.\n */\nexport class VideoTaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current job snapshot (single request). */\n get(signal?: AbortSignal): Promise<VideoTask> {\n return this.transport.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<VideoTask> {\n return this.get(signal);\n }\n\n /** Poll until the job reaches a terminal status (completed/failed/cancelled). */\n async wait(opts: VideoWaitOptions = {}): Promise<VideoTask> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/** Abort-aware sleep. Rejects with an abort error if `signal` fires first. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n };\n if (signal) signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { createTransport, normalizeUrl, type Transport } from \"./http.js\";\nimport { QLError } from \"./errors.js\";\nimport { readSSEEvents, parseSSEData } from \"./sse.js\";\nimport { TaskHandle, VideoTaskHandle } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CapabilitiesResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelsResult,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n TtsInput,\n TtsResult,\n UploadedFile,\n FileUploadOptions,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n VideoGenerateInput,\n VideoModelsResult,\n VideoTask,\n VideoTaskCreated,\n VoicesResult,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\n/** Videos namespace (tiered video generation: submit → poll). */\nexport class VideosApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/videos/models — list tiered video models + engine availability. */\n listModels(): Promise<VideoModelsResult> {\n return this.t.json<VideoModelsResult>(\"GET\", \"/api/v1/videos/models\");\n }\n\n /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */\n generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated> {\n return this.t.json<VideoTaskCreated>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });\n }\n\n /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */\n getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */\n cancelTask(taskId: string): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"DELETE\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);\n }\n\n /** Get a handle for polling / waiting on a video job (poll(), wait()). */\n handle(taskId: string): VideoTaskHandle {\n return new VideoTaskHandle(this.t, taskId);\n }\n}\n\n/** Audio namespace (text-to-speech). */\nexport class AudioApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/audio/voices — list available TTS voices. */\n voices(): Promise<VoicesResult> {\n return this.t.json<VoicesResult>(\"GET\", \"/api/v1/audio/voices\");\n }\n\n /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */\n textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult> {\n return this.t.json<TtsResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });\n }\n}\n\n/** Files namespace (media uploads). */\nexport class FilesApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/files — upload a media file (multipart field \"file\"). */\n async upload(file: Blob, opts: FileUploadOptions = {}): Promise<UploadedFile> {\n const form = new FormData();\n if (opts.filename !== undefined) {\n form.append(\"file\", file, opts.filename);\n } else {\n form.append(\"file\", file);\n }\n // Coarse progress only: fetch does not expose upload byte progress.\n opts.onProgress?.(0);\n const result = await this.t.form<UploadedFile>(\"/api/v1/files\", { form });\n opts.onProgress?.(100);\n return result;\n }\n}\n\nfunction readEnvBaseUrl(): string | undefined {\n try {\n if (typeof process !== \"undefined\" && process?.env) {\n return process.env.QL_BASE_URL || undefined;\n }\n } catch {\n /* non-Node runtime */\n }\n return undefined;\n}\n\n/**\n * The public client. Example:\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });\n * const agents = await ql.agents.list();\n */\nexport class QLClient {\n readonly workspace: WorkspaceApi;\n readonly agents: AgentsApi;\n readonly workflows: WorkflowsApi;\n readonly tasks: TasksApi;\n readonly images: ImagesApi;\n readonly videos: VideosApi;\n readonly audio: AudioApi;\n readonly files: FilesApi;\n\n private readonly transport: Transport;\n private readonly base: string;\n\n constructor(opts: QLClientOptions) {\n if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.length === 0) {\n throw new QLError(\"apiKey is required\", { code: \"validation_error\" });\n }\n this.base = normalizeUrl(opts.baseUrl ?? readEnvBaseUrl() ?? DEFAULT_BASE_URL);\n const fetchImpl = (opts.fetch ?? globalThis.fetch).bind(globalThis);\n this.transport = createTransport({ apiKey: opts.apiKey, baseUrl: this.base, fetchImpl });\n this.workspace = new WorkspaceApi(this.transport);\n this.agents = new AgentsApi(this.transport);\n this.workflows = new WorkflowsApi(this.transport);\n this.tasks = new TasksApi(this.transport);\n this.images = new ImagesApi(this.transport);\n this.videos = new VideosApi(this.transport);\n this.audio = new AudioApi(this.transport);\n this.files = new FilesApi(this.transport);\n }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Videos — tiered video generation (async: submit → poll)\n// ---------------------------------------------------------------------------\n\nexport type VideoTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for a video model. */\nexport interface VideoPricingEntry {\n /** What is billed, e.g. \"output_video\" / \"voiceover\". */\n billable: string;\n /** Billing unit: per rendered second, or flat per request. */\n unit: \"second\" | \"request\";\n costUsd: number;\n}\n\n/** A tiered video-generation model as returned by `videos.listModels`. */\nexport interface VideoModelInfo {\n id: string;\n name: string;\n tier: VideoTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n /** Execution engine (e.g. \"motion-graphics\"). */\n engine: string;\n supportsProductImages: boolean;\n maxReferenceImages: number;\n supportsReferenceVideos: boolean;\n maxReferenceVideos: number;\n supportedAspectRatios: string[];\n supportedResolutions: string[];\n /** Inclusive [min, max] duration in seconds. */\n durationRange: [number, number];\n voiceoverSupport: boolean;\n pricing: {\n summary: string;\n entries: VideoPricingEntry[];\n };\n recommended: boolean;\n enabled: boolean;\n /** Runtime engine availability (render toolchain present). */\n available: boolean;\n}\n\n/** Result of `videos.listModels`. */\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n}\n\n/** Input for `videos.generate`. */\nexport interface VideoGenerateInput {\n /** The creative brief / script for the video. */\n prompt: string;\n /** Explicit registry model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: VideoTier | string;\n /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */\n images_list?: string[];\n /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */\n video_files?: string[];\n /** e.g. \"16:9\", \"9:16\", \"1:1\". Default \"16:9\". */\n aspect_ratio?: string;\n /** Duration in seconds (must be within the model's durationRange). */\n duration?: number;\n /** e.g. \"720p\" | \"1080p\". Default \"720p\". */\n resolution?: string;\n /** Bake an ElevenLabs voiceover into the render (requires `narration`). */\n generate_audio?: boolean;\n /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */\n narration?: string;\n}\n\n/** Returned when a video job is created (HTTP 202). */\nexport interface VideoTaskCreated {\n taskId: string;\n status: \"queued\";\n}\n\nexport type VideoTaskStatus =\n | \"queued\"\n | \"rendering\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A video job snapshot, as returned by `videos.getTask`. */\nexport interface VideoTask {\n taskId: string;\n status: VideoTaskStatus;\n progress?: {\n current: number;\n total: number;\n message?: string;\n };\n /** Served media path (e.g. /generated/video-….mp4) once completed. */\n outputUrl?: string;\n mime?: string;\n ext?: string;\n /** Actual rendered duration in seconds. */\n durationSec?: number;\n error?: string;\n model?: string;\n tier?: string;\n latencyMs?: number;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a video job. */\nexport interface VideoWaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest job snapshot. */\n onTick?: (task: VideoTask) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Audio — text-to-speech\n// ---------------------------------------------------------------------------\n\n/** Input for `audio.textToSpeech`. */\nexport interface TtsInput {\n /** Text to synthesize (max 3000 chars). */\n text: string;\n /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */\n voiceId?: string;\n /** Voice stability 0..1 (default 0.5). */\n stability?: number;\n /** Similarity boost 0..1 (default 0.75). */\n similarityBoost?: number;\n}\n\n/** Result of `audio.textToSpeech`. */\nexport interface TtsResult {\n /** Served audio path (e.g. /generated/tts-….mp3). */\n url: string;\n voiceId: string;\n modelId: string;\n bytes: number;\n latencyMs: number;\n}\n\n/** A single ElevenLabs voice as returned by `audio.voices`. */\nexport interface VoiceInfo {\n id: string;\n name: string;\n}\n\n/** Result of `audio.voices`. */\nexport interface VoicesResult {\n voices: VoiceInfo[];\n /** \"live\" = fetched from the provider; \"none\" = no provider key configured. */\n source: \"live\" | \"none\";\n note?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Files — media uploads\n// ---------------------------------------------------------------------------\n\n/** Result of `files.upload`. */\nexport interface UploadedFile {\n /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */\n url: string;\n filename: string;\n size: number;\n contentType: string;\n}\n\n/** Options for `files.upload`. */\nexport interface FileUploadOptions {\n /** Override the stored display name (extension is kept from the file). */\n filename?: string;\n /**\n * Coarse progress callback. Fetch does not expose upload byte progress, so this\n * reports 0 at start and 100 on completion.\n */\n onProgress?: (percent: number) => void;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/sse.ts","../src/task.ts","../src/client.ts","../src/types.ts"],"sourcesContent":["import type { ApiErrorCode } from \"./types.js\";\n\nexport interface QLErrorContext {\n method?: string;\n url?: string;\n}\n\n/**\n * Error thrown by the SDK for any failed API interaction.\n *\n * - `status`: HTTP status code (when the failure came from an HTTP response).\n * - `code`: stable API error code when provided by the backend, otherwise a\n * synthesized one derived from the status, or a synthetic transport\n * code such as \"aborted\" / \"timeout\" / \"network\".\n * - `message`: human-readable description. The API key is never included.\n */\nexport class QLError extends Error {\n readonly status?: number;\n readonly code: string;\n readonly method?: string;\n readonly url?: string;\n /** The raw parsed error body (if any), for advanced inspection. */\n readonly details?: unknown;\n\n constructor(message: string, opts: { status?: number; code: string; context?: QLErrorContext; details?: unknown } = { code: \"internal_error\" }) {\n super(message);\n this.name = \"QLError\";\n this.status = opts.status;\n this.code = opts.code;\n this.method = opts.context?.method;\n this.url = opts.context?.url;\n this.details = opts.details;\n // Restore prototype chain (required when targeting ES5-ish runtimes).\n Object.setPrototypeOf(this, QLError.prototype);\n }\n\n /** True for 401/403 or unauthorized/forbidden codes. */\n get isAuthError(): boolean {\n return this.code === \"unauthorized\" || this.code === \"forbidden\" || this.status === 401 || this.status === 403;\n }\n\n /** True when the request was aborted by the caller. */\n get isAborted(): boolean {\n return this.code === \"aborted\";\n }\n\n /** True when a wait() call exceeded its timeout. */\n get isTimeout(): boolean {\n return this.code === \"timeout\";\n }\n\n /** True for transient network failures (no HTTP response received). */\n get isNetworkError(): boolean {\n return this.code === \"network\";\n }\n}\n\n/** Map an HTTP status to a stable API error code when the body has none. */\nexport function codeFromStatus(status: number): ApiErrorCode | \"conflict\" {\n switch (status) {\n case 400:\n return \"validation_error\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 409:\n return \"conflict\";\n default:\n return status >= 500 ? \"internal_error\" : \"validation_error\";\n }\n}\n\ninterface ParsedErrorBody {\n ok?: boolean;\n error?: { code?: string; message?: string } | string;\n message?: string;\n}\n\n/** Build a QLError from a non-2xx HTTP response. Never includes the API key. */\nexport function toHttpError(status: number, text: string | undefined, ctx: QLErrorContext): QLError {\n let parsed: ParsedErrorBody | null = null;\n if (text) {\n try {\n const j = JSON.parse(text);\n if (j && typeof j === \"object\") parsed = j as ParsedErrorBody;\n } catch {\n parsed = null;\n }\n }\n\n const bodyErr = parsed?.error;\n let code: string | undefined;\n let message: string | undefined;\n if (typeof bodyErr === \"string\") {\n message = bodyErr;\n } else if (bodyErr && typeof bodyErr === \"object\") {\n code = typeof bodyErr.code === \"string\" ? bodyErr.code : undefined;\n message = typeof bodyErr.message === \"string\" ? bodyErr.message : undefined;\n }\n if (!code) code = codeFromStatus(status);\n if (!message) message = (typeof parsed?.message === \"string\" ? parsed.message : undefined) ?? `Request failed with status ${status}`;\n\n return new QLError(message, { status, code, context: ctx, details: parsed ?? undefined });\n}\n\n/** Wrap a low-level fetch/network failure (no HTTP response). */\nexport function toNetworkError(cause: unknown, ctx: QLErrorContext): QLError {\n const aborted = isAbortCause(cause);\n if (aborted) {\n return new QLError(\"Request aborted\", { code: \"aborted\", context: ctx });\n }\n const msg = cause instanceof Error ? cause.message : String(cause);\n return new QLError(`Network error: ${msg}`, { code: \"network\", context: ctx, details: cause });\n}\n\nfunction isAbortCause(cause: unknown): boolean {\n if (!cause) return false;\n if (typeof cause === \"object\") {\n const c = cause as { name?: string; type?: string };\n if (c.name === \"AbortError\" || c.type === \"aborted\") return true;\n }\n return false;\n}\n\n/** Build an abort error for wait()/stream cancellation. */\nexport function abortError(): QLError {\n return new QLError(\"Operation aborted\", { code: \"aborted\" });\n}\n\n/** Build a timeout error for wait(). */\nexport function timeoutError(timeoutMs: number): QLError {\n return new QLError(`Timed out after ${timeoutMs}ms`, { code: \"timeout\" });\n}\n","import { QLError, toHttpError, toNetworkError } from \"./errors.js\";\nimport type { ApiErrorCode } from \"./types.js\";\n\nexport interface TransportOptions {\n apiKey: string;\n baseUrl: string;\n fetchImpl: typeof fetch;\n}\n\nexport interface JsonRequestOptions {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport interface FormRequestOptions {\n form: FormData;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * Internal transport used by the API namespaces. Keeps the API key inside a\n * closure (never exposed) and normalizes responses/errors for the caller.\n */\nexport interface Transport {\n /** Perform a JSON request and return the unwrapped `data` payload. */\n json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;\n /** Perform a multipart/form-data request and return the unwrapped `data` payload. */\n form<T>(path: string, opts: FormRequestOptions): Promise<T>;\n /**\n * Perform a request expected to stream SSE. Returns the response body stream\n * after verifying a 2xx + text/event-stream; throws QLError otherwise.\n */\n stream(method: string, path: string, opts?: JsonRequestOptions & { acceptStream?: boolean }): Promise<ReadableStream<Uint8Array>>;\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n const { apiKey, baseUrl, fetchImpl } = opts;\n\n return {\n async json<T>(method: string, path: string, reqOpts: JsonRequestOptions = {}) {\n const res = await doFetch(method, path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });\n return unwrap<T>(text, { method, url: res.url });\n },\n\n async form<T>(path: string, reqOpts: FormRequestOptions) {\n const res = await doFormFetch(path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method: \"POST\", url: res.url });\n return unwrap<T>(text, { method: \"POST\", url: res.url });\n },\n\n async stream(method, path, reqOpts = {}) {\n const res = await doFetch(method, path, {\n ...reqOpts,\n headers: { accept: \"text/event-stream\", ...(reqOpts.headers ?? {}) },\n });\n if (!res.ok) {\n const text = await res.text().catch(() => undefined);\n throw toHttpError(res.status, text, { method, url: res.url });\n }\n const ctype = (res.headers.get(\"content-type\") || \"\").toLowerCase();\n if (!ctype.includes(\"text/event-stream\")) {\n // The endpoint returned a non-SSE body (e.g. an error envelope). Surface it.\n const text = await res.text().catch(() => undefined);\n throw new QLError(`Expected text/event-stream but got \"${ctype || \"unknown\"}\"`, {\n status: res.status,\n code: \"internal_error\",\n context: { method, url: res.url },\n details: safeParse(text),\n });\n }\n if (!res.body) throw new QLError(\"Response has no readable body stream\", { code: \"network\", context: { method, url: res.url } });\n return res.body;\n },\n };\n\n function doFetch(method: string, path: string, reqOpts: JsonRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path, reqOpts.query);\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method,\n headers,\n body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method, url });\n });\n }\n\n function doFormFetch(path: string, reqOpts: FormRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path);\n // No content-type header here — fetch sets the multipart boundary itself.\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method: \"POST\",\n headers,\n body: reqOpts.form,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method: \"POST\", url });\n });\n }\n}\n\nfunction unwrap<T>(text: string, ctx: { method?: string; url?: string }): T {\n const parsed = safeParse(text);\n if (parsed && typeof parsed === \"object\" && \"ok\" in (parsed as Record<string, unknown>)) {\n const env = parsed as { ok: boolean; data?: unknown; error?: { code?: string; message?: string } };\n if (env.ok === true) return env.data as T;\n // ok:false on a 2xx — treat as an application error.\n throw new QLError(env.error?.message || \"Request failed\", {\n code: (env.error?.code as ApiErrorCode) || \"internal_error\",\n context: ctx,\n details: env,\n });\n }\n // Non-enveloped payload (legacy shapes): return as-is.\n return parsed as T;\n}\n\nfunction safeParse(text?: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Join base + path and append a query string (skipping undefined values). */\nexport function buildUrl(baseUrl: string, path: string, query?: Record<string, string | number | undefined>): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const p = path.startsWith(\"/\") ? path : `/${path}`;\n let url = `${base}${p}`;\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n }\n return url;\n}\n\n/** Normalize a base URL: trim whitespace and drop any trailing slash. */\nexport function normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n","/**\n * Minimal, dependency-free Server-Sent Events reader built on Web Streams.\n *\n * Handles the cases that commonly break naive parsers:\n * - a `data:` line split across two TCP chunks (chunk boundaries)\n * - multiple events arriving in a single chunk\n * - both CRLF and LF line endings (and lone CR)\n * - a final event that is not terminated by a trailing newline\n * - the `[DONE]` terminator\n * - abort signals\n */\n\nexport interface SSEEvent {\n /** The concatenated `data:` payload for this event (trimmed of the leading space). */\n data: string;\n}\n\ninterface ReadOptions {\n signal?: AbortSignal;\n /** When true, stop after the first `[DONE]` data value. Default true. */\n stopOnDone?: boolean;\n}\n\n/**\n * Read raw SSE events from a `ReadableStream<Uint8Array>`.\n * Yields one object per event with its combined `data` payload.\n */\nexport async function* readSSEEvents(\n body: ReadableStream<Uint8Array>,\n opts: ReadOptions = {},\n): AsyncGenerator<SSEEvent, void, unknown> {\n const stopOnDone = opts.stopOnDone ?? true;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let dataLines: string[] = [];\n\n // Abort wiring: cancel the underlying stream promptly when the signal fires.\n const onAbort = () => {\n void reader.cancel().catch(() => {});\n };\n if (opts.signal) {\n if (opts.signal.aborted) {\n await reader.cancel().catch(() => {});\n return;\n }\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n const dispatch = (): SSEEvent | null => {\n if (dataLines.length === 0) return null;\n const data = dataLines.join(\"\\n\");\n dataLines = [];\n return { data };\n };\n\n const processLine = (line: string): SSEEvent | null => {\n if (line === \"\") return dispatch(); // blank line = event boundary\n if (line.startsWith(\":\")) return null; // comment\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) value = value.slice(1);\n dataLines.push(value);\n return null;\n }\n // Ignore event:/id:/retry: and unknown fields.\n return null;\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let s = splitFirstLine(buffer);\n while (s !== null) {\n const ev = processLine(s.line);\n if (ev) {\n if (stopOnDone && ev.data.trim() === \"[DONE]\") return;\n yield ev;\n }\n buffer = s.rest;\n s = splitFirstLine(buffer);\n }\n }\n\n // Flush any bytes still held by the decoder.\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const ev = processLine(buffer);\n if (ev && !(stopOnDone && ev.data.trim() === \"[DONE]\")) yield ev;\n }\n // Flush a final event that had no terminating blank line.\n const tail = dispatch();\n if (tail && !(stopOnDone && tail.data.trim() === \"[DONE]\")) yield tail;\n } finally {\n if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n try {\n reader.releaseLock();\n } catch {\n /* already released */\n }\n }\n}\n\n/** Split the first complete line (LF, CRLF, or lone CR) out of `buf`. */\nfunction splitFirstLine(buf: string): { line: string; rest: string } | null {\n const nl = buf.indexOf(\"\\n\");\n const cr = buf.indexOf(\"\\r\");\n let end = -1;\n let termLen = 0;\n if (nl !== -1 && (cr === -1 || nl < cr)) {\n end = nl;\n termLen = 1;\n } else if (cr !== -1) {\n end = cr;\n termLen = buf[cr + 1] === \"\\n\" ? 2 : 1;\n }\n if (end === -1) return null;\n return { line: buf.slice(0, end), rest: buf.slice(end + termLen) };\n}\n\n/** Parse a single SSE `data` payload as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n const trimmed = data.trim();\n if (trimmed === \"\" || trimmed === \"[DONE]\") return null;\n try {\n return JSON.parse(trimmed) as T;\n } catch {\n return null; // malformed JSON is skipped, not fatal\n }\n}\n","import type { Transport } from \"./http.js\";\nimport { abortError, timeoutError } from \"./errors.js\";\nimport type { Task, WaitOptions, VideoTask, VideoWaitOptions } from \"./types.js\";\n\n/** Statuses at which a job will not change again (shared by tasks and video jobs). */\nconst TERMINAL_TASK_STATUSES = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\nexport function isTerminalTaskStatus(status: string): boolean {\n return TERMINAL_TASK_STATUSES.has(status);\n}\n\ninterface PollOptions {\n intervalMs?: number;\n maxIntervalMs?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Shared polling loop used by TaskHandle.wait() and VideoTaskHandle.wait().\n *\n * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.\n * - Throws a QLError with code \"timeout\" if `timeoutMs` elapses first.\n * - Throws a QLError with code \"aborted\" if `signal` aborts.\n */\nasync function pollUntilTerminal<T>(\n fetchSnapshot: (signal?: AbortSignal) => Promise<T>,\n isTerminal: (snapshot: T) => boolean,\n onTick: ((snapshot: T) => void) | undefined,\n opts: PollOptions,\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? 2000;\n const maxIntervalMs = opts.maxIntervalMs ?? 15000;\n const signal = opts.signal;\n const startedAt = Date.now();\n let delay = intervalMs;\n\n for (;;) {\n if (signal?.aborted) throw abortError();\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n const snapshot = await fetchSnapshot(signal);\n onTick?.(snapshot);\n if (isTerminal(snapshot)) return snapshot;\n\n // Recompute timeout after the poll so a slow request doesn't overshoot silently.\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n await sleep(delay, signal);\n delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));\n }\n}\n\n/**\n * A handle to a background task created via `tasks.create`.\n *\n * NOTE on execution: creating a task only enqueues it. It may stay in the\n * `queued` state until an existing worker/execution mechanism processes it —\n * this SDK does not trigger execution. `wait()` simply polls until the task\n * reaches a terminal status (or you time out / abort).\n */\nexport class TaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current task snapshot (single request). */\n get(signal?: AbortSignal): Promise<Task> {\n return this.transport.json<Task>(\"GET\", `/api/v1/tasks/${this.taskId}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<Task> {\n return this.get(signal);\n }\n\n /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */\n async wait(opts: WaitOptions = {}): Promise<Task> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/**\n * A handle to a video job created via `videos.generate`.\n * Polls the video-tasks endpoint until the job reaches a terminal status.\n */\nexport class VideoTaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current job snapshot (single request). */\n get(signal?: AbortSignal): Promise<VideoTask> {\n return this.transport.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<VideoTask> {\n return this.get(signal);\n }\n\n /** Poll until the job reaches a terminal status (completed/failed/cancelled). */\n async wait(opts: VideoWaitOptions = {}): Promise<VideoTask> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/** Abort-aware sleep. Rejects with an abort error if `signal` fires first. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n };\n if (signal) signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { createTransport, normalizeUrl, type Transport } from \"./http.js\";\nimport { QLError } from \"./errors.js\";\nimport { readSSEEvents, parseSSEData } from \"./sse.js\";\nimport { TaskHandle, VideoTaskHandle } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CatalogResult,\n CapabilitiesResult,\n CreateKeyInput,\n CreateKeyResult,\n DeleteKeyResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelsResult,\n KeysResult,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n TtsInput,\n TtsResult,\n UploadedFile,\n FileUploadOptions,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n VerifyKeyResult,\n VideoGenerateInput,\n VideoModelsResult,\n VideoTask,\n VideoTaskCreated,\n VoicesResult,\n WorkspaceModelsResult,\n WorkspaceModelsUpdateInput,\n WorkspaceUpdateInput,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n\n /** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */\n getModels(): Promise<WorkspaceModelsResult> {\n return this.t.json<WorkspaceModelsResult>(\"GET\", \"/api/v1/workspace/models\");\n }\n\n /** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */\n update(input: WorkspaceUpdateInput): Promise<Workspace> {\n return this.t.json<Workspace>(\"PATCH\", \"/api/v1/workspace\", { body: input });\n }\n\n /** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */\n updateModels(input: WorkspaceModelsUpdateInput): Promise<Workspace> {\n return this.t.json<Workspace>(\"PATCH\", \"/api/v1/workspace\", { body: { config: { openrouter: input } } });\n }\n\n /** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */\n listCatalogModels(): Promise<CatalogResult> {\n return this.t.json<CatalogResult>(\"GET\", \"/api/v1/workspace/models/catalog\");\n }\n\n /** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */\n verifyOpenRouterKey(key: string, model?: string, baseUrl?: string): Promise<VerifyKeyResult> {\n return this.t.json<VerifyKeyResult>(\"POST\", \"/api/v1/workspace/models/verify\", { body: { key, model, baseUrl } });\n }\n\n /** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */\n listKeys(): Promise<KeysResult> {\n return this.t.json<KeysResult>(\"GET\", \"/api/v1/workspace/keys\");\n }\n\n /**\n * POST /api/v1/workspace/keys — mint a new API key for the workspace.\n * All expired, non-revoked keys (issued and legacy) are discarded first, so a\n * rotation is one call. The raw `secret` is returned exactly once.\n */\n createKey(input?: CreateKeyInput): Promise<CreateKeyResult> {\n return this.t.json<CreateKeyResult>(\"POST\", \"/api/v1/workspace/keys\", { body: input ?? {} });\n }\n\n /** DELETE /api/v1/workspace/keys/:keyId — delete an issued or legacy key. */\n deleteKey(keyId: string): Promise<DeleteKeyResult> {\n return this.t.json<DeleteKeyResult>(\"DELETE\", `/api/v1/workspace/keys/${encodeURIComponent(keyId)}`);\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\n/** Videos namespace (tiered video generation: submit → poll). */\nexport class VideosApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/videos/models — list tiered video models + engine availability. */\n listModels(): Promise<VideoModelsResult> {\n return this.t.json<VideoModelsResult>(\"GET\", \"/api/v1/videos/models\");\n }\n\n /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */\n generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated> {\n return this.t.json<VideoTaskCreated>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });\n }\n\n /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */\n getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */\n cancelTask(taskId: string): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"DELETE\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);\n }\n\n /** Get a handle for polling / waiting on a video job (poll(), wait()). */\n handle(taskId: string): VideoTaskHandle {\n return new VideoTaskHandle(this.t, taskId);\n }\n}\n\n/** Audio namespace (text-to-speech). */\nexport class AudioApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/audio/voices — list available TTS voices. */\n voices(): Promise<VoicesResult> {\n return this.t.json<VoicesResult>(\"GET\", \"/api/v1/audio/voices\");\n }\n\n /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */\n textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult> {\n return this.t.json<TtsResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });\n }\n}\n\n/** Files namespace (media uploads). */\nexport class FilesApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/files — upload a media file (multipart field \"file\"). */\n async upload(file: Blob, opts: FileUploadOptions = {}): Promise<UploadedFile> {\n const form = new FormData();\n if (opts.filename !== undefined) {\n form.append(\"file\", file, opts.filename);\n } else {\n form.append(\"file\", file);\n }\n // Coarse progress only: fetch does not expose upload byte progress.\n opts.onProgress?.(0);\n const result = await this.t.form<UploadedFile>(\"/api/v1/files\", { form });\n opts.onProgress?.(100);\n return result;\n }\n}\n\nfunction readEnvBaseUrl(): string | undefined {\n try {\n if (typeof process !== \"undefined\" && process?.env) {\n return process.env.QL_BASE_URL || undefined;\n }\n } catch {\n /* non-Node runtime */\n }\n return undefined;\n}\n\n/**\n * The public client. Example:\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });\n * const agents = await ql.agents.list();\n */\nexport class QLClient {\n readonly workspace: WorkspaceApi;\n readonly agents: AgentsApi;\n readonly workflows: WorkflowsApi;\n readonly tasks: TasksApi;\n readonly images: ImagesApi;\n readonly videos: VideosApi;\n readonly audio: AudioApi;\n readonly files: FilesApi;\n\n private readonly transport: Transport;\n private readonly base: string;\n\n constructor(opts: QLClientOptions) {\n if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.length === 0) {\n throw new QLError(\"apiKey is required\", { code: \"validation_error\" });\n }\n this.base = normalizeUrl(opts.baseUrl ?? readEnvBaseUrl() ?? DEFAULT_BASE_URL);\n const fetchImpl = (opts.fetch ?? globalThis.fetch).bind(globalThis);\n this.transport = createTransport({ apiKey: opts.apiKey, baseUrl: this.base, fetchImpl });\n this.workspace = new WorkspaceApi(this.transport);\n this.agents = new AgentsApi(this.transport);\n this.workflows = new WorkflowsApi(this.transport);\n this.tasks = new TasksApi(this.transport);\n this.images = new ImagesApi(this.transport);\n this.videos = new VideosApi(this.transport);\n this.audio = new AudioApi(this.transport);\n this.files = new FilesApi(this.transport);\n }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter model id override — wins over the workspace director-panel default. */\n modelId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */\n modelId?: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Videos — tiered video generation (async: submit → poll)\n// ---------------------------------------------------------------------------\n\nexport type VideoTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for a video model. */\nexport interface VideoPricingEntry {\n /** What is billed, e.g. \"output_video\" / \"voiceover\". */\n billable: string;\n /** Billing unit: per rendered second, or flat per request. */\n unit: \"second\" | \"request\";\n costUsd: number;\n}\n\n/** A tiered video-generation model as returned by `videos.listModels`. */\nexport interface VideoModelInfo {\n id: string;\n name: string;\n tier: VideoTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n /** Execution engine (e.g. \"motion-graphics\"). */\n engine: string;\n supportsProductImages: boolean;\n maxReferenceImages: number;\n supportsReferenceVideos: boolean;\n maxReferenceVideos: number;\n supportedAspectRatios: string[];\n supportedResolutions: string[];\n /** Inclusive [min, max] duration in seconds. */\n durationRange: [number, number];\n voiceoverSupport: boolean;\n pricing: {\n summary: string;\n entries: VideoPricingEntry[];\n };\n recommended: boolean;\n enabled: boolean;\n /** Runtime engine availability (render toolchain present). */\n available: boolean;\n}\n\n/** Result of `videos.listModels`. */\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n}\n\n/** Input for `videos.generate`. */\nexport interface VideoGenerateInput {\n /** The creative brief / script for the video. */\n prompt: string;\n /** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */\n modelId?: string;\n /** Explicit registry model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: VideoTier | string;\n /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */\n images_list?: string[];\n /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */\n video_files?: string[];\n /** e.g. \"16:9\", \"9:16\", \"1:1\". Default \"16:9\". */\n aspect_ratio?: string;\n /** Duration in seconds (must be within the model's durationRange). */\n duration?: number;\n /** e.g. \"720p\" | \"1080p\". Default \"720p\". */\n resolution?: string;\n /** Bake an ElevenLabs voiceover into the render (requires `narration`). */\n generate_audio?: boolean;\n /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */\n narration?: string;\n}\n\n/** Returned when a video job is created (HTTP 202). */\nexport interface VideoTaskCreated {\n taskId: string;\n status: \"queued\";\n}\n\nexport type VideoTaskStatus =\n | \"queued\"\n | \"rendering\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A video job snapshot, as returned by `videos.getTask`. */\nexport interface VideoTask {\n taskId: string;\n status: VideoTaskStatus;\n progress?: {\n current: number;\n total: number;\n message?: string;\n };\n /** Served media path (e.g. /generated/video-….mp4) once completed. */\n outputUrl?: string;\n mime?: string;\n ext?: string;\n /** Actual rendered duration in seconds. */\n durationSec?: number;\n error?: string;\n model?: string;\n tier?: string;\n latencyMs?: number;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a video job. */\nexport interface VideoWaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest job snapshot. */\n onTick?: (task: VideoTask) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Audio — text-to-speech\n// ---------------------------------------------------------------------------\n\n// ─── Workspace model configuration (director panel) ──────────────────────\n\n/** Per-role model defaults as configured in the director panel. */\nexport interface WorkspaceModelConfig {\n status: \"active\" | \"inactive\";\n /** Masked OpenRouter key — the raw key is never returned by the API. */\n keyMasked: string;\n /** Optional chat-completions base URL override (empty = public OpenRouter API). */\n baseUrl: string;\n reasoning: string;\n instruct: string;\n response: string;\n vision: string;\n image: string;\n video: string;\n /** Ordered per-role fallback model ids (max 3 each), tried on provider failure. */\n fallbacks: {\n reasoning: string[];\n instruct: string[];\n response: string[];\n vision: string[];\n image: string[];\n video: string[];\n };\n}\n\n/** Result of `workspace.getModels`. */\nexport interface WorkspaceModelsResult {\n openrouter: WorkspaceModelConfig;\n}\n\n/** Partial model-config update for `workspace.update` / `workspace.updateModels`. */\nexport interface WorkspaceModelsUpdateInput {\n status?: \"active\" | \"inactive\";\n /** Full OpenRouter API key to store/rotate. Omit to leave unchanged. */\n key?: string;\n /** Optional chat-completions base URL override (defaults to the public OpenRouter API). */\n baseUrl?: string;\n reasoning?: string;\n instruct?: string;\n response?: string;\n vision?: string;\n image?: string;\n video?: string;\n /** Ordered per-role fallback model ids (max 3 each). */\n fallbacks?: {\n reasoning?: string[];\n instruct?: string[];\n response?: string[];\n vision?: string[];\n image?: string[];\n video?: string[];\n };\n}\n\n/** Input for `workspace.update`. */\nexport interface WorkspaceUpdateInput {\n name?: string;\n config?: { openrouter?: WorkspaceModelsUpdateInput };\n}\n\n/** A single OpenRouter catalog model. */\nexport interface CatalogModel {\n id: string;\n name: string;\n contextLength: number | null;\n promptPrice: number | null;\n completionPrice: number | null;\n}\n\n/** Result of `workspace.listCatalogModels`. */\nexport interface CatalogResult {\n models: CatalogModel[];\n /** True when the upstream fetch failed and a cached snapshot was served. */\n stale?: boolean;\n}\n\n/** Result of `workspace.verifyOpenRouterKey`. */\nexport interface VerifyKeyResult {\n valid: boolean;\n error?: string;\n}\n\n/** A v1 API key with rotation metadata (hashes never leave the server). */\nexport interface ApiKeyInfo {\n _id: string;\n name: string;\n prefix: string;\n scopes: string[];\n createdAt: string | Date;\n lastUsedAt: string | Date | null;\n revokedAt: string | Date | null;\n /** When the key is auto-deleted (createdAt + lifetime). */\n rotatesAt: string | Date;\n /** Whole days remaining until rotation (0 when expired). */\n daysLeft: number;\n}\n\n/** Result of `workspace.listKeys`. */\nexport interface KeysResult {\n /** Key lifetime in days before auto-deletion. */\n lifetimeDays: number;\n keys: ApiKeyInfo[];\n}\n\n/** Input for `workspace.createKey`. */\nexport interface CreateKeyInput {\n /** Display name for the key (defaults to \"API Key\" server-side). */\n name?: string;\n}\n\n/** A freshly minted key. `secret` is the raw key — shown exactly once, never stored in plaintext. */\nexport interface MintedKey {\n id: string;\n name: string;\n prefix: string;\n secret: string;\n}\n\n/** An expired key that was discarded automatically when a new key was minted. */\nexport interface DiscardedKey {\n _id?: string;\n name: string;\n prefix: string;\n /** True when the key was embedded on the workspace document (pre-ApiKey-collection era). */\n legacy: boolean;\n}\n\n/** Result of `workspace.createKey`. */\nexport interface CreateKeyResult {\n key: MintedKey;\n /** Expired, non-revoked keys discarded as part of the rotation. */\n discarded: DiscardedKey[];\n}\n\n/** Result of `workspace.deleteKey`. */\nexport interface DeleteKeyResult {\n deleted: {\n id: string;\n name: string;\n prefix: string;\n legacy: boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n\n/** Input for `audio.textToSpeech`. */\nexport interface TtsInput {\n /** Text to synthesize (max 3000 chars). */\n text: string;\n /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */\n voiceId?: string;\n /** Voice stability 0..1 (default 0.5). */\n stability?: number;\n /** Similarity boost 0..1 (default 0.75). */\n similarityBoost?: number;\n}\n\n/** Result of `audio.textToSpeech`. */\nexport interface TtsResult {\n /** Served audio path (e.g. /generated/tts-….mp3). */\n url: string;\n voiceId: string;\n modelId: string;\n bytes: number;\n latencyMs: number;\n}\n\n/** A single ElevenLabs voice as returned by `audio.voices`. */\nexport interface VoiceInfo {\n id: string;\n name: string;\n}\n\n/** Result of `audio.voices`. */\nexport interface VoicesResult {\n voices: VoiceInfo[];\n /** \"live\" = fetched from the provider; \"none\" = no provider key configured. */\n source: \"live\" | \"none\";\n note?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Files — media uploads\n// ---------------------------------------------------------------------------\n\n/** Result of `files.upload`. */\nexport interface UploadedFile {\n /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */\n url: string;\n filename: string;\n size: number;\n contentType: string;\n}\n\n/** Options for `files.upload`. */\nexport interface FileUploadOptions {\n /** Override the stored display name (extension is kept from the file). */\n filename?: string;\n /**\n * Coarse progress callback. Fetch does not expose upload byte progress, so this\n * reports 0 at start and 100 on completion.\n */\n onProgress?: (percent: number) => void;\n}\n"],"mappings":";AAgBO,IAAM,UAAN,MAAM,iBAAgB,MAAM;AAAA,EAQjC,YAAY,SAAiB,OAAuF,EAAE,MAAM,iBAAiB,GAAG;AAC9I,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,OAAO,KAAK;AACjB,SAAK,SAAS,KAAK,SAAS;AAC5B,SAAK,MAAM,KAAK,SAAS;AACzB,SAAK,UAAU,KAAK;AAEpB,WAAO,eAAe,MAAM,SAAQ,SAAS;AAAA,EAC/C;AAAA;AAAA,EAGA,IAAI,cAAuB;AACzB,WAAO,KAAK,SAAS,kBAAkB,KAAK,SAAS,eAAe,KAAK,WAAW,OAAO,KAAK,WAAW;AAAA,EAC7G;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA,EAGA,IAAI,iBAA0B;AAC5B,WAAO,KAAK,SAAS;AAAA,EACvB;AACF;AAGO,SAAS,eAAe,QAA2C;AACxE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,UAAU,MAAM,mBAAmB;AAAA,EAC9C;AACF;AASO,SAAS,YAAY,QAAgB,MAA0B,KAA8B;AAClG,MAAI,SAAiC;AACrC,MAAI,MAAM;AACR,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,IAAI;AACzB,UAAI,KAAK,OAAO,MAAM,SAAU,UAAS;AAAA,IAC3C,QAAQ;AACN,eAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ;AACxB,MAAI;AACJ,MAAI;AACJ,MAAI,OAAO,YAAY,UAAU;AAC/B,cAAU;AAAA,EACZ,WAAW,WAAW,OAAO,YAAY,UAAU;AACjD,WAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AACzD,cAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU;AAAA,EACpE;AACA,MAAI,CAAC,KAAM,QAAO,eAAe,MAAM;AACvC,MAAI,CAAC,QAAS,YAAW,OAAO,QAAQ,YAAY,WAAW,OAAO,UAAU,WAAc,8BAA8B,MAAM;AAElI,SAAO,IAAI,QAAQ,SAAS,EAAE,QAAQ,MAAM,SAAS,KAAK,SAAS,UAAU,OAAU,CAAC;AAC1F;AAGO,SAAS,eAAe,OAAgB,KAA8B;AAC3E,QAAM,UAAU,aAAa,KAAK;AAClC,MAAI,SAAS;AACX,WAAO,IAAI,QAAQ,mBAAmB,EAAE,MAAM,WAAW,SAAS,IAAI,CAAC;AAAA,EACzE;AACA,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,SAAO,IAAI,QAAQ,kBAAkB,GAAG,IAAI,EAAE,MAAM,WAAW,SAAS,KAAK,SAAS,MAAM,CAAC;AAC/F;AAEA,SAAS,aAAa,OAAyB;AAC7C,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,gBAAgB,EAAE,SAAS,UAAW,QAAO;AAAA,EAC9D;AACA,SAAO;AACT;AAGO,SAAS,aAAsB;AACpC,SAAO,IAAI,QAAQ,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAC7D;AAGO,SAAS,aAAa,WAA4B;AACvD,SAAO,IAAI,QAAQ,mBAAmB,SAAS,MAAM,EAAE,MAAM,UAAU,CAAC;AAC1E;;;ACjGO,SAAS,gBAAgB,MAAmC;AACjE,QAAM,EAAE,QAAQ,SAAS,UAAU,IAAI;AAEvC,SAAO;AAAA,IACL,MAAM,KAAQ,QAAgB,MAAc,UAA8B,CAAC,GAAG;AAC5E,YAAM,MAAM,MAAM,QAAQ,QAAQ,MAAM,OAAO;AAC/C,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,OAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AACzE,aAAO,OAAU,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,IACjD;AAAA,IAEA,MAAM,KAAQ,MAAc,SAA6B;AACvD,YAAM,MAAM,MAAM,YAAY,MAAM,OAAO;AAC3C,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,OAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,QAAQ,KAAK,IAAI,IAAI,CAAC;AACjF,aAAO,OAAU,MAAM,EAAE,QAAQ,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,IACzD;AAAA,IAEA,MAAM,OAAO,QAAQ,MAAM,UAAU,CAAC,GAAG;AACvC,YAAM,MAAM,MAAM,QAAQ,QAAQ,MAAM;AAAA,QACtC,GAAG;AAAA,QACH,SAAS,EAAE,QAAQ,qBAAqB,GAAI,QAAQ,WAAW,CAAC,EAAG;AAAA,MACrE,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,MAAS;AACnD,cAAM,YAAY,IAAI,QAAQ,MAAM,EAAE,QAAQ,KAAK,IAAI,IAAI,CAAC;AAAA,MAC9D;AACA,YAAM,SAAS,IAAI,QAAQ,IAAI,cAAc,KAAK,IAAI,YAAY;AAClE,UAAI,CAAC,MAAM,SAAS,mBAAmB,GAAG;AAExC,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,MAAS;AACnD,cAAM,IAAI,QAAQ,uCAAuC,SAAS,SAAS,KAAK;AAAA,UAC9E,QAAQ,IAAI;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,EAAE,QAAQ,KAAK,IAAI,IAAI;AAAA,UAChC,SAAS,UAAU,IAAI;AAAA,QACzB,CAAC;AAAA,MACH;AACA,UAAI,CAAC,IAAI,KAAM,OAAM,IAAI,QAAQ,wCAAwC,EAAE,MAAM,WAAW,SAAS,EAAE,QAAQ,KAAK,IAAI,IAAI,EAAE,CAAC;AAC/H,aAAO,IAAI;AAAA,IACb;AAAA,EACF;AAEA,WAAS,QAAQ,QAAgB,MAAc,SAAgD;AAC7F,UAAM,MAAM,SAAS,SAAS,MAAM,QAAQ,KAAK;AACjD,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,MAAM;AAAA,MAC/B,QAAQ;AAAA,MACR,GAAI,QAAQ,SAAS,SAAY,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,MAC3E,GAAI,QAAQ,WAAW,CAAC;AAAA,IAC1B;AACA,WAAO,UAAU,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,SAAS,SAAY,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,MAClE,QAAQ,QAAQ;AAAA,IAClB,CAAC,EAAE,MAAM,CAAC,QAAQ;AAChB,YAAM,eAAe,KAAK,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,WAAS,YAAY,MAAc,SAAgD;AACjF,UAAM,MAAM,SAAS,SAAS,IAAI;AAElC,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,MAAM;AAAA,MAC/B,QAAQ;AAAA,MACR,GAAI,QAAQ,WAAW,CAAC;AAAA,IAC1B;AACA,WAAO,UAAU,KAAK;AAAA,MACpB,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,IAClB,CAAC,EAAE,MAAM,CAAC,QAAQ;AAChB,YAAM,eAAe,KAAK,EAAE,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AACF;AAEA,SAAS,OAAU,MAAc,KAA2C;AAC1E,QAAM,SAAS,UAAU,IAAI;AAC7B,MAAI,UAAU,OAAO,WAAW,YAAY,QAAS,QAAoC;AACvF,UAAM,MAAM;AACZ,QAAI,IAAI,OAAO,KAAM,QAAO,IAAI;AAEhC,UAAM,IAAI,QAAQ,IAAI,OAAO,WAAW,kBAAkB;AAAA,MACxD,MAAO,IAAI,OAAO,QAAyB;AAAA,MAC3C,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,UAAU,MAAwB;AACzC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,SAAS,SAAiB,MAAc,OAA6D;AACnH,QAAM,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACvC,QAAM,IAAI,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAChD,MAAI,MAAM,GAAG,IAAI,GAAG,CAAC;AACrB,MAAI,OAAO;AACT,UAAM,SAAS,IAAI,gBAAgB;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAI,UAAU,UAAa,UAAU,KAAM,QAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAC1E;AACA,UAAM,KAAK,OAAO,SAAS;AAC3B,QAAI,GAAI,QAAO,IAAI,EAAE;AAAA,EACvB;AACA,SAAO;AACT;AAGO,SAAS,aAAa,KAAqB;AAChD,SAAO,IAAI,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACtC;;;ACvIA,gBAAuB,cACrB,MACA,OAAoB,CAAC,GACoB;AACzC,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,MAAI,YAAsB,CAAC;AAG3B,QAAM,UAAU,MAAM;AACpB,SAAK,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACrC;AACA,MAAI,KAAK,QAAQ;AACf,QAAI,KAAK,OAAO,SAAS;AACvB,YAAM,OAAO,OAAO,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpC;AAAA,IACF;AACA,SAAK,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC/D;AAEA,QAAM,WAAW,MAAuB;AACtC,QAAI,UAAU,WAAW,EAAG,QAAO;AACnC,UAAM,OAAO,UAAU,KAAK,IAAI;AAChC,gBAAY,CAAC;AACb,WAAO,EAAE,KAAK;AAAA,EAChB;AAEA,QAAM,cAAc,CAAC,SAAkC;AACrD,QAAI,SAAS,GAAI,QAAO,SAAS;AACjC,QAAI,KAAK,WAAW,GAAG,EAAG,QAAO;AACjC,QAAI,KAAK,WAAW,OAAO,GAAG;AAC5B,UAAI,QAAQ,KAAK,MAAM,CAAC;AACxB,UAAI,MAAM,WAAW,GAAG,EAAG,SAAQ,MAAM,MAAM,CAAC;AAChD,gBAAU,KAAK,KAAK;AACpB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,MAAI;AACF,eAAS;AACP,UAAI,KAAK,QAAQ,QAAS;AAC1B,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAEhD,UAAI,IAAI,eAAe,MAAM;AAC7B,aAAO,MAAM,MAAM;AACjB,cAAM,KAAK,YAAY,EAAE,IAAI;AAC7B,YAAI,IAAI;AACN,cAAI,cAAc,GAAG,KAAK,KAAK,MAAM,SAAU;AAC/C,gBAAM;AAAA,QACR;AACA,iBAAS,EAAE;AACX,YAAI,eAAe,MAAM;AAAA,MAC3B;AAAA,IACF;AAGA,cAAU,QAAQ,OAAO;AACzB,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,KAAK,YAAY,MAAM;AAC7B,UAAI,MAAM,EAAE,cAAc,GAAG,KAAK,KAAK,MAAM,UAAW,OAAM;AAAA,IAChE;AAEA,UAAM,OAAO,SAAS;AACtB,QAAI,QAAQ,EAAE,cAAc,KAAK,KAAK,KAAK,MAAM,UAAW,OAAM;AAAA,EACpE,UAAE;AACA,QAAI,KAAK,OAAQ,MAAK,OAAO,oBAAoB,SAAS,OAAO;AACjE,QAAI;AACF,aAAO,YAAY;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAGA,SAAS,eAAe,KAAoD;AAC1E,QAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,QAAM,KAAK,IAAI,QAAQ,IAAI;AAC3B,MAAI,MAAM;AACV,MAAI,UAAU;AACd,MAAI,OAAO,OAAO,OAAO,MAAM,KAAK,KAAK;AACvC,UAAM;AACN,cAAU;AAAA,EACZ,WAAW,OAAO,IAAI;AACpB,UAAM;AACN,cAAU,IAAI,KAAK,CAAC,MAAM,OAAO,IAAI;AAAA,EACvC;AACA,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO,EAAE,MAAM,IAAI,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,MAAM,MAAM,OAAO,EAAE;AACnE;AAGO,SAAS,aAA0B,MAAwB;AAChE,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,MAAM,YAAY,SAAU,QAAO;AACnD,MAAI;AACF,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AChIA,IAAM,yBAAyB,oBAAI,IAAI,CAAC,aAAa,UAAU,WAAW,CAAC;AAEpE,SAAS,qBAAqB,QAAyB;AAC5D,SAAO,uBAAuB,IAAI,MAAM;AAC1C;AAgBA,eAAe,kBACb,eACA,YACA,QACA,MACY;AACZ,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,gBAAgB,KAAK,iBAAiB;AAC5C,QAAM,SAAS,KAAK;AACpB,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI,QAAQ;AAEZ,aAAS;AACP,QAAI,QAAQ,QAAS,OAAM,WAAW;AACtC,QAAI,KAAK,cAAc,UAAa,KAAK,IAAI,IAAI,aAAa,KAAK,WAAW;AAC5E,YAAM,aAAa,KAAK,SAAS;AAAA,IACnC;AAEA,UAAM,WAAW,MAAM,cAAc,MAAM;AAC3C,aAAS,QAAQ;AACjB,QAAI,WAAW,QAAQ,EAAG,QAAO;AAGjC,QAAI,KAAK,cAAc,UAAa,KAAK,IAAI,IAAI,aAAa,KAAK,WAAW;AAC5E,YAAM,aAAa,KAAK,SAAS;AAAA,IACnC;AAEA,UAAM,MAAM,OAAO,MAAM;AACzB,YAAQ,KAAK,IAAI,eAAe,KAAK,MAAM,QAAQ,GAAG,CAAC;AAAA,EACzD;AACF;AAUO,IAAM,aAAN,MAAiB;AAAA,EACtB,YACmB,WACD,QAChB;AAFiB;AACD;AAAA,EACf;AAAA;AAAA,EAGH,IAAI,QAAqC;AACvC,WAAO,KAAK,UAAU,KAAW,OAAO,iBAAiB,KAAK,MAAM,IAAI,EAAE,OAAO,CAAC;AAAA,EACpF;AAAA;AAAA,EAGA,KAAK,QAAqC;AACxC,WAAO,KAAK,IAAI,MAAM;AAAA,EACxB;AAAA;AAAA,EAGA,MAAM,KAAK,OAAoB,CAAC,GAAkB;AAChD,WAAO;AAAA,MACL,CAAC,WAAW,KAAK,IAAI,MAAM;AAAA,MAC3B,CAAC,SAAS,qBAAqB,KAAK,MAAM;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACmB,WACD,QAChB;AAFiB;AACD;AAAA,EACf;AAAA;AAAA,EAGH,IAAI,QAA0C;AAC5C,WAAO,KAAK,UAAU,KAAgB,OAAO,uBAAuB,mBAAmB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EACnH;AAAA;AAAA,EAGA,KAAK,QAA0C;AAC7C,WAAO,KAAK,IAAI,MAAM;AAAA,EACxB;AAAA;AAAA,EAGA,MAAM,KAAK,OAAyB,CAAC,GAAuB;AAC1D,WAAO;AAAA,MACL,CAAC,WAAW,KAAK,IAAI,MAAM;AAAA,MAC3B,CAAC,SAAS,qBAAqB,KAAK,MAAM;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,MAAM,IAAY,QAAqC;AAC9D,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,QAAI,QAAQ,SAAS;AACnB,aAAO,WAAW,CAAC;AACnB;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ;AACR,cAAQ;AAAA,IACV,GAAG,EAAE;AACL,UAAM,UAAU,MAAM;AACpB,mBAAa,KAAK;AAClB,cAAQ;AACR,aAAO,WAAW,CAAC;AAAA,IACrB;AACA,UAAM,UAAU,MAAM;AACpB,UAAI,OAAQ,QAAO,oBAAoB,SAAS,OAAO;AAAA,IACzD;AACA,QAAI,OAAQ,QAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EACtE,CAAC;AACH;;;AClGO,IAAM,mBAAmB;AAYzB,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAE5C,MAA0B;AACxB,WAAO,KAAK,EAAE,KAAgB,OAAO,mBAAmB;AAAA,EAC1D;AAAA;AAAA,EAGA,YAA4C;AAC1C,WAAO,KAAK,EAAE,KAA4B,OAAO,0BAA0B;AAAA,EAC7E;AAAA;AAAA,EAGA,OAAO,OAAiD;AACtD,WAAO,KAAK,EAAE,KAAgB,SAAS,qBAAqB,EAAE,MAAM,MAAM,CAAC;AAAA,EAC7E;AAAA;AAAA,EAGA,aAAa,OAAuD;AAClE,WAAO,KAAK,EAAE,KAAgB,SAAS,qBAAqB,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,MAAM,EAAE,EAAE,CAAC;AAAA,EACzG;AAAA;AAAA,EAGA,oBAA4C;AAC1C,WAAO,KAAK,EAAE,KAAoB,OAAO,kCAAkC;AAAA,EAC7E;AAAA;AAAA,EAGA,oBAAoB,KAAa,OAAgB,SAA4C;AAC3F,WAAO,KAAK,EAAE,KAAsB,QAAQ,mCAAmC,EAAE,MAAM,EAAE,KAAK,OAAO,QAAQ,EAAE,CAAC;AAAA,EAClH;AAAA;AAAA,EAGA,WAAgC;AAC9B,WAAO,KAAK,EAAE,KAAiB,OAAO,wBAAwB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,OAAkD;AAC1D,WAAO,KAAK,EAAE,KAAsB,QAAQ,0BAA0B,EAAE,MAAM,SAAS,CAAC,EAAE,CAAC;AAAA,EAC7F;AAAA;AAAA,EAGA,UAAU,OAAyC;AACjD,WAAO,KAAK,EAAE,KAAsB,UAAU,0BAA0B,mBAAmB,KAAK,CAAC,EAAE;AAAA,EACrG;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,OAAiC;AAC/B,WAAO,KAAK,EAAE,KAAsB,OAAO,gBAAgB;AAAA,EAC7D;AAAA;AAAA,EAGA,IAAI,SAAuC;AACzC,WAAO,KAAK,EAAE,KAAkB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,EAAE;AAAA,EACxF;AAAA;AAAA,EAGA,aAAa,SAA8C;AACzD,WAAO,KAAK,EAAE,KAAyB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,eAAe;AAAA,EAC5G;AAAA;AAAA,EAGA,cAAc,SAAiB,OAAyD;AACtF,WAAO,KAAK,EAAE,KAA0B,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,qBAAqB;AAAA,MAChH,MAAM,EAAE,OAAO,MAAM,OAAO,QAAQ,MAAM,UAAU,CAAC,EAAE;AAAA,IACzD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KAAK,OAAuC;AAC1C,WAAO,KAAK,EAAE,KAAiB,QAAQ,uBAAuB,EAAE,MAAM,MAAM,CAAC;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,OAAkB,OAAsB,CAAC,GAAmC;AACrF,WAAO,KAAK,eAAe,OAAO,IAAI;AAAA,EACxC;AAAA;AAAA,EAGA,QAAQ,SAAiB,SAAwB,CAAC,GAAyB;AACzE,WAAO,KAAK,EAAE,KAAkB,OAAO,kBAAkB,mBAAmB,OAAO,CAAC,aAAa;AAAA,MAC/F,OAAO,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,eAAe,OAAkB,MAAsD;AACpG,UAAM,OAAO,MAAM,KAAK,EAAE,OAAO,QAAQ,8BAA8B,EAAE,MAAM,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC3G,QAAI,UAAU;AACd,QAAI,YAAY;AAChB,qBAAiB,MAAM,cAAc,MAAM,EAAE,QAAQ,KAAK,OAAO,CAAC,GAAG;AACnE,YAAM,UAAU,aAA+G,GAAG,IAAI;AACtI,UAAI,CAAC,QAAS;AACd,YAAM,QAAQ,QAAQ,UAAU,CAAC,GAAG;AACpC,YAAM,OAAO,OAAO,OAAO,YAAY,WAAW,MAAM,UAAU;AAClE,YAAM,SACJ,OAAO,OAAO,cAAc,WACxB,MAAM,YACN,OAAO,OAAO,sBAAsB,WAClC,MAAM,oBACN;AACR,UAAI,KAAM,YAAW;AACrB,UAAI,OAAQ,cAAa;AACzB,UAAI,QAAQ,OAAQ,OAAM,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,OAAO;AAAA,IAC9E;AACA,UAAM,EAAE,MAAM,QAAQ,SAAS,WAAW,aAAa,OAAU;AAAA,EACnE;AACF;AAGO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,IAAI,YAAoB,QAA0B,CAAC,GAA8B;AAC/E,WAAO,KAAK,EAAE,KAAuB,QAAQ,qBAAqB,mBAAmB,UAAU,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,EACzH;AAAA;AAAA,EAGA,OAAO,OAAqC;AAC1C,WAAO,KAAK,EAAE,KAAkB,OAAO,yBAAyB,mBAAmB,KAAK,CAAC,EAAE;AAAA,EAC7F;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,OAAO,OAA8C;AACnD,WAAO,KAAK,EAAE,KAAkB,QAAQ,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAAA,EAC1E;AAAA;AAAA,EAGA,IAAI,QAAgB,QAAqC;AACvD,WAAO,KAAK,EAAE,KAAW,OAAO,iBAAiB,mBAAmB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,OAAO,QAA4B;AACjC,WAAO,IAAI,WAAW,KAAK,GAAG,MAAM;AAAA,EACtC;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,aAAyC;AACvC,WAAO,KAAK,EAAE,KAAwB,OAAO,uBAAuB;AAAA,EACtE;AAAA;AAAA,EAGA,SAAS,SAAiB,OAAyD;AACjF,WAAO,KAAK,EAAE,KAA0B,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;AAAA,EACzH;AACF;AAGO,IAAM,YAAN,MAAgB;AAAA,EACrB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,aAAyC;AACvC,WAAO,KAAK,EAAE,KAAwB,OAAO,uBAAuB;AAAA,EACtE;AAAA;AAAA,EAGA,SAAS,SAAiB,OAAsD;AAC9E,WAAO,KAAK,EAAE,KAAuB,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,WAAW,EAAE,MAAM,MAAM,CAAC;AAAA,EACtH;AAAA;AAAA,EAGA,QAAQ,QAAgB,QAA0C;AAChE,WAAO,KAAK,EAAE,KAAgB,OAAO,uBAAuB,mBAAmB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;AAAA,EACtG;AAAA;AAAA,EAGA,WAAW,QAAoC;AAC7C,WAAO,KAAK,EAAE,KAAgB,UAAU,uBAAuB,mBAAmB,MAAM,CAAC,EAAE;AAAA,EAC7F;AAAA;AAAA,EAGA,OAAO,QAAiC;AACtC,WAAO,IAAI,gBAAgB,KAAK,GAAG,MAAM;AAAA,EAC3C;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,SAAgC;AAC9B,WAAO,KAAK,EAAE,KAAmB,OAAO,sBAAsB;AAAA,EAChE;AAAA;AAAA,EAGA,aAAa,SAAiB,OAAqC;AACjE,WAAO,KAAK,EAAE,KAAgB,QAAQ,kBAAkB,mBAAmB,OAAO,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,EAC5G;AACF;AAGO,IAAM,WAAN,MAAe;AAAA,EACpB,YAA6B,GAAc;AAAd;AAAA,EAAe;AAAA;AAAA,EAG5C,MAAM,OAAO,MAAY,OAA0B,CAAC,GAA0B;AAC5E,UAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,KAAK,aAAa,QAAW;AAC/B,WAAK,OAAO,QAAQ,MAAM,KAAK,QAAQ;AAAA,IACzC,OAAO;AACL,WAAK,OAAO,QAAQ,IAAI;AAAA,IAC1B;AAEA,SAAK,aAAa,CAAC;AACnB,UAAM,SAAS,MAAM,KAAK,EAAE,KAAmB,iBAAiB,EAAE,KAAK,CAAC;AACxE,SAAK,aAAa,GAAG;AACrB,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAqC;AAC5C,MAAI;AACF,QAAI,OAAO,YAAY,eAAe,SAAS,KAAK;AAClD,aAAO,QAAQ,IAAI,eAAe;AAAA,IACpC;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAOO,IAAM,WAAN,MAAe;AAAA,EAapB,YAAY,MAAuB;AACjC,QAAI,CAAC,QAAQ,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,WAAW,GAAG;AACxE,YAAM,IAAI,QAAQ,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAAA,IACtE;AACA,SAAK,OAAO,aAAa,KAAK,WAAW,eAAe,KAAK,gBAAgB;AAC7E,UAAM,aAAa,KAAK,SAAS,WAAW,OAAO,KAAK,UAAU;AAClE,SAAK,YAAY,gBAAgB,EAAE,QAAQ,KAAK,QAAQ,SAAS,KAAK,MAAM,UAAU,CAAC;AACvF,SAAK,YAAY,IAAI,aAAa,KAAK,SAAS;AAChD,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,YAAY,IAAI,aAAa,KAAK,SAAS;AAChD,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AACxC,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,SAAS,IAAI,UAAU,KAAK,SAAS;AAC1C,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AACxC,SAAK,QAAQ,IAAI,SAAS,KAAK,SAAS;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,UAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;;;ACjVO,IAAM,kBAAkB;AAAA,EAC7B,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,eAAe;AACjB;","names":[]}
|