ql-agent-sdk 1.0.2 → 1.1.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 CHANGED
@@ -633,6 +633,127 @@ try {
633
633
 
634
634
  ---
635
635
 
636
+ ### Videos (Tiered Generation)
637
+
638
+ Async video generation: submit a job, then poll until it completes. Reference images may be base64 data URLs or https URLs; reference (style) videos must be https URLs — upload local files with `ql.files.upload` first.
639
+
640
+ #### `ql.videos.listModels()` → `Promise<VideoModelsResult>`
641
+
642
+ Lists the tiered video models plus runtime engine availability: `{ models: VideoModelInfo[], engine: { available, detail } }`. Each model reports its tier, supported aspect ratios/resolutions, duration range, reference-image/video limits, voiceover support, and pricing.
643
+
644
+ **Example:**
645
+ ```ts
646
+ const { models, engine } = await ql.videos.listModels();
647
+ if (!engine.available) console.warn("Video engine unavailable:", engine.detail);
648
+ const recommended = models.find((m) => m.recommended && m.available);
649
+ ```
650
+
651
+ #### `ql.videos.generate(agentId, input)` → `Promise<VideoTaskCreated>`
652
+
653
+ Starts a video job (HTTP 202) and returns `{ taskId, status: "queued" }`.
654
+
655
+ | Field | Description |
656
+ |-------|-------------|
657
+ | `prompt` | The creative brief / script for the video |
658
+ | `model`? | Explicit registry model id (wins over `tier`) |
659
+ | `tier`? | Tier to resolve a model from when `model` is omitted |
660
+ | `images_list`? | Product/reference images — base64 data URLs or https URLs (order defines IMG_0..N) |
661
+ | `video_files`? | Reference (style) videos — https URLs only |
662
+ | `aspect_ratio`? | e.g. `"16:9"`, `"9:16"`, `"1:1"` (default `"16:9"`) |
663
+ | `duration`? | Seconds, within the model's `durationRange` |
664
+ | `resolution`? | e.g. `"720p"` / `"1080p"` (default `"720p"`) |
665
+ | `generate_audio`? | Bake a voiceover into the render (requires `narration`) |
666
+ | `narration`? | Voiceover text (max 3000 chars) |
667
+
668
+ **Example:**
669
+ ```ts
670
+ const created = await ql.videos.generate("marketing", {
671
+ prompt: "A 10-second product reel for the new sneaker drop, studio lighting.",
672
+ model: "motion/reel",
673
+ images_list: ["data:image/png;base64,..."], // or https URLs
674
+ video_files: ["https://cdn.example.com/style-ref.mp4"],
675
+ aspect_ratio: "9:16",
676
+ duration: 10,
677
+ resolution: "1080p",
678
+ generate_audio: true,
679
+ narration: "Introducing the all-new AirFlex.",
680
+ });
681
+ ```
682
+
683
+ #### `ql.videos.getTask(taskId, signal?)` → `Promise<VideoTask>`
684
+
685
+ Fetches the current job snapshot: `{ taskId, status, progress?, outputUrl?, mime?, ext?, durationSec?, error?, model?, tier?, latencyMs?, createdAt, completedAt }`.
686
+
687
+ #### `ql.videos.cancelTask(taskId)` → `Promise<VideoTask>`
688
+
689
+ Cancels a queued/rendering job and returns the updated snapshot. Throws a `QLError` with code `"conflict"` (HTTP 409) if the job is already terminal.
690
+
691
+ #### `ql.videos.handle(taskId)` → `VideoTaskHandle`
692
+
693
+ Same `poll()` / `wait(opts?)` pattern as `TaskHandle`, polling `/api/v1/video-tasks/:taskId`. Terminal statuses: `completed` (check `outputUrl`), `failed` (check `error`), `cancelled`. Wait options and non-terminal exits (`timeout` / `aborted`) are identical to tasks.
694
+
695
+ **Example:**
696
+ ```ts
697
+ const done = await ql.videos.handle(created.taskId).wait({
698
+ intervalMs: 2000,
699
+ timeoutMs: 10 * 60_000,
700
+ onTick: (job) => {
701
+ if (job.progress?.message) process.stdout.write(`\r${job.progress.message}`);
702
+ },
703
+ });
704
+ if (done.status === "completed" && done.outputUrl) {
705
+ console.log("Video ready:", `${ql.baseUrl}${done.outputUrl}`);
706
+ }
707
+ ```
708
+
709
+ ### Audio (Text-to-Speech)
710
+
711
+ #### `ql.audio.voices()` → `Promise<VoicesResult>`
712
+
713
+ Lists available TTS voices: `{ voices: { id, name }[], source: "live" | "none", note? }`. `source === "none"` means no provider key is configured server-side.
714
+
715
+ #### `ql.audio.textToSpeech(agentId, input)` → `Promise<TtsResult>`
716
+
717
+ Synchronous synthesis (no polling). Returns `{ url, voiceId, modelId, bytes, latencyMs }` where `url` is a served media path (e.g. `/generated/tts-….mp3`).
718
+
719
+ | Field | Description |
720
+ |-------|-------------|
721
+ | `text` | Text to synthesize (max 3000 chars) |
722
+ | `voiceId`? | Voice id from `ql.audio.voices()` (defaults to the platform voice) |
723
+ | `stability`? | Voice stability 0..1 (default 0.5) |
724
+ | `similarityBoost`? | Similarity boost 0..1 (default 0.75) |
725
+
726
+ **Example:**
727
+ ```ts
728
+ const { voices } = await ql.audio.voices();
729
+ const result = await ql.audio.textToSpeech("marketing", {
730
+ text: "Say hello to the all-new AirFlex.",
731
+ voiceId: voices[0]?.id,
732
+ });
733
+ console.log(`${ql.baseUrl}${result.url}`);
734
+ ```
735
+
736
+ ### Files (Media Upload)
737
+
738
+ #### `ql.files.upload(file, opts?)` → `Promise<UploadedFile>`
739
+
740
+ Uploads a media file as multipart form data (field `"file"`) and returns `{ url, filename, size, contentType }`. The returned `url` is a stable served path (e.g. `/uploads/<workspace>/<file>`) that can be used directly as a media input URL — e.g. in `videos.generate({ video_files: [res.url] })`.
741
+
742
+ | Option | Description |
743
+ |--------|-------------|
744
+ | `filename`? | Override the stored display name (extension is kept from the file) |
745
+ | `onProgress`? | Coarse progress callback — fetch does not expose byte progress, so it reports 0 at start and 100 on completion only |
746
+
747
+ **Example:**
748
+ ```ts
749
+ const blob = await file.arrayBuffer(); // or any Blob source
750
+ const uploaded = await ql.files.upload(new Blob([blob], { type: "video/mp4" }), {
751
+ filename: "style-ref.mp4",
752
+ });
753
+ ```
754
+
755
+ ---
756
+
636
757
  ## Error Handling
637
758
 
638
759
  All API failures throw a typed **`QLError`**:
package/dist/index.cjs CHANGED
@@ -22,12 +22,16 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  API_ERROR_CODES: () => API_ERROR_CODES,
24
24
  AgentsApi: () => AgentsApi,
25
+ AudioApi: () => AudioApi,
25
26
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
27
+ FilesApi: () => FilesApi,
26
28
  ImagesApi: () => ImagesApi,
27
29
  QLClient: () => QLClient,
28
30
  QLError: () => QLError,
29
31
  TaskHandle: () => TaskHandle,
30
32
  TasksApi: () => TasksApi,
33
+ VideoTaskHandle: () => VideoTaskHandle,
34
+ VideosApi: () => VideosApi,
31
35
  WorkflowsApi: () => WorkflowsApi,
32
36
  WorkspaceApi: () => WorkspaceApi,
33
37
  isTerminalTaskStatus: () => isTerminalTaskStatus
@@ -135,6 +139,12 @@ function createTransport(opts) {
135
139
  if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });
