ql-agent-sdk 1.3.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -1
- package/dist/index.cjs +12 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -1
- package/dist/index.d.ts +53 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ Create keys in your Quanton Labs dashboard → **API Keys** page. Each key is sc
|
|
|
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()` |
|
|
81
|
-
| `messages` | `ql.agents.history()` |
|
|
81
|
+
| `messages` | `ql.agents.history()`, `ql.agents.listMessages()` |
|
|
82
82
|
| `workflows` | `ql.workflows.run()`, `ql.workflows.getRun()` |
|
|
83
83
|
| `tasks` | `ql.tasks.create()`, `ql.tasks.get()` |
|
|
84
84
|
| `*` | All of the above (default for new keys) |
|
|
@@ -485,6 +485,74 @@ do {
|
|
|
485
485
|
console.log(`${allMessages.length} total messages`);
|
|
486
486
|
```
|
|
487
487
|
|
|
488
|
+
#### `ql.agents.listMessages(params)` → `Promise<AgentMessagesPage>`
|
|
489
|
+
|
|
490
|
+
**Scope:** `messages`
|
|
491
|
+
|
|
492
|
+
Returns the **chronological message feed** for a conversation — chat turns plus workflow artifacts (tool results, step progress, approval requests). Use this to poll live progress of a background run: call it without `after` for the latest N, then page forward with `after`.
|
|
493
|
+
|
|
494
|
+
**Parameters:**
|
|
495
|
+
- `params.agentId: string` — agent slug or ObjectId (required)
|
|
496
|
+
- `params.after?: string` — cursor = id of the last item you received (forward pagination). Omit for the latest N.
|
|
497
|
+
- `params.limit?: number` — page size, 1–50 (default 20)
|
|
498
|
+
- `params.userId?: string` — optional filter by user (defaults to the workspace id)
|
|
499
|
+
|
|
500
|
+
**Response (200):**
|
|
501
|
+
```json
|
|
502
|
+
{
|
|
503
|
+
"items": [
|
|
504
|
+
{
|
|
505
|
+
"id": "6ae0d963...",
|
|
506
|
+
"role": "user",
|
|
507
|
+
"kind": "chat",
|
|
508
|
+
"content": "Import this CSV into users",
|
|
509
|
+
"status": "completed",
|
|
510
|
+
"timestamp": "2026-11-05T10:00:00.000Z"
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"id": "6ae0d964...",
|
|
514
|
+
"role": "assistant",
|
|
515
|
+
"kind": "workflow",
|
|
516
|
+
"content": null,
|
|
517
|
+
"taskId": "6ae0d965...",
|
|
518
|
+
"toolCalls": [{ "name": "fetch_schema", "status": "completed", "result": { "collections": ["users"] } }],
|
|
519
|
+
"status": "completed",
|
|
520
|
+
"timestamp": "2026-11-05T10:00:02.000Z"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"id": "6ae0d966...",
|
|
524
|
+
"role": "assistant",
|
|
525
|
+
"kind": "approval_request",
|
|
526
|
+
"content": "Delete 3 rows from `users`? ...",
|
|
527
|
+
"outputFormat": "json",
|
|
528
|
+
"status": "completed",
|
|
529
|
+
"timestamp": "2026-11-05T10:00:05.000Z"
|
|
530
|
+
}
|
|
531
|
+
],
|
|
532
|
+
"hasMore": true,
|
|
533
|
+
"nextAfter": "6ae0d966..."
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
| Field | Description |
|
|
538
|
+
|-------|-------------|
|
|
539
|
+
| `items[].kind` | `"chat"` (default), `"tool_result"`, `"workflow"`, or `"approval_request"` |
|
|
540
|
+
| `items[].content` | Message text (may be null for artifact-only entries) |
|
|
541
|
+
| `items[].outputFormat` | Declared format of `content`: `"text"`, `"json"`, or `"html"` |
|
|
542
|
+
| `items[].toolCalls` | Tool invocations; each may carry a truncated `result` once complete |
|
|
543
|
+
| `items[].taskId` | Task id for entries produced by a background workflow run |
|
|
544
|
+
| `hasMore` / `nextAfter` | Forward pagination: pass `nextAfter` as the next `after` |
|
|
545
|
+
|
|
546
|
+
**Polling a live run (e.g. every 4s):**
|
|
547
|
+
```ts
|
|
548
|
+
let after: string | undefined;
|
|
549
|
+
const timer = setInterval(async () => {
|
|
550
|
+
const page = await ql.agents.listMessages({ agentId: "operations", limit: 20, after });
|
|
551
|
+
for (const item of page.items) renderFeedItem(item); // tool chips, step progress, approvals…
|
|
552
|
+
after = page.nextAfter;
|
|
553
|
+
}, 4000);
|
|
554
|
+
```
|
|
555
|
+
|
|
488
556
|
---
|
|
489
557
|
|
|
490
558
|
### Workflows
|
package/dist/index.cjs
CHANGED
|
@@ -517,6 +517,18 @@ var AgentsApi = class {
|
|
|
517
517
|
query: { limit: params.limit, before: params.before, userId: params.userId }
|
|
518
518
|
});
|
|
519
519
|
}
|
|
520
|
+
/**
|
|
521
|
+
* GET /api/v1/agents/messages — chronological message feed for a conversation.
|
|
522
|
+
*
|
|
523
|
+
* Returns the latest N entries in chronological order (omit `after`), or page
|
|
524
|
+
* forward with `after` = id of the last item you received. Includes workflow
|
|
525
|
+
* artifacts: tool results, step progress, and approval requests.
|
|
526
|
+
*/
|
|
527
|
+
listMessages(params) {
|
|
528
|
+
return this.t.json("GET", "/api/v1/agents/messages", {
|
|
529
|
+
query: { agentId: params.agentId, after: params.after, limit: params.limit, userId: params.userId }
|
|
530
|
+
});
|
|
531
|
+
}
|
|
520
532
|
async *chatStreamImpl(input, opts) {
|
|
521
533
|
const body = await this.t.stream("POST", "/api/v1/agents/chat/stream", { body: input, signal: opts.signal });
|
|
522
534
|
let content = "";
|
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 CreateKeyInput,\n CreateKeyResult,\n DeleteKeyResult,\n DiscardedKey,\n MintedKey,\n ChatMessage,\n ChatInput,\n ChatFile,\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<{ type?: string; stage?: string; detail?: string; choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n if (payload.type === \"progress\") {\n yield { type: \"progress\", stage: payload.stage, detail: payload.detail };\n continue;\n }\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 * CSV/TSV attachments (base64 payloads). The backend parses them and hands\n * the rows to the agent's tool loop as structured data for batch processing.\n */\n files?: ChatFile[];\n}\n\n/** A file attachment sent with a chat request (base64 payload; CSV/TSV only). */\nexport interface ChatFile {\n name: string;\n mime?: string;\n dataBase64: string;\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 * - `progress`: tool-loop progress frames (e.g. which tools ran) for long jobs.\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: \"progress\"; stage?: string; detail?: 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`. */\n/** An OpenRouter AI video model (from the public GET /api/v1/videos/models catalog). */\nexport interface OrVideoModel {\n id: string;\n canonical_slug?: string | null;\n hugging_face_id?: string | null;\n name: string;\n created?: number;\n description?: string;\n /** e.g. [\"480p\",\"720p\"] — null when the provider does not publish it. */\n supported_resolutions?: string[] | null;\n /** e.g. [\"16:9\",\"9:16\"] — null when the model decides. */\n supported_aspect_ratios?: string[] | null;\n /** e.g. [\"854x480\",\"1280x720\"]. */\n supported_sizes?: string[] | null;\n /** Discrete list of allowed durations in seconds (e.g. [3,5] or [1..15]). */\n supported_durations?: number[] | null;\n supported_frame_images?: (\"first_frame\" | \"last_frame\")[] | null;\n upscale_factor?: number | null;\n creativity?: number | null;\n /** Native audio generation (null = model decides / unknown). */\n generate_audio?: boolean | null;\n seed?: boolean | null;\n /** Per-SKU price strings — \"cents_*\" keys are in cents, the rest in USD. */\n pricing_skus?: Record<string, string> | null;\n allowed_passthrough_parameters?: string[];\n}\n\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n /** Live OpenRouter AI video catalog (may be empty when the upstream is unreachable). */\n openrouterModels?: OrVideoModel[];\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":[]}
|
|
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 ChatFile,\n ChatResult,\n ChatStreamEvent,\n StreamOptions,\n MessageItem,\n HistoryPage,\n HistoryParams,\n AgentMessageKind,\n AgentMessageOutputFormat,\n AgentFeedToolCall,\n AgentMessageItem,\n AgentMessagesPage,\n AgentMessagesParams,\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 AgentMessagesPage,\n AgentMessagesParams,\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 /**\n * GET /api/v1/agents/messages — chronological message feed for a conversation.\n *\n * Returns the latest N entries in chronological order (omit `after`), or page\n * forward with `after` = id of the last item you received. Includes workflow\n * artifacts: tool results, step progress, and approval requests.\n */\n listMessages(params: AgentMessagesParams): Promise<AgentMessagesPage> {\n return this.t.json<AgentMessagesPage>(\"GET\", \"/api/v1/agents/messages\", {\n query: { agentId: params.agentId, after: params.after, limit: params.limit, 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<{ type?: string; stage?: string; detail?: string; choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n if (payload.type === \"progress\") {\n yield { type: \"progress\", stage: payload.stage, detail: payload.detail };\n continue;\n }\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 * CSV/TSV attachments (base64 payloads). The backend parses them and hands\n * the rows to the agent's tool loop as structured data for batch processing.\n */\n files?: ChatFile[];\n}\n\n/** A file attachment sent with a chat request (base64 payload; CSV/TSV only). */\nexport interface ChatFile {\n name: string;\n mime?: string;\n dataBase64: string;\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 * - `progress`: tool-loop progress frames (e.g. which tools ran) for long jobs.\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: \"progress\"; stage?: string; detail?: 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/** Kinds of entries in the chronological agent message feed. */\nexport type AgentMessageKind = \"chat\" | \"tool_result\" | \"workflow\" | \"approval_request\";\n\n/** Declared output format of a feed message's content, when set. */\nexport type AgentMessageOutputFormat = \"text\" | \"json\" | \"html\";\n\n/** A tool call recorded on a feed message; `result` appears once the call completes (truncated server-side). */\nexport interface AgentFeedToolCall {\n name?: string;\n args?: unknown;\n status?: string;\n error?: string;\n result?: unknown;\n [key: string]: unknown;\n}\n\n/** One entry in the chronological agent message feed (GET /api/v1/agents/messages). */\nexport interface AgentMessageItem {\n id: string;\n role: string;\n kind: AgentMessageKind;\n content: string | null;\n reasoning?: string;\n toolCalls?: AgentFeedToolCall[];\n outputFormat?: AgentMessageOutputFormat;\n taskId?: string;\n status: string;\n timestamp: string | Date;\n}\n\n/** A page of the chronological agent message feed. */\nexport interface AgentMessagesPage {\n items: AgentMessageItem[];\n hasMore: boolean;\n /** Cursor for the next forward page (pass as `after`); undefined when exhausted. */\n nextAfter?: string;\n}\n\n/** Query params for `agents.listMessages`. */\nexport interface AgentMessagesParams {\n /** Platform slug or ObjectId of the agent. Required. */\n agentId: string;\n /** Cursor = id of the last item on the previous page (forward pagination). Omit for the latest N. */\n after?: string;\n /** Page size, 1..50 (default 20 server-side). */\n limit?: number;\n /** Optional internal user id filter (defaults to the workspace id server-side). */\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`. */\n/** An OpenRouter AI video model (from the public GET /api/v1/videos/models catalog). */\nexport interface OrVideoModel {\n id: string;\n canonical_slug?: string | null;\n hugging_face_id?: string | null;\n name: string;\n created?: number;\n description?: string;\n /** e.g. [\"480p\",\"720p\"] — null when the provider does not publish it. */\n supported_resolutions?: string[] | null;\n /** e.g. [\"16:9\",\"9:16\"] — null when the model decides. */\n supported_aspect_ratios?: string[] | null;\n /** e.g. [\"854x480\",\"1280x720\"]. */\n supported_sizes?: string[] | null;\n /** Discrete list of allowed durations in seconds (e.g. [3,5] or [1..15]). */\n supported_durations?: number[] | null;\n supported_frame_images?: (\"first_frame\" | \"last_frame\")[] | null;\n upscale_factor?: number | null;\n creativity?: number | null;\n /** Native audio generation (null = model decides / unknown). */\n generate_audio?: boolean | null;\n seed?: boolean | null;\n /** Per-SKU price strings — \"cents_*\" keys are in cents, the rest in USD. */\n pricing_skus?: Record<string, string> | null;\n allowed_passthrough_parameters?: string[];\n}\n\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n /** Live OpenRouter AI video catalog (may be empty when the upstream is unreachable). */\n openrouterModels?: OrVideoModel[];\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
|
@@ -130,6 +130,50 @@ interface HistoryParams {
|
|
|
130
130
|
/** Optional internal user id filter. */
|
|
131
131
|
userId?: string;
|
|
132
132
|
}
|
|
133
|
+
/** Kinds of entries in the chronological agent message feed. */
|
|
134
|
+
type AgentMessageKind = "chat" | "tool_result" | "workflow" | "approval_request";
|
|
135
|
+
/** Declared output format of a feed message's content, when set. */
|
|
136
|
+
type AgentMessageOutputFormat = "text" | "json" | "html";
|
|
137
|
+
/** A tool call recorded on a feed message; `result` appears once the call completes (truncated server-side). */
|
|
138
|
+
interface AgentFeedToolCall {
|
|
139
|
+
name?: string;
|
|
140
|
+
args?: unknown;
|
|
141
|
+
status?: string;
|
|
142
|
+
error?: string;
|
|
143
|
+
result?: unknown;
|
|
144
|
+
[key: string]: unknown;
|
|
145
|
+
}
|
|
146
|
+
/** One entry in the chronological agent message feed (GET /api/v1/agents/messages). */
|
|
147
|
+
interface AgentMessageItem {
|
|
148
|
+
id: string;
|
|
149
|
+
role: string;
|
|
150
|
+
kind: AgentMessageKind;
|
|
151
|
+
content: string | null;
|
|
152
|
+
reasoning?: string;
|
|
153
|
+
toolCalls?: AgentFeedToolCall[];
|
|
154
|
+
outputFormat?: AgentMessageOutputFormat;
|
|
155
|
+
taskId?: string;
|
|
156
|
+
status: string;
|
|
157
|
+
timestamp: string | Date;
|
|
158
|
+
}
|
|
159
|
+
/** A page of the chronological agent message feed. */
|
|
160
|
+
interface AgentMessagesPage {
|
|
161
|
+
items: AgentMessageItem[];
|
|
162
|
+
hasMore: boolean;
|
|
163
|
+
/** Cursor for the next forward page (pass as `after`); undefined when exhausted. */
|
|
164
|
+
nextAfter?: string;
|
|
165
|
+
}
|
|
166
|
+
/** Query params for `agents.listMessages`. */
|
|
167
|
+
interface AgentMessagesParams {
|
|
168
|
+
/** Platform slug or ObjectId of the agent. Required. */
|
|
169
|
+
agentId: string;
|
|
170
|
+
/** Cursor = id of the last item on the previous page (forward pagination). Omit for the latest N. */
|
|
171
|
+
after?: string;
|
|
172
|
+
/** Page size, 1..50 (default 20 server-side). */
|
|
173
|
+
limit?: number;
|
|
174
|
+
/** Optional internal user id filter (defaults to the workspace id server-side). */
|
|
175
|
+
userId?: string;
|
|
176
|
+
}
|
|
133
177
|
/** Agent summary as returned by `agents.list`. */
|
|
134
178
|
interface AgentSummary {
|
|
135
179
|
id: string;
|
|
@@ -803,6 +847,14 @@ declare class AgentsApi {
|
|
|
803
847
|
chatStream(input: ChatInput, opts?: StreamOptions): AsyncIterable<ChatStreamEvent>;
|
|
804
848
|
/** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */
|
|
805
849
|
history(agentId: string, params?: HistoryParams): Promise<HistoryPage>;
|
|
850
|
+
/**
|
|
851
|
+
* GET /api/v1/agents/messages — chronological message feed for a conversation.
|
|
852
|
+
*
|
|
853
|
+
* Returns the latest N entries in chronological order (omit `after`), or page
|
|
854
|
+
* forward with `after` = id of the last item you received. Includes workflow
|
|
855
|
+
* artifacts: tool results, step progress, and approval requests.
|
|
856
|
+
*/
|
|
857
|
+
listMessages(params: AgentMessagesParams): Promise<AgentMessagesPage>;
|
|
806
858
|
private chatStreamImpl;
|
|
807
859
|
}
|
|
808
860
|
/** Workflows namespace. */
|
|
@@ -922,4 +974,4 @@ declare class QLError extends Error {
|
|
|
922
974
|
get isNetworkError(): boolean;
|
|
923
975
|
}
|
|
924
976
|
|
|
925
|
-
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 ChatFile, 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 };
|
|
977
|
+
export { API_ERROR_CODES, type AgentDetail, type AgentFeedToolCall, type AgentListResult, type AgentMessageItem, type AgentMessageKind, type AgentMessageOutputFormat, type AgentMessagesPage, type AgentMessagesParams, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatFile, 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
|
@@ -130,6 +130,50 @@ interface HistoryParams {
|
|
|
130
130
|
/** Optional internal user id filter. */
|
|
131
131
|
userId?: string;
|
|
132
132
|
}
|
|
133
|
+
/** Kinds of entries in the chronological agent message feed. */
|
|
134
|
+
type AgentMessageKind = "chat" | "tool_result" | "workflow" | "approval_request";
|
|
135
|
+
/** Declared output format of a feed message's content, when set. */
|
|
136
|
+
type AgentMessageOutputFormat = "text" | "json" | "html";
|
|
137
|
+
/** A tool call recorded on a feed message; `result` appears once the call completes (truncated server-side). */
|
|
138
|
+
interface AgentFeedToolCall {
|
|
139
|
+
name?: string;
|
|
140
|
+
args?: unknown;
|
|
141
|
+
status?: string;
|
|
142
|
+
error?: string;
|
|
143
|
+
result?: unknown;
|
|
144
|
+
[key: string]: unknown;
|
|
145
|
+
}
|
|
146
|
+
/** One entry in the chronological agent message feed (GET /api/v1/agents/messages). */
|
|
147
|
+
interface AgentMessageItem {
|
|
148
|
+
id: string;
|
|
149
|
+
role: string;
|
|
150
|
+
kind: AgentMessageKind;
|
|
151
|
+
content: string | null;
|
|
152
|
+
reasoning?: string;
|
|
153
|
+
toolCalls?: AgentFeedToolCall[];
|
|
154
|
+
outputFormat?: AgentMessageOutputFormat;
|
|
155
|
+
taskId?: string;
|
|
156
|
+
status: string;
|
|
157
|
+
timestamp: string | Date;
|
|
158
|
+
}
|
|
159
|
+
/** A page of the chronological agent message feed. */
|
|
160
|
+
interface AgentMessagesPage {
|
|
161
|
+
items: AgentMessageItem[];
|
|
162
|
+
hasMore: boolean;
|
|
163
|
+
/** Cursor for the next forward page (pass as `after`); undefined when exhausted. */
|
|
164
|
+
nextAfter?: string;
|
|
165
|
+
}
|
|
166
|
+
/** Query params for `agents.listMessages`. */
|
|
167
|
+
interface AgentMessagesParams {
|
|
168
|
+
/** Platform slug or ObjectId of the agent. Required. */
|
|
169
|
+
agentId: string;
|
|
170
|
+
/** Cursor = id of the last item on the previous page (forward pagination). Omit for the latest N. */
|
|
171
|
+
after?: string;
|
|
172
|
+
/** Page size, 1..50 (default 20 server-side). */
|
|
173
|
+
limit?: number;
|
|
174
|
+
/** Optional internal user id filter (defaults to the workspace id server-side). */
|
|
175
|
+
userId?: string;
|
|
176
|
+
}
|
|
133
177
|
/** Agent summary as returned by `agents.list`. */
|
|
134
178
|
interface AgentSummary {
|
|
135
179
|
id: string;
|
|
@@ -803,6 +847,14 @@ declare class AgentsApi {
|
|
|
803
847
|
chatStream(input: ChatInput, opts?: StreamOptions): AsyncIterable<ChatStreamEvent>;
|
|
804
848
|
/** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */
|
|
805
849
|
history(agentId: string, params?: HistoryParams): Promise<HistoryPage>;
|
|
850
|
+
/**
|
|
851
|
+
* GET /api/v1/agents/messages — chronological message feed for a conversation.
|
|
852
|
+
*
|
|
853
|
+
* Returns the latest N entries in chronological order (omit `after`), or page
|
|
854
|
+
* forward with `after` = id of the last item you received. Includes workflow
|
|
855
|
+
* artifacts: tool results, step progress, and approval requests.
|
|
856
|
+
*/
|
|
857
|
+
listMessages(params: AgentMessagesParams): Promise<AgentMessagesPage>;
|
|
806
858
|
private chatStreamImpl;
|
|
807
859
|
}
|
|
808
860
|
/** Workflows namespace. */
|
|
@@ -922,4 +974,4 @@ declare class QLError extends Error {
|
|
|
922
974
|
get isNetworkError(): boolean;
|
|
923
975
|
}
|
|
924
976
|
|
|
925
|
-
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 ChatFile, 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 };
|
|
977
|
+
export { API_ERROR_CODES, type AgentDetail, type AgentFeedToolCall, type AgentListResult, type AgentMessageItem, type AgentMessageKind, type AgentMessageOutputFormat, type AgentMessagesPage, type AgentMessagesParams, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatFile, 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
|
@@ -477,6 +477,18 @@ var AgentsApi = class {
|
|
|
477
477
|
query: { limit: params.limit, before: params.before, userId: params.userId }
|
|
478
478
|
});
|
|
479
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* GET /api/v1/agents/messages — chronological message feed for a conversation.
|
|
482
|
+
*
|
|
483
|
+
* Returns the latest N entries in chronological order (omit `after`), or page
|
|
484
|
+
* forward with `after` = id of the last item you received. Includes workflow
|
|
485
|
+
* artifacts: tool results, step progress, and approval requests.
|
|
486
|
+
*/
|
|
487
|
+
listMessages(params) {
|
|
488
|
+
return this.t.json("GET", "/api/v1/agents/messages", {
|
|
489
|
+
query: { agentId: params.agentId, after: params.after, limit: params.limit, userId: params.userId }
|
|
490
|
+
});
|
|
491
|
+
}
|
|
480
492
|
async *chatStreamImpl(input, opts) {
|
|
481
493
|
const body = await this.t.stream("POST", "/api/v1/agents/chat/stream", { body: input, signal: opts.signal });
|
|
482
494
|
let content = "";
|
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 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<{ type?: string; stage?: string; detail?: string; choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n if (payload.type === \"progress\") {\n yield { type: \"progress\", stage: payload.stage, detail: payload.detail };\n continue;\n }\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 * CSV/TSV attachments (base64 payloads). The backend parses them and hands\n * the rows to the agent's tool loop as structured data for batch processing.\n */\n files?: ChatFile[];\n}\n\n/** A file attachment sent with a chat request (base64 payload; CSV/TSV only). */\nexport interface ChatFile {\n name: string;\n mime?: string;\n dataBase64: string;\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 * - `progress`: tool-loop progress frames (e.g. which tools ran) for long jobs.\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: \"progress\"; stage?: string; detail?: 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`. */\n/** An OpenRouter AI video model (from the public GET /api/v1/videos/models catalog). */\nexport interface OrVideoModel {\n id: string;\n canonical_slug?: string | null;\n hugging_face_id?: string | null;\n name: string;\n created?: number;\n description?: string;\n /** e.g. [\"480p\",\"720p\"] — null when the provider does not publish it. */\n supported_resolutions?: string[] | null;\n /** e.g. [\"16:9\",\"9:16\"] — null when the model decides. */\n supported_aspect_ratios?: string[] | null;\n /** e.g. [\"854x480\",\"1280x720\"]. */\n supported_sizes?: string[] | null;\n /** Discrete list of allowed durations in seconds (e.g. [3,5] or [1..15]). */\n supported_durations?: number[] | null;\n supported_frame_images?: (\"first_frame\" | \"last_frame\")[] | null;\n upscale_factor?: number | null;\n creativity?: number | null;\n /** Native audio generation (null = model decides / unknown). */\n generate_audio?: boolean | null;\n seed?: boolean | null;\n /** Per-SKU price strings — \"cents_*\" keys are in cents, the rest in USD. */\n pricing_skus?: Record<string, string> | null;\n allowed_passthrough_parameters?: string[];\n}\n\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n /** Live OpenRouter AI video catalog (may be empty when the upstream is unreachable). */\n openrouterModels?: OrVideoModel[];\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":[]}
|
|
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 AgentMessagesPage,\n AgentMessagesParams,\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 /**\n * GET /api/v1/agents/messages — chronological message feed for a conversation.\n *\n * Returns the latest N entries in chronological order (omit `after`), or page\n * forward with `after` = id of the last item you received. Includes workflow\n * artifacts: tool results, step progress, and approval requests.\n */\n listMessages(params: AgentMessagesParams): Promise<AgentMessagesPage> {\n return this.t.json<AgentMessagesPage>(\"GET\", \"/api/v1/agents/messages\", {\n query: { agentId: params.agentId, after: params.after, limit: params.limit, 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<{ type?: string; stage?: string; detail?: string; choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n if (payload.type === \"progress\") {\n yield { type: \"progress\", stage: payload.stage, detail: payload.detail };\n continue;\n }\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 * CSV/TSV attachments (base64 payloads). The backend parses them and hands\n * the rows to the agent's tool loop as structured data for batch processing.\n */\n files?: ChatFile[];\n}\n\n/** A file attachment sent with a chat request (base64 payload; CSV/TSV only). */\nexport interface ChatFile {\n name: string;\n mime?: string;\n dataBase64: string;\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 * - `progress`: tool-loop progress frames (e.g. which tools ran) for long jobs.\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: \"progress\"; stage?: string; detail?: 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/** Kinds of entries in the chronological agent message feed. */\nexport type AgentMessageKind = \"chat\" | \"tool_result\" | \"workflow\" | \"approval_request\";\n\n/** Declared output format of a feed message's content, when set. */\nexport type AgentMessageOutputFormat = \"text\" | \"json\" | \"html\";\n\n/** A tool call recorded on a feed message; `result` appears once the call completes (truncated server-side). */\nexport interface AgentFeedToolCall {\n name?: string;\n args?: unknown;\n status?: string;\n error?: string;\n result?: unknown;\n [key: string]: unknown;\n}\n\n/** One entry in the chronological agent message feed (GET /api/v1/agents/messages). */\nexport interface AgentMessageItem {\n id: string;\n role: string;\n kind: AgentMessageKind;\n content: string | null;\n reasoning?: string;\n toolCalls?: AgentFeedToolCall[];\n outputFormat?: AgentMessageOutputFormat;\n taskId?: string;\n status: string;\n timestamp: string | Date;\n}\n\n/** A page of the chronological agent message feed. */\nexport interface AgentMessagesPage {\n items: AgentMessageItem[];\n hasMore: boolean;\n /** Cursor for the next forward page (pass as `after`); undefined when exhausted. */\n nextAfter?: string;\n}\n\n/** Query params for `agents.listMessages`. */\nexport interface AgentMessagesParams {\n /** Platform slug or ObjectId of the agent. Required. */\n agentId: string;\n /** Cursor = id of the last item on the previous page (forward pagination). Omit for the latest N. */\n after?: string;\n /** Page size, 1..50 (default 20 server-side). */\n limit?: number;\n /** Optional internal user id filter (defaults to the workspace id server-side). */\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`. */\n/** An OpenRouter AI video model (from the public GET /api/v1/videos/models catalog). */\nexport interface OrVideoModel {\n id: string;\n canonical_slug?: string | null;\n hugging_face_id?: string | null;\n name: string;\n created?: number;\n description?: string;\n /** e.g. [\"480p\",\"720p\"] — null when the provider does not publish it. */\n supported_resolutions?: string[] | null;\n /** e.g. [\"16:9\",\"9:16\"] — null when the model decides. */\n supported_aspect_ratios?: string[] | null;\n /** e.g. [\"854x480\",\"1280x720\"]. */\n supported_sizes?: string[] | null;\n /** Discrete list of allowed durations in seconds (e.g. [3,5] or [1..15]). */\n supported_durations?: number[] | null;\n supported_frame_images?: (\"first_frame\" | \"last_frame\")[] | null;\n upscale_factor?: number | null;\n creativity?: number | null;\n /** Native audio generation (null = model decides / unknown). */\n generate_audio?: boolean | null;\n seed?: boolean | null;\n /** Per-SKU price strings — \"cents_*\" keys are in cents, the rest in USD. */\n pricing_skus?: Record<string, string> | null;\n allowed_passthrough_parameters?: string[];\n}\n\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n /** Live OpenRouter AI video catalog (may be empty when the upstream is unreachable). */\n openrouterModels?: OrVideoModel[];\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;;;AChGO,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,QAAyD;AACpE,WAAO,KAAK,EAAE,KAAwB,OAAO,2BAA2B;AAAA,MACtE,OAAO,EAAE,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAAA,IACpG,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+J,GAAG,IAAI;AACtL,UAAI,CAAC,QAAS;AACd,UAAI,QAAQ,SAAS,YAAY;AAC/B,cAAM,EAAE,MAAM,YAAY,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO;AACvE;AAAA,MACF;AACA,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;;;ACpWO,IAAM,kBAAkB;AAAA,EAC7B,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,eAAe;AACjB;","names":[]}
|