136
140
  return unwrap(text, { method, url: res.url });
137
141
  },
142
+ async form(path, reqOpts) {
143
+ const res = await doFormFetch(path, reqOpts);
144
+ const text = await res.text();
145
+ if (!res.ok) throw toHttpError(res.status, text, { method: "POST", url: res.url });
146
+ return unwrap(text, { method: "POST", url: res.url });
147
+ },
138
148
  async stream(method, path, reqOpts = {}) {
139
149
  const res = await doFetch(method, path, {
140
150
  ...reqOpts,
@@ -175,6 +185,22 @@ function createTransport(opts) {
175
185
  throw toNetworkError(err, { method, url });
176
186
  });
177
187
  }
188
+ function doFormFetch(path, reqOpts) {
189
+ const url = buildUrl(baseUrl, path);
190
+ const headers = {
191
+ authorization: `Bearer ${apiKey}`,
192
+ accept: "application/json",
193
+ ...reqOpts.headers ?? {}
194
+ };
195
+ return fetchImpl(url, {
196
+ method: "POST",
197
+ headers,
198
+ body: reqOpts.form,
199
+ signal: reqOpts.signal
200
+ }).catch((err) => {
201
+ throw toNetworkError(err, { method: "POST", url });
202
+ });
203
+ }
178
204
  }
179
205
  function unwrap(text, ctx) {
180
206
  const parsed = safeParse(text);
@@ -313,6 +339,27 @@ var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
313
339
  function isTerminalTaskStatus(status) {
314
340
  return TERMINAL_TASK_STATUSES.has(status);
315
341
  }
342
+ async function pollUntilTerminal(fetchSnapshot, isTerminal, onTick, opts) {
343
+ const intervalMs = opts.intervalMs ?? 2e3;
344
+ const maxIntervalMs = opts.maxIntervalMs ?? 15e3;
345
+ const signal = opts.signal;
346
+ const startedAt = Date.now();
347
+ let delay = intervalMs;
348
+ for (; ; ) {
349
+ if (signal?.aborted) throw abortError();
350
+ if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
351
+ throw timeoutError(opts.timeoutMs);
352
+ }
353
+ const snapshot = await fetchSnapshot(signal);
354
+ onTick?.(snapshot);
355
+ if (isTerminal(snapshot)) return snapshot;
356
+ if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
357
+ throw timeoutError(opts.timeoutMs);
358
+ }
359
+ await sleep(delay, signal);
360
+ delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));
361
+ }
362
+ }
316
363
  var TaskHandle = class {
317
364
  constructor(transport, taskId) {
318
365
  this.transport = transport;
@@ -326,33 +373,37 @@ var TaskHandle = class {
326
373
  poll(signal) {
327
374
  return this.get(signal);
328
375
  }
329
- /**
330
- * Poll until the task reaches a terminal status.
331
- *
332
- * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.
333
- * - Throws a QLError with code "timeout" if `timeoutMs` elapses first.
334
- * - Throws a QLError with code "aborted" if `signal` aborts.
335
- */
376
+ /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */
336
377
  async wait(opts = {}) {
337
- const intervalMs = opts.intervalMs ?? 2e3;
338
- const maxIntervalMs = opts.maxIntervalMs ?? 15e3;
339
- const signal = opts.signal;
340
- const startedAt = Date.now();
341
- let delay = intervalMs;
342
- for (; ; ) {
343
- if (signal?.aborted) throw abortError();
344
- if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
345
- throw timeoutError(opts.timeoutMs);
346
- }
347
- const task = await this.get(signal);
348
- opts.onTick?.(task);
349
- if (isTerminalTaskStatus(task.status)) return task;
350
- if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
351
- throw timeoutError(opts.timeoutMs);
352
- }
353
- await sleep(delay, signal);
354
- delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));
355
- }
378
+ return pollUntilTerminal(
379
+ (signal) => this.get(signal),
380
+ (task) => isTerminalTaskStatus(task.status),
381
+ opts.onTick,
382
+ opts
383
+ );
384
+ }
385
+ };
386
+ var VideoTaskHandle = class {
387
+ constructor(transport, taskId) {
388
+ this.transport = transport;
389
+ this.taskId = taskId;
390
+ }
391
+ /** Fetch the current job snapshot (single request). */
392
+ get(signal) {
393
+ return this.transport.json("GET", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });
394
+ }
395
+ /** Alias of `get()` — perform one poll and return the latest snapshot. */
396
+ poll(signal) {
397
+ return this.get(signal);
398
+ }
399
+ /** Poll until the job reaches a terminal status (completed/failed/cancelled). */
400
+ async wait(opts = {}) {
401
+ return pollUntilTerminal(
402
+ (signal) => this.get(signal),
403
+ (task) => isTerminalTaskStatus(task.status),
404
+ opts.onTick,
405
+ opts
406
+ );
356
407
  }
357
408
  };
358
409
  function sleep(ms, signal) {
@@ -490,6 +541,62 @@ var ImagesApi = class {
490
541
  return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });
491
542
  }
492
543
  };
544
+ var VideosApi = class {
545
+ constructor(t) {
546
+ this.t = t;
547
+ }
548
+ /** GET /api/v1/videos/models — list tiered video models + engine availability. */
549
+ listModels() {
550
+ return this.t.json("GET", "/api/v1/videos/models");
551
+ }
552
+ /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */
553
+ generate(agentId, input) {
554
+ return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });
555
+ }
556
+ /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */
557
+ getTask(taskId, signal) {
558
+ return this.t.json("GET", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });
559
+ }
560
+ /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */
561
+ cancelTask(taskId) {
562
+ return this.t.json("DELETE", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);
563
+ }
564
+ /** Get a handle for polling / waiting on a video job (poll(), wait()). */
565
+ handle(taskId) {
566
+ return new VideoTaskHandle(this.t, taskId);
567
+ }
568
+ };
569
+ var AudioApi = class {
570
+ constructor(t) {
571
+ this.t = t;
572
+ }
573
+ /** GET /api/v1/audio/voices — list available TTS voices. */
574
+ voices() {
575
+ return this.t.json("GET", "/api/v1/audio/voices");
576
+ }
577
+ /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */
578
+ textToSpeech(agentId, input) {
579
+ return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });
580
+ }
581
+ };
582
+ var FilesApi = class {
583
+ constructor(t) {
584
+ this.t = t;
585
+ }
586
+ /** POST /api/v1/files — upload a media file (multipart field "file"). */
587
+ async upload(file, opts = {}) {
588
+ const form = new FormData();
589
+ if (opts.filename !== void 0) {
590
+ form.append("file", file, opts.filename);
591
+ } else {
592
+ form.append("file", file);
593
+ }
594
+ opts.onProgress?.(0);
595
+ const result = await this.t.form("/api/v1/files", { form });
596
+ opts.onProgress?.(100);
597
+ return result;
598
+ }
599
+ };
493
600
  function readEnvBaseUrl() {
494
601
  try {
495
602
  if (typeof process !== "undefined" && process?.env) {
@@ -512,6 +619,9 @@ var QLClient = class {
512
619
  this.workflows = new WorkflowsApi(this.transport);
513
620
  this.tasks = new TasksApi(this.transport);
514
621
  this.images = new ImagesApi(this.transport);
622
+ this.videos = new VideosApi(this.transport);
623
+ this.audio = new AudioApi(this.transport);
624
+ this.files = new FilesApi(this.transport);
515
625
  }
516
626
  /** The normalized base URL in use (not secret). */
517
627
  get baseUrl() {
@@ -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, 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, isTerminalTaskStatus } from \"./task.js\";\n\nexport { API_ERROR_CODES } from \"./types.js\";\nexport type {\n ApiErrorCode,\n ChatMessage,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n StreamOptions,\n MessageItem,\n HistoryPage,\n HistoryParams,\n AgentSummary,\n AgentListResult,\n CapParamKind,\n CapabilityParam,\n CapabilityTemplate,\n CapabilityInfo,\n AgentDetail,\n CapabilitiesResult,\n RunCapabilityInput,\n CapabilityResult,\n RunCapabilityResult,\n Workspace,\n WorkflowRunInput,\n WorkflowRunStart,\n WorkflowRunStatus,\n WorkflowRun,\n ImageTier,\n ImagePricingEntry,\n ImageModelInfo,\n ImageModelsResult,\n ImageReferenceInput,\n ImageGenerateInput,\n GeneratedImage,\n ImageUsage,\n ImageGenerateResult,\n TaskPriority,\n TaskCreateInput,\n TaskCreated,\n TaskStatus,\n Task,\n WaitOptions,\n} 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\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 /**\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 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\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 } from \"./types.js\";\n\n/** Statuses at which a task will not change again. */\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\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 /**\n * Poll until the task reaches a terminal status.\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 */\n async wait(opts: WaitOptions = {}): Promise<Task> {\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 task = await this.get(signal);\n opts.onTick?.(task);\n if (isTerminalTaskStatus(task.status)) return task;\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/** 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 } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CapabilitiesResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n GeneratedImage,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelInfo,\n ImageModelsResult,\n ImageReferenceInput,\n ImageTier,\n ImageUsage,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\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\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 }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n"],"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 ChatMessage,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n StreamOptions,\n MessageItem,\n HistoryPage,\n HistoryParams,\n AgentSummary,\n AgentListResult,\n CapParamKind,\n CapabilityParam,\n CapabilityTemplate,\n CapabilityInfo,\n AgentDetail,\n CapabilitiesResult,\n RunCapabilityInput,\n CapabilityResult,\n RunCapabilityResult,\n Workspace,\n WorkflowRunInput,\n WorkflowRunStart,\n WorkflowRunStatus,\n WorkflowRun,\n ImageTier,\n ImagePricingEntry,\n ImageModelInfo,\n ImageModelsResult,\n ImageReferenceInput,\n ImageGenerateInput,\n GeneratedImage,\n ImageUsage,\n ImageGenerateResult,\n TaskPriority,\n TaskCreateInput,\n TaskCreated,\n TaskStatus,\n Task,\n WaitOptions,\n VideoTier,\n VideoPricingEntry,\n VideoModelInfo,\n VideoModelsResult,\n VideoGenerateInput,\n VideoTaskCreated,\n VideoTaskStatus,\n VideoTask,\n VideoWaitOptions,\n TtsInput,\n TtsResult,\n VoiceInfo,\n VoicesResult,\n UploadedFile,\n FileUploadOptions,\n} from \"./types.js\";\n","import type { ApiErrorCode } from \"./types.js\";\n\nexport interface QLErrorContext {\n method?: string;\n url?: string;\n}\n\n/**\n * Error thrown by the SDK for any failed API interaction.\n *\n * - `status`: HTTP status code (when the failure came from an HTTP response).\n * - `code`: stable API error code when provided by the backend, otherwise a\n * synthesized one derived from the status, or a synthetic transport\n * code such as \"aborted\" / \"timeout\" / \"network\".\n * - `message`: human-readable description. The API key is never included.\n */\nexport class QLError extends Error {\n readonly status?: number;\n readonly code: string;\n readonly method?: string;\n readonly url?: string;\n /** The raw parsed error body (if any), for advanced inspection. */\n readonly details?: unknown;\n\n constructor(message: string, opts: { status?: number; code: string; context?: QLErrorContext; details?: unknown } = { code: \"internal_error\" }) {\n super(message);\n this.name = \"QLError\";\n this.status = opts.status;\n this.code = opts.code;\n this.method = opts.context?.method;\n this.url = opts.context?.url;\n this.details = opts.details;\n // Restore prototype chain (required when targeting ES5-ish runtimes).\n Object.setPrototypeOf(this, QLError.prototype);\n }\n\n /** True for 401/403 or unauthorized/forbidden codes. */\n get isAuthError(): boolean {\n return this.code === \"unauthorized\" || this.code === \"forbidden\" || this.status === 401 || this.status === 403;\n }\n\n /** True when the request was aborted by the caller. */\n get isAborted(): boolean {\n return this.code === \"aborted\";\n }\n\n /** True when a wait() call exceeded its timeout. */\n get isTimeout(): boolean {\n return this.code === \"timeout\";\n }\n\n /** True for transient network failures (no HTTP response received). */\n get isNetworkError(): boolean {\n return this.code === \"network\";\n }\n}\n\n/** Map an HTTP status to a stable API error code when the body has none. */\nexport function codeFromStatus(status: number): ApiErrorCode | \"conflict\" {\n switch (status) {\n case 400:\n return \"validation_error\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 409:\n return \"conflict\";\n default:\n return status >= 500 ? \"internal_error\" : \"validation_error\";\n }\n}\n\ninterface ParsedErrorBody {\n ok?: boolean;\n error?: { code?: string; message?: string } | string;\n message?: string;\n}\n\n/** Build a QLError from a non-2xx HTTP response. Never includes the API key. */\nexport function toHttpError(status: number, text: string | undefined, ctx: QLErrorContext): QLError {\n let parsed: ParsedErrorBody | null = null;\n if (text) {\n try {\n const j = JSON.parse(text);\n if (j && typeof j === \"object\") parsed = j as ParsedErrorBody;\n } catch {\n parsed = null;\n }\n }\n\n const bodyErr = parsed?.error;\n let code: string | undefined;\n let message: string | undefined;\n if (typeof bodyErr === \"string\") {\n message = bodyErr;\n } else if (bodyErr && typeof bodyErr === \"object\") {\n code = typeof bodyErr.code === \"string\" ? bodyErr.code : undefined;\n message = typeof bodyErr.message === \"string\" ? bodyErr.message : undefined;\n }\n if (!code) code = codeFromStatus(status);\n if (!message) message = (typeof parsed?.message === \"string\" ? parsed.message : undefined) ?? `Request failed with status ${status}`;\n\n return new QLError(message, { status, code, context: ctx, details: parsed ?? undefined });\n}\n\n/** Wrap a low-level fetch/network failure (no HTTP response). */\nexport function toNetworkError(cause: unknown, ctx: QLErrorContext): QLError {\n const aborted = isAbortCause(cause);\n if (aborted) {\n return new QLError(\"Request aborted\", { code: \"aborted\", context: ctx });\n }\n const msg = cause instanceof Error ? cause.message : String(cause);\n return new QLError(`Network error: ${msg}`, { code: \"network\", context: ctx, details: cause });\n}\n\nfunction isAbortCause(cause: unknown): boolean {\n if (!cause) return false;\n if (typeof cause === \"object\") {\n const c = cause as { name?: string; type?: string };\n if (c.name === \"AbortError\" || c.type === \"aborted\") return true;\n }\n return false;\n}\n\n/** Build an abort error for wait()/stream cancellation. */\nexport function abortError(): QLError {\n return new QLError(\"Operation aborted\", { code: \"aborted\" });\n}\n\n/** Build a timeout error for wait(). */\nexport function timeoutError(timeoutMs: number): QLError {\n return new QLError(`Timed out after ${timeoutMs}ms`, { code: \"timeout\" });\n}\n","import { QLError, toHttpError, toNetworkError } from \"./errors.js\";\nimport type { ApiErrorCode } from \"./types.js\";\n\nexport interface TransportOptions {\n apiKey: string;\n baseUrl: string;\n fetchImpl: typeof fetch;\n}\n\nexport interface JsonRequestOptions {\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport interface FormRequestOptions {\n form: FormData;\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\n/**\n * Internal transport used by the API namespaces. Keeps the API key inside a\n * closure (never exposed) and normalizes responses/errors for the caller.\n */\nexport interface Transport {\n /** Perform a JSON request and return the unwrapped `data` payload. */\n json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;\n /** Perform a multipart/form-data request and return the unwrapped `data` payload. */\n form<T>(path: string, opts: FormRequestOptions): Promise<T>;\n /**\n * Perform a request expected to stream SSE. Returns the response body stream\n * after verifying a 2xx + text/event-stream; throws QLError otherwise.\n */\n stream(method: string, path: string, opts?: JsonRequestOptions & { acceptStream?: boolean }): Promise<ReadableStream<Uint8Array>>;\n}\n\nexport function createTransport(opts: TransportOptions): Transport {\n const { apiKey, baseUrl, fetchImpl } = opts;\n\n return {\n async json<T>(method: string, path: string, reqOpts: JsonRequestOptions = {}) {\n const res = await doFetch(method, path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });\n return unwrap<T>(text, { method, url: res.url });\n },\n\n async form<T>(path: string, reqOpts: FormRequestOptions) {\n const res = await doFormFetch(path, reqOpts);\n const text = await res.text();\n if (!res.ok) throw toHttpError(res.status, text, { method: \"POST\", url: res.url });\n return unwrap<T>(text, { method: \"POST\", url: res.url });\n },\n\n async stream(method, path, reqOpts = {}) {\n const res = await doFetch(method, path, {\n ...reqOpts,\n headers: { accept: \"text/event-stream\", ...(reqOpts.headers ?? {}) },\n });\n if (!res.ok) {\n const text = await res.text().catch(() => undefined);\n throw toHttpError(res.status, text, { method, url: res.url });\n }\n const ctype = (res.headers.get(\"content-type\") || \"\").toLowerCase();\n if (!ctype.includes(\"text/event-stream\")) {\n // The endpoint returned a non-SSE body (e.g. an error envelope). Surface it.\n const text = await res.text().catch(() => undefined);\n throw new QLError(`Expected text/event-stream but got \"${ctype || \"unknown\"}\"`, {\n status: res.status,\n code: \"internal_error\",\n context: { method, url: res.url },\n details: safeParse(text),\n });\n }\n if (!res.body) throw new QLError(\"Response has no readable body stream\", { code: \"network\", context: { method, url: res.url } });\n return res.body;\n },\n };\n\n function doFetch(method: string, path: string, reqOpts: JsonRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path, reqOpts.query);\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method,\n headers,\n body: reqOpts.body !== undefined ? JSON.stringify(reqOpts.body) : undefined,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method, url });\n });\n }\n\n function doFormFetch(path: string, reqOpts: FormRequestOptions): Promise<Response> {\n const url = buildUrl(baseUrl, path);\n // No content-type header here — fetch sets the multipart boundary itself.\n const headers: Record<string, string> = {\n authorization: `Bearer ${apiKey}`,\n accept: \"application/json\",\n ...(reqOpts.headers ?? {}),\n };\n return fetchImpl(url, {\n method: \"POST\",\n headers,\n body: reqOpts.form,\n signal: reqOpts.signal,\n }).catch((err) => {\n throw toNetworkError(err, { method: \"POST\", url });\n });\n }\n}\n\nfunction unwrap<T>(text: string, ctx: { method?: string; url?: string }): T {\n const parsed = safeParse(text);\n if (parsed && typeof parsed === \"object\" && \"ok\" in (parsed as Record<string, unknown>)) {\n const env = parsed as { ok: boolean; data?: unknown; error?: { code?: string; message?: string } };\n if (env.ok === true) return env.data as T;\n // ok:false on a 2xx — treat as an application error.\n throw new QLError(env.error?.message || \"Request failed\", {\n code: (env.error?.code as ApiErrorCode) || \"internal_error\",\n context: ctx,\n details: env,\n });\n }\n // Non-enveloped payload (legacy shapes): return as-is.\n return parsed as T;\n}\n\nfunction safeParse(text?: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Join base + path and append a query string (skipping undefined values). */\nexport function buildUrl(baseUrl: string, path: string, query?: Record<string, string | number | undefined>): string {\n const base = baseUrl.replace(/\\/+$/, \"\");\n const p = path.startsWith(\"/\") ? path : `/${path}`;\n let url = `${base}${p}`;\n if (query) {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) params.set(key, String(value));\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n }\n return url;\n}\n\n/** Normalize a base URL: trim whitespace and drop any trailing slash. */\nexport function normalizeUrl(url: string): string {\n return url.trim().replace(/\\/+$/, \"\");\n}\n","/**\n * Minimal, dependency-free Server-Sent Events reader built on Web Streams.\n *\n * Handles the cases that commonly break naive parsers:\n * - a `data:` line split across two TCP chunks (chunk boundaries)\n * - multiple events arriving in a single chunk\n * - both CRLF and LF line endings (and lone CR)\n * - a final event that is not terminated by a trailing newline\n * - the `[DONE]` terminator\n * - abort signals\n */\n\nexport interface SSEEvent {\n /** The concatenated `data:` payload for this event (trimmed of the leading space). */\n data: string;\n}\n\ninterface ReadOptions {\n signal?: AbortSignal;\n /** When true, stop after the first `[DONE]` data value. Default true. */\n stopOnDone?: boolean;\n}\n\n/**\n * Read raw SSE events from a `ReadableStream<Uint8Array>`.\n * Yields one object per event with its combined `data` payload.\n */\nexport async function* readSSEEvents(\n body: ReadableStream<Uint8Array>,\n opts: ReadOptions = {},\n): AsyncGenerator<SSEEvent, void, unknown> {\n const stopOnDone = opts.stopOnDone ?? true;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let dataLines: string[] = [];\n\n // Abort wiring: cancel the underlying stream promptly when the signal fires.\n const onAbort = () => {\n void reader.cancel().catch(() => {});\n };\n if (opts.signal) {\n if (opts.signal.aborted) {\n await reader.cancel().catch(() => {});\n return;\n }\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n const dispatch = (): SSEEvent | null => {\n if (dataLines.length === 0) return null;\n const data = dataLines.join(\"\\n\");\n dataLines = [];\n return { data };\n };\n\n const processLine = (line: string): SSEEvent | null => {\n if (line === \"\") return dispatch(); // blank line = event boundary\n if (line.startsWith(\":\")) return null; // comment\n if (line.startsWith(\"data:\")) {\n let value = line.slice(5);\n if (value.startsWith(\" \")) value = value.slice(1);\n dataLines.push(value);\n return null;\n }\n // Ignore event:/id:/retry: and unknown fields.\n return null;\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n\n let s = splitFirstLine(buffer);\n while (s !== null) {\n const ev = processLine(s.line);\n if (ev) {\n if (stopOnDone && ev.data.trim() === \"[DONE]\") return;\n yield ev;\n }\n buffer = s.rest;\n s = splitFirstLine(buffer);\n }\n }\n\n // Flush any bytes still held by the decoder.\n buffer += decoder.decode();\n if (buffer.length > 0) {\n const ev = processLine(buffer);\n if (ev && !(stopOnDone && ev.data.trim() === \"[DONE]\")) yield ev;\n }\n // Flush a final event that had no terminating blank line.\n const tail = dispatch();\n if (tail && !(stopOnDone && tail.data.trim() === \"[DONE]\")) yield tail;\n } finally {\n if (opts.signal) opts.signal.removeEventListener(\"abort\", onAbort);\n try {\n reader.releaseLock();\n } catch {\n /* already released */\n }\n }\n}\n\n/** Split the first complete line (LF, CRLF, or lone CR) out of `buf`. */\nfunction splitFirstLine(buf: string): { line: string; rest: string } | null {\n const nl = buf.indexOf(\"\\n\");\n const cr = buf.indexOf(\"\\r\");\n let end = -1;\n let termLen = 0;\n if (nl !== -1 && (cr === -1 || nl < cr)) {\n end = nl;\n termLen = 1;\n } else if (cr !== -1) {\n end = cr;\n termLen = buf[cr + 1] === \"\\n\" ? 2 : 1;\n }\n if (end === -1) return null;\n return { line: buf.slice(0, end), rest: buf.slice(end + termLen) };\n}\n\n/** Parse a single SSE `data` payload as JSON, returning null on failure. */\nexport function parseSSEData<T = unknown>(data: string): T | null {\n const trimmed = data.trim();\n if (trimmed === \"\" || trimmed === \"[DONE]\") return null;\n try {\n return JSON.parse(trimmed) as T;\n } catch {\n return null; // malformed JSON is skipped, not fatal\n }\n}\n","import type { Transport } from \"./http.js\";\nimport { abortError, timeoutError } from \"./errors.js\";\nimport type { Task, WaitOptions, VideoTask, VideoWaitOptions } from \"./types.js\";\n\n/** Statuses at which a job will not change again (shared by tasks and video jobs). */\nconst TERMINAL_TASK_STATUSES = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\nexport function isTerminalTaskStatus(status: string): boolean {\n return TERMINAL_TASK_STATUSES.has(status);\n}\n\ninterface PollOptions {\n intervalMs?: number;\n maxIntervalMs?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n}\n\n/**\n * Shared polling loop used by TaskHandle.wait() and VideoTaskHandle.wait().\n *\n * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.\n * - Throws a QLError with code \"timeout\" if `timeoutMs` elapses first.\n * - Throws a QLError with code \"aborted\" if `signal` aborts.\n */\nasync function pollUntilTerminal<T>(\n fetchSnapshot: (signal?: AbortSignal) => Promise<T>,\n isTerminal: (snapshot: T) => boolean,\n onTick: ((snapshot: T) => void) | undefined,\n opts: PollOptions,\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? 2000;\n const maxIntervalMs = opts.maxIntervalMs ?? 15000;\n const signal = opts.signal;\n const startedAt = Date.now();\n let delay = intervalMs;\n\n for (;;) {\n if (signal?.aborted) throw abortError();\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n const snapshot = await fetchSnapshot(signal);\n onTick?.(snapshot);\n if (isTerminal(snapshot)) return snapshot;\n\n // Recompute timeout after the poll so a slow request doesn't overshoot silently.\n if (opts.timeoutMs !== undefined && Date.now() - startedAt >= opts.timeoutMs) {\n throw timeoutError(opts.timeoutMs);\n }\n\n await sleep(delay, signal);\n delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));\n }\n}\n\n/**\n * A handle to a background task created via `tasks.create`.\n *\n * NOTE on execution: creating a task only enqueues it. It may stay in the\n * `queued` state until an existing worker/execution mechanism processes it —\n * this SDK does not trigger execution. `wait()` simply polls until the task\n * reaches a terminal status (or you time out / abort).\n */\nexport class TaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current task snapshot (single request). */\n get(signal?: AbortSignal): Promise<Task> {\n return this.transport.json<Task>(\"GET\", `/api/v1/tasks/${this.taskId}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<Task> {\n return this.get(signal);\n }\n\n /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */\n async wait(opts: WaitOptions = {}): Promise<Task> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/**\n * A handle to a video job created via `videos.generate`.\n * Polls the video-tasks endpoint until the job reaches a terminal status.\n */\nexport class VideoTaskHandle {\n constructor(\n private readonly transport: Transport,\n public readonly taskId: string,\n ) {}\n\n /** Fetch the current job snapshot (single request). */\n get(signal?: AbortSignal): Promise<VideoTask> {\n return this.transport.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });\n }\n\n /** Alias of `get()` — perform one poll and return the latest snapshot. */\n poll(signal?: AbortSignal): Promise<VideoTask> {\n return this.get(signal);\n }\n\n /** Poll until the job reaches a terminal status (completed/failed/cancelled). */\n async wait(opts: VideoWaitOptions = {}): Promise<VideoTask> {\n return pollUntilTerminal(\n (signal) => this.get(signal),\n (task) => isTerminalTaskStatus(task.status),\n opts.onTick,\n opts,\n );\n }\n}\n\n/** Abort-aware sleep. Rejects with an abort error if `signal` fires first. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(abortError());\n return;\n }\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n };\n if (signal) signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n","import { createTransport, normalizeUrl, type Transport } from \"./http.js\";\nimport { QLError } from \"./errors.js\";\nimport { readSSEEvents, parseSSEData } from \"./sse.js\";\nimport { TaskHandle, VideoTaskHandle } from \"./task.js\";\nimport type {\n AgentDetail,\n AgentListResult,\n CapabilitiesResult,\n ChatInput,\n ChatResult,\n ChatStreamEvent,\n HistoryPage,\n HistoryParams,\n ImageGenerateInput,\n ImageGenerateResult,\n ImageModelsResult,\n RunCapabilityInput,\n RunCapabilityResult,\n StreamOptions,\n Task,\n TaskCreateInput,\n TaskCreated,\n TtsInput,\n TtsResult,\n UploadedFile,\n FileUploadOptions,\n WorkflowRun,\n WorkflowRunInput,\n WorkflowRunStart,\n Workspace,\n VideoGenerateInput,\n VideoModelsResult,\n VideoTask,\n VideoTaskCreated,\n VoicesResult,\n} from \"./types.js\";\n\nexport const DEFAULT_BASE_URL = \"https://app.quantonlabs.com\";\n\nexport interface QLClientOptions {\n /** Your Quanton Labs API key (Bearer). Never logged or exposed. */\n apiKey: string;\n /** API base URL. Defaults to `QL_BASE_URL` if set, else https://app.quantonlabs.com. */\n baseUrl?: string;\n /** Override the global fetch (for tests, proxies, or custom runtimes). */\n fetch?: typeof fetch;\n}\n\n/** Workspace namespace. */\nexport class WorkspaceApi {\n constructor(private readonly t: Transport) {}\n /** GET /api/v1/workspace */\n get(): Promise<Workspace> {\n return this.t.json<Workspace>(\"GET\", \"/api/v1/workspace\");\n }\n}\n\n/** Agents namespace. */\nexport class AgentsApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/agents — list the global agent registry. */\n list(): Promise<AgentListResult> {\n return this.t.json<AgentListResult>(\"GET\", \"/api/v1/agents\");\n }\n\n /** GET /api/v1/agents/:agentId — agent detail + capabilities. */\n get(agentId: string): Promise<AgentDetail> {\n return this.t.json<AgentDetail>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}`);\n }\n\n /** GET /api/v1/agents/:agentId/capabilities */\n capabilities(agentId: string): Promise<CapabilitiesResult> {\n return this.t.json<CapabilitiesResult>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities`);\n }\n\n /** POST /api/v1/agents/:agentId/capabilities/run — run a feature. */\n runCapability(agentId: string, input: RunCapabilityInput): Promise<RunCapabilityResult> {\n return this.t.json<RunCapabilityResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/capabilities/run`, {\n body: { capId: input.capId, params: input.params ?? {} },\n });\n }\n\n /** POST /api/v1/agents/chat — non-streaming chat. */\n chat(input: ChatInput): Promise<ChatResult> {\n return this.t.json<ChatResult>(\"POST\", \"/api/v1/agents/chat\", { body: input });\n }\n\n /**\n * POST /api/v1/agents/chat/stream — streaming chat as an async iterable.\n *\n * Yields incremental `delta` events (text and/or reasoning) followed by a\n * single `done` event with the fully accumulated text. Stop early by passing\n * an `AbortSignal` (see StreamOptions) or breaking out of the loop.\n */\n chatStream(input: ChatInput, opts: StreamOptions = {}): AsyncIterable<ChatStreamEvent> {\n return this.chatStreamImpl(input, opts);\n }\n\n /** GET /api/v1/agents/:agentId/messages — paginated history (newest first). */\n history(agentId: string, params: HistoryParams = {}): Promise<HistoryPage> {\n return this.t.json<HistoryPage>(\"GET\", `/api/v1/agents/${encodeURIComponent(agentId)}/messages`, {\n query: { limit: params.limit, before: params.before, userId: params.userId },\n });\n }\n\n private async *chatStreamImpl(input: ChatInput, opts: StreamOptions): AsyncGenerator<ChatStreamEvent> {\n const body = await this.t.stream(\"POST\", \"/api/v1/agents/chat/stream\", { body: input, signal: opts.signal });\n let content = \"\";\n let reasoning = \"\";\n for await (const ev of readSSEEvents(body, { signal: opts.signal })) {\n const payload = parseSSEData<{ choices?: { delta?: { content?: string; reasoning?: string; reasoning_content?: string } }[] }>(ev.data);\n if (!payload) continue; // [DONE] or malformed chunk\n const delta = payload.choices?.[0]?.delta;\n const text = typeof delta?.content === \"string\" ? delta.content : undefined;\n const reason =\n typeof delta?.reasoning === \"string\"\n ? delta.reasoning\n : typeof delta?.reasoning_content === \"string\"\n ? delta.reasoning_content\n : undefined;\n if (text) content += text;\n if (reason) reasoning += reason;\n if (text || reason) yield { type: \"delta\", content: text, reasoning: reason };\n }\n yield { type: \"done\", content, reasoning: reasoning || undefined };\n }\n}\n\n/** Workflows namespace. */\nexport class WorkflowsApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/workflows/:id/run — start a run (returns immediately, HTTP 202). */\n run(workflowId: string, input: WorkflowRunInput = {}): Promise<WorkflowRunStart> {\n return this.t.json<WorkflowRunStart>(\"POST\", `/api/v1/workflows/${encodeURIComponent(workflowId)}/run`, { body: input });\n }\n\n /** GET /api/v1/workflow-runs/:runId — poll a run. */\n getRun(runId: string): Promise<WorkflowRun> {\n return this.t.json<WorkflowRun>(\"GET\", `/api/v1/workflow-runs/${encodeURIComponent(runId)}`);\n }\n}\n\n/** Tasks namespace. */\nexport class TasksApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/tasks — create (enqueue) a background task. Does NOT trigger execution. */\n create(input: TaskCreateInput): Promise<TaskCreated> {\n return this.t.json<TaskCreated>(\"POST\", \"/api/v1/tasks\", { body: input });\n }\n\n /** GET /api/v1/tasks/:taskId — fetch the current snapshot. */\n get(taskId: string, signal?: AbortSignal): Promise<Task> {\n return this.t.json<Task>(\"GET\", `/api/v1/tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** Get a handle for polling / waiting on a task (poll(), wait()). */\n handle(taskId: string): TaskHandle {\n return new TaskHandle(this.t, taskId);\n }\n}\n\n/** Images namespace (tiered image generation). */\nexport class ImagesApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/images/models — list tiered image models + runtime availability. */\n listModels(): Promise<ImageModelsResult> {\n return this.t.json<ImageModelsResult>(\"GET\", \"/api/v1/images/models\");\n }\n\n /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */\n generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult> {\n return this.t.json<ImageGenerateResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });\n }\n}\n\n/** Videos namespace (tiered video generation: submit → poll). */\nexport class VideosApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/videos/models — list tiered video models + engine availability. */\n listModels(): Promise<VideoModelsResult> {\n return this.t.json<VideoModelsResult>(\"GET\", \"/api/v1/videos/models\");\n }\n\n /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */\n generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated> {\n return this.t.json<VideoTaskCreated>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });\n }\n\n /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */\n getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"GET\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });\n }\n\n /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */\n cancelTask(taskId: string): Promise<VideoTask> {\n return this.t.json<VideoTask>(\"DELETE\", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);\n }\n\n /** Get a handle for polling / waiting on a video job (poll(), wait()). */\n handle(taskId: string): VideoTaskHandle {\n return new VideoTaskHandle(this.t, taskId);\n }\n}\n\n/** Audio namespace (text-to-speech). */\nexport class AudioApi {\n constructor(private readonly t: Transport) {}\n\n /** GET /api/v1/audio/voices — list available TTS voices. */\n voices(): Promise<VoicesResult> {\n return this.t.json<VoicesResult>(\"GET\", \"/api/v1/audio/voices\");\n }\n\n /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */\n textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult> {\n return this.t.json<TtsResult>(\"POST\", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });\n }\n}\n\n/** Files namespace (media uploads). */\nexport class FilesApi {\n constructor(private readonly t: Transport) {}\n\n /** POST /api/v1/files — upload a media file (multipart field \"file\"). */\n async upload(file: Blob, opts: FileUploadOptions = {}): Promise<UploadedFile> {\n const form = new FormData();\n if (opts.filename !== undefined) {\n form.append(\"file\", file, opts.filename);\n } else {\n form.append(\"file\", file);\n }\n // Coarse progress only: fetch does not expose upload byte progress.\n opts.onProgress?.(0);\n const result = await this.t.form<UploadedFile>(\"/api/v1/files\", { form });\n opts.onProgress?.(100);\n return result;\n }\n}\n\nfunction readEnvBaseUrl(): string | undefined {\n try {\n if (typeof process !== \"undefined\" && process?.env) {\n return process.env.QL_BASE_URL || undefined;\n }\n } catch {\n /* non-Node runtime */\n }\n return undefined;\n}\n\n/**\n * The public client. Example:\n * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });\n * const agents = await ql.agents.list();\n */\nexport class QLClient {\n readonly workspace: WorkspaceApi;\n readonly agents: AgentsApi;\n readonly workflows: WorkflowsApi;\n readonly tasks: TasksApi;\n readonly images: ImagesApi;\n readonly videos: VideosApi;\n readonly audio: AudioApi;\n readonly files: FilesApi;\n\n private readonly transport: Transport;\n private readonly base: string;\n\n constructor(opts: QLClientOptions) {\n if (!opts || typeof opts.apiKey !== \"string\" || opts.apiKey.length === 0) {\n throw new QLError(\"apiKey is required\", { code: \"validation_error\" });\n }\n this.base = normalizeUrl(opts.baseUrl ?? readEnvBaseUrl() ?? DEFAULT_BASE_URL);\n const fetchImpl = (opts.fetch ?? globalThis.fetch).bind(globalThis);\n this.transport = createTransport({ apiKey: opts.apiKey, baseUrl: this.base, fetchImpl });\n this.workspace = new WorkspaceApi(this.transport);\n this.agents = new AgentsApi(this.transport);\n this.workflows = new WorkflowsApi(this.transport);\n this.tasks = new TasksApi(this.transport);\n this.images = new ImagesApi(this.transport);\n this.videos = new VideosApi(this.transport);\n this.audio = new AudioApi(this.transport);\n this.files = new FilesApi(this.transport);\n }\n\n /** The normalized base URL in use (not secret). */\n get baseUrl(): string {\n return this.base;\n }\n}\n","/**\n * Public request/response types for the Quanton Labs agent platform API (v1).\n *\n * These mirror the verified Phase 1 endpoints. The public surface is enveloped:\n * success -> { ok: true, data }\n * error -> { ok: false, error: { code, message } }\n * The SDK unwraps `data` for you and surfaces errors as a typed QLError.\n */\n\n/** Stable API error codes emitted by the backend. */\nexport const API_ERROR_CODES = {\n unauthorized: \"unauthorized\",\n forbidden: \"forbidden\",\n notFound: \"not_found\",\n validationError: \"validation_error\",\n conflict: \"conflict\",\n internalError: \"internal_error\",\n} as const;\n\nexport type ApiErrorCode = (typeof API_ERROR_CODES)[keyof typeof API_ERROR_CODES];\n\n/** A single message in a chat conversation. */\nexport interface ChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Input for `agents.chat` and `agents.chatStream`. */\nexport interface ChatInput {\n agentId: string;\n messages: ChatMessage[];\n /** Optional internal user id; defaults to the key's workspace when omitted. */\n userId?: string;\n /** Optional OpenRouter response-format hint (e.g. `{ type: \"json_object\" }`). */\n response_format?: Record<string, unknown>;\n}\n\n/** Result of a non-streaming chat call. */\nexport interface ChatResult {\n content: string;\n toolCalls: number;\n iterations: number;\n /** Human-readable duration string, e.g. \"2.91s\". */\n duration: string;\n}\n\n/**\n * A single event yielded by `agents.chatStream`.\n * - `delta`: an incremental piece of the streamed response (text and/or reasoning).\n * - `done`: emitted once at the end with the fully accumulated text.\n */\nexport type ChatStreamEvent =\n | { type: \"delta\"; content?: string; reasoning?: string }\n | { type: \"done\"; content: string; reasoning?: string };\n\n/** Options accepted by streaming methods. */\nexport interface StreamOptions {\n /** Abort the in-flight request/stream at any time. */\n signal?: AbortSignal;\n}\n\n/** A conversation-history page (newest first). */\nexport interface MessageItem {\n id: string;\n role: string;\n content: string | null;\n reasoning?: string;\n toolCalls: unknown[];\n status: string;\n timestamp: string | Date;\n}\n\nexport interface HistoryPage {\n agentId: string;\n limit: number;\n /** Cursor for the next page (pass as `before`); null when exhausted. */\n nextBefore: string | null;\n items: MessageItem[];\n}\n\n/** Query params for `agents.history`. */\nexport interface HistoryParams {\n /** Page size, 1..100 (default 20 server-side). */\n limit?: number;\n /** Cursor = id of the last item on the previous page. */\n before?: string;\n /** Optional internal user id filter. */\n userId?: string;\n}\n\n/** Agent summary as returned by `agents.list`. */\nexport interface AgentSummary {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n capabilityCount: number;\n}\n\nexport interface AgentListResult {\n agents: AgentSummary[];\n}\n\n/** A schema-driven capability parameter (rendered as a form field in the UI). */\nexport type CapParamKind = \"text\" | \"textarea\" | \"number\" | \"select\" | \"boolean\" | \"json\";\n\nexport interface CapabilityParam {\n key: string;\n label: string;\n kind: CapParamKind;\n placeholder?: string;\n options?: { value: string; label: string }[];\n required?: boolean;\n hint?: string;\n rows?: number;\n [key: string]: unknown;\n}\n\n/** A pre-filled example input set (suggestion chip). */\nexport interface CapabilityTemplate {\n label: string;\n values: Record<string, unknown>;\n}\n\n/** A client-safe capability descriptor (the server-side `run` is stripped). */\nexport interface CapabilityInfo {\n id: string;\n name: string;\n description: string;\n category: string;\n icon?: string;\n badge?: string;\n params: CapabilityParam[];\n templates?: CapabilityTemplate[];\n metrics?: string[];\n tableKey?: string;\n outputHint?: string;\n [key: string]: unknown;\n}\n\n/** Agent detail + its capabilities, as returned by `agents.get`. */\nexport interface AgentDetail {\n agent: {\n id: string;\n name: string;\n domain: string;\n description: string;\n icon: string;\n tags: string[];\n };\n capabilities: CapabilityInfo[];\n}\n\n/** Result of `agents.capabilities`. */\nexport interface CapabilitiesResult {\n agentId: string;\n capabilities: CapabilityInfo[];\n}\n\n/** Input for `agents.runCapability`. */\nexport interface RunCapabilityInput {\n capId: string;\n /** Capability-specific parameters (see the capability's `params`). */\n params?: Record<string, unknown>;\n}\n\n/**\n * The result of running a capability. A discriminated union matching the\n * backend — a feature can return text, structured JSON, HTML, or a file URL.\n */\nexport type CapabilityResult =\n | { type: \"text\"; content: string }\n | { type: \"json\"; data: unknown }\n | { type: \"html\"; html: string }\n | { type: \"file\"; url: string; filename: string; mime: string };\n\n/** Result envelope for `agents.runCapability`. */\nexport interface RunCapabilityResult {\n result: CapabilityResult;\n}\n\n/** The workspace object as returned by the public API (redacted). */\nexport interface Workspace {\n _id: string;\n name: string;\n plan?: string;\n createdAt?: string | Date;\n updatedAt?: string | Date;\n}\n\n/** Input for `workflows.run`. */\nexport interface WorkflowRunInput {\n /** Optional workflow input payload. */\n input?: Record<string, unknown>;\n}\n\n/** Returned immediately when a workflow run is started (HTTP 202). */\nexport interface WorkflowRunStart {\n runId: string;\n status: \"running\";\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A workflow run snapshot, as returned by `workflows.getRun`. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n output: unknown | null;\n error?: string;\n durationMs?: number;\n startedAt: string | Date;\n finishedAt: string | Date | null;\n}\n\nexport type TaskPriority = \"low\" | \"medium\" | \"high\" | \"urgent\";\n\n/** Input for `tasks.create`. */\nexport interface TaskCreateInput {\n agentId: string;\n title: string;\n description?: string;\n /** Arbitrary payload handed to the agent. */\n input?: unknown;\n priority?: TaskPriority;\n}\n\n/** Returned when a task is created (HTTP 201). */\nexport interface TaskCreated {\n taskId: string;\n status: TaskStatus;\n}\n\nexport type TaskStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | \"retrying\"\n | (string & {});\n\n/** A task snapshot, as returned by `tasks.get`. */\nexport interface Task {\n taskId: string;\n status: TaskStatus;\n title: string;\n progress?: unknown;\n result?: unknown;\n output?: unknown;\n error?: string;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a task. */\nexport interface WaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest task snapshot. */\n onTick?: (task: Task) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Images — tiered image generation\n// ---------------------------------------------------------------------------\n\nexport type ImageTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for an image model. */\nexport interface ImagePricingEntry {\n /** What is billed, e.g. \"output_image\" / \"input_image\". */\n billable: string;\n /** Billing unit: flat per image, or per output-image token. */\n unit: \"image\" | \"token\";\n costUsd: number;\n /** Optional sub-variant (e.g. a resolution tier or quality variant). */\n variant?: string;\n}\n\n/** A tiered image-generation model as returned by `images.listModels`. */\nexport interface ImageModelInfo {\n id: string;\n name: string;\n tier: ImageTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n referenceImageSupport: boolean;\n maxReferenceImages: number;\n /** Empty array = the model does not accept a resolution parameter. */\n supportedResolutions: string[];\n supportedAspectRatios: string[];\n /** Max value for the `n` (images per request) parameter. */\n maxImages: number;\n pricing: {\n /** Human-readable summary, e.g. \"$0.018 / image\". */\n summary: string;\n entries: ImagePricingEntry[];\n };\n recommended: boolean;\n /** Static registry flag (always reflects the shipped registry). */\n enabled: boolean;\n /** Runtime availability — live when `verified` is true. */\n available: boolean;\n /** Whether `available` reflects a live OpenRouter check. */\n verified: boolean;\n}\n\n/** Result of `images.listModels`. */\nexport interface ImageModelsResult {\n models: ImageModelInfo[];\n availability: {\n /** True when the availability values came from a fresh OpenRouter check. */\n fresh: boolean;\n verifiedAt: string | Date | null;\n };\n}\n\n/** A reference image for generation. */\nexport interface ImageReferenceInput {\n /** Base64 data URL, e.g. \"data:image/png;base64,...\". */\n dataUrl: string;\n /** Optional instruction on how this reference should influence the output. */\n description?: string;\n}\n\n/** Input for `images.generate`. */\nexport interface ImageGenerateInput {\n prompt: string;\n /** Explicit OpenRouter model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: ImageTier | string;\n references?: ImageReferenceInput[];\n resolution?: string;\n aspect_ratio?: string;\n n?: number;\n}\n\n/** A single generated image. */\nexport interface GeneratedImage {\n /** Base64-encoded image bytes (no data-URL prefix). */\n b64Json: string;\n mediaType: string;\n}\n\n/** Token + cost usage for a generation, as reported by the provider. */\nexport interface ImageUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n /** Actual cost in USD. */\n cost: number;\n}\n\n/** Result of `images.generate`. */\nexport interface ImageGenerateResult {\n images: GeneratedImage[];\n usage: ImageUsage | null;\n model: string;\n tier: string;\n latencyMs: number;\n}\n\n// ---------------------------------------------------------------------------\n// Videos — tiered video generation (async: submit → poll)\n// ---------------------------------------------------------------------------\n\nexport type VideoTier = \"standard\" | \"professional\" | \"advanced\";\n\n/** A single pricing entry for a video model. */\nexport interface VideoPricingEntry {\n /** What is billed, e.g. \"output_video\" / \"voiceover\". */\n billable: string;\n /** Billing unit: per rendered second, or flat per request. */\n unit: \"second\" | \"request\";\n costUsd: number;\n}\n\n/** A tiered video-generation model as returned by `videos.listModels`. */\nexport interface VideoModelInfo {\n id: string;\n name: string;\n tier: VideoTier;\n description: string;\n /** Short best-use-case label for UI copy. */\n bestFor: string;\n /** Execution engine (e.g. \"motion-graphics\"). */\n engine: string;\n supportsProductImages: boolean;\n maxReferenceImages: number;\n supportsReferenceVideos: boolean;\n maxReferenceVideos: number;\n supportedAspectRatios: string[];\n supportedResolutions: string[];\n /** Inclusive [min, max] duration in seconds. */\n durationRange: [number, number];\n voiceoverSupport: boolean;\n pricing: {\n summary: string;\n entries: VideoPricingEntry[];\n };\n recommended: boolean;\n enabled: boolean;\n /** Runtime engine availability (render toolchain present). */\n available: boolean;\n}\n\n/** Result of `videos.listModels`. */\nexport interface VideoModelsResult {\n models: VideoModelInfo[];\n engine: {\n available: boolean;\n detail: string;\n };\n}\n\n/** Input for `videos.generate`. */\nexport interface VideoGenerateInput {\n /** The creative brief / script for the video. */\n prompt: string;\n /** Explicit registry model id (wins over `tier`). */\n model?: string;\n /** Tier to resolve a model from (used when `model` is omitted). */\n tier?: VideoTier | string;\n /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */\n images_list?: string[];\n /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */\n video_files?: string[];\n /** e.g. \"16:9\", \"9:16\", \"1:1\". Default \"16:9\". */\n aspect_ratio?: string;\n /** Duration in seconds (must be within the model's durationRange). */\n duration?: number;\n /** e.g. \"720p\" | \"1080p\". Default \"720p\". */\n resolution?: string;\n /** Bake an ElevenLabs voiceover into the render (requires `narration`). */\n generate_audio?: boolean;\n /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */\n narration?: string;\n}\n\n/** Returned when a video job is created (HTTP 202). */\nexport interface VideoTaskCreated {\n taskId: string;\n status: \"queued\";\n}\n\nexport type VideoTaskStatus =\n | \"queued\"\n | \"rendering\"\n | \"completed\"\n | \"failed\"\n | \"cancelled\"\n | (string & {});\n\n/** A video job snapshot, as returned by `videos.getTask`. */\nexport interface VideoTask {\n taskId: string;\n status: VideoTaskStatus;\n progress?: {\n current: number;\n total: number;\n message?: string;\n };\n /** Served media path (e.g. /generated/video-….mp4) once completed. */\n outputUrl?: string;\n mime?: string;\n ext?: string;\n /** Actual rendered duration in seconds. */\n durationSec?: number;\n error?: string;\n model?: string;\n tier?: string;\n latencyMs?: number;\n createdAt: string | Date;\n completedAt: string | Date | null;\n}\n\n/** Options for polling / waiting on a video job. */\nexport interface VideoWaitOptions {\n /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */\n intervalMs?: number;\n /** Upper bound for the backoff delay in ms (default 15000). */\n maxIntervalMs?: number;\n /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */\n timeoutMs?: number;\n /** Abort polling at any time. */\n signal?: AbortSignal;\n /** Called after each poll with the latest job snapshot. */\n onTick?: (task: VideoTask) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Audio — text-to-speech\n// ---------------------------------------------------------------------------\n\n/** Input for `audio.textToSpeech`. */\nexport interface TtsInput {\n /** Text to synthesize (max 3000 chars). */\n text: string;\n /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */\n voiceId?: string;\n /** Voice stability 0..1 (default 0.5). */\n stability?: number;\n /** Similarity boost 0..1 (default 0.75). */\n similarityBoost?: number;\n}\n\n/** Result of `audio.textToSpeech`. */\nexport interface TtsResult {\n /** Served audio path (e.g. /generated/tts-….mp3). */\n url: string;\n voiceId: string;\n modelId: string;\n bytes: number;\n latencyMs: number;\n}\n\n/** A single ElevenLabs voice as returned by `audio.voices`. */\nexport interface VoiceInfo {\n id: string;\n name: string;\n}\n\n/** Result of `audio.voices`. */\nexport interface VoicesResult {\n voices: VoiceInfo[];\n /** \"live\" = fetched from the provider; \"none\" = no provider key configured. */\n source: \"live\" | \"none\";\n note?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Files — media uploads\n// ---------------------------------------------------------------------------\n\n/** Result of `files.upload`. */\nexport interface UploadedFile {\n /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */\n url: string;\n filename: string;\n size: number;\n contentType: string;\n}\n\n/** Options for `files.upload`. */\nexport interface FileUploadOptions {\n /** Override the stored display name (extension is kept from the file). */\n filename?: string;\n /**\n * Coarse progress callback. Fetch does not expose upload byte progress, so this\n * reports 0 at start and 100 on completion.\n */\n onProgress?: (percent: number) => void;\n}\n"],"mappings":"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","names":[]}