ql-agent-sdk 1.0.1 → 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/dist/index.d.ts CHANGED
@@ -4,6 +4,11 @@ interface JsonRequestOptions {
4
4
  signal?: AbortSignal;
5
5
  headers?: Record<string, string>;
6
6
  }
7
+ interface FormRequestOptions {
8
+ form: FormData;
9
+ signal?: AbortSignal;
10
+ headers?: Record<string, string>;
11
+ }
7
12
  /**
8
13
  * Internal transport used by the API namespaces. Keeps the API key inside a
9
14
  * closure (never exposed) and normalizes responses/errors for the caller.
@@ -11,6 +16,8 @@ interface JsonRequestOptions {
11
16
  interface Transport {
12
17
  /** Perform a JSON request and return the unwrapped `data` payload. */
13
18
  json<T>(method: string, path: string, opts?: JsonRequestOptions): Promise<T>;
19
+ /** Perform a multipart/form-data request and return the unwrapped `data` payload. */
20
+ form<T>(path: string, opts: FormRequestOptions): Promise<T>;
14
21
  /**
15
22
  * Perform a request expected to stream SSE. Returns the response body stream
16
23
  * after verifying a 2xx + text/event-stream; throws QLError otherwise.
@@ -270,6 +277,254 @@ interface WaitOptions {
270
277
  /** Called after each poll with the latest task snapshot. */
271
278
  onTick?: (task: Task) => void;
272
279
  }
280
+ type ImageTier = "standard" | "professional" | "advanced";
281
+ /** A single pricing entry for an image model. */
282
+ interface ImagePricingEntry {
283
+ /** What is billed, e.g. "output_image" / "input_image". */
284
+ billable: string;
285
+ /** Billing unit: flat per image, or per output-image token. */
286
+ unit: "image" | "token";
287
+ costUsd: number;
288
+ /** Optional sub-variant (e.g. a resolution tier or quality variant). */
289
+ variant?: string;
290
+ }
291
+ /** A tiered image-generation model as returned by `images.listModels`. */
292
+ interface ImageModelInfo {
293
+ id: string;
294
+ name: string;
295
+ tier: ImageTier;
296
+ description: string;
297
+ /** Short best-use-case label for UI copy. */
298
+ bestFor: string;
299
+ referenceImageSupport: boolean;
300
+ maxReferenceImages: number;
301
+ /** Empty array = the model does not accept a resolution parameter. */
302
+ supportedResolutions: string[];
303
+ supportedAspectRatios: string[];
304
+ /** Max value for the `n` (images per request) parameter. */
305
+ maxImages: number;
306
+ pricing: {
307
+ /** Human-readable summary, e.g. "$0.018 / image". */
308
+ summary: string;
309
+ entries: ImagePricingEntry[];
310
+ };
311
+ recommended: boolean;
312
+ /** Static registry flag (always reflects the shipped registry). */
313
+ enabled: boolean;
314
+ /** Runtime availability — live when `verified` is true. */
315
+ available: boolean;
316
+ /** Whether `available` reflects a live OpenRouter check. */
317
+ verified: boolean;
318
+ }
319
+ /** Result of `images.listModels`. */
320
+ interface ImageModelsResult {
321
+ models: ImageModelInfo[];
322
+ availability: {
323
+ /** True when the availability values came from a fresh OpenRouter check. */
324
+ fresh: boolean;
325
+ verifiedAt: string | Date | null;
326
+ };
327
+ }
328
+ /** A reference image for generation. */
329
+ interface ImageReferenceInput {
330
+ /** Base64 data URL, e.g. "data:image/png;base64,...". */
331
+ dataUrl: string;
332
+ /** Optional instruction on how this reference should influence the output. */
333
+ description?: string;
334
+ }
335
+ /** Input for `images.generate`. */
336
+ interface ImageGenerateInput {
337
+ prompt: string;
338
+ /** Explicit OpenRouter model id (wins over `tier`). */
339
+ model?: string;
340
+ /** Tier to resolve a model from (used when `model` is omitted). */
341
+ tier?: ImageTier | string;
342
+ references?: ImageReferenceInput[];
343
+ resolution?: string;
344
+ aspect_ratio?: string;
345
+ n?: number;
346
+ }
347
+ /** A single generated image. */
348
+ interface GeneratedImage {
349
+ /** Base64-encoded image bytes (no data-URL prefix). */
350
+ b64Json: string;
351
+ mediaType: string;
352
+ }
353
+ /** Token + cost usage for a generation, as reported by the provider. */
354
+ interface ImageUsage {
355
+ promptTokens: number;
356
+ completionTokens: number;
357
+ totalTokens: number;
358
+ /** Actual cost in USD. */
359
+ cost: number;
360
+ }
361
+ /** Result of `images.generate`. */
362
+ interface ImageGenerateResult {
363
+ images: GeneratedImage[];
364
+ usage: ImageUsage | null;
365
+ model: string;
366
+ tier: string;
367
+ latencyMs: number;
368
+ }
369
+ type VideoTier = "standard" | "professional" | "advanced";
370
+ /** A single pricing entry for a video model. */
371
+ interface VideoPricingEntry {
372
+ /** What is billed, e.g. "output_video" / "voiceover". */
373
+ billable: string;
374
+ /** Billing unit: per rendered second, or flat per request. */
375
+ unit: "second" | "request";
376
+ costUsd: number;
377
+ }
378
+ /** A tiered video-generation model as returned by `videos.listModels`. */
379
+ interface VideoModelInfo {
380
+ id: string;
381
+ name: string;
382
+ tier: VideoTier;
383
+ description: string;
384
+ /** Short best-use-case label for UI copy. */
385
+ bestFor: string;
386
+ /** Execution engine (e.g. "motion-graphics"). */
387
+ engine: string;
388
+ supportsProductImages: boolean;
389
+ maxReferenceImages: number;
390
+ supportsReferenceVideos: boolean;
391
+ maxReferenceVideos: number;
392
+ supportedAspectRatios: string[];
393
+ supportedResolutions: string[];
394
+ /** Inclusive [min, max] duration in seconds. */
395
+ durationRange: [number, number];
396
+ voiceoverSupport: boolean;
397
+ pricing: {
398
+ summary: string;
399
+ entries: VideoPricingEntry[];
400
+ };
401
+ recommended: boolean;
402
+ enabled: boolean;
403
+ /** Runtime engine availability (render toolchain present). */
404
+ available: boolean;
405
+ }
406
+ /** Result of `videos.listModels`. */
407
+ interface VideoModelsResult {
408
+ models: VideoModelInfo[];
409
+ engine: {
410
+ available: boolean;
411
+ detail: string;
412
+ };
413
+ }
414
+ /** Input for `videos.generate`. */
415
+ interface VideoGenerateInput {
416
+ /** The creative brief / script for the video. */
417
+ prompt: string;
418
+ /** Explicit registry model id (wins over `tier`). */
419
+ model?: string;
420
+ /** Tier to resolve a model from (used when `model` is omitted). */
421
+ tier?: VideoTier | string;
422
+ /** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */
423
+ images_list?: string[];
424
+ /** Reference (style) videos — https URLs only (upload local files via `files.upload`). */
425
+ video_files?: string[];
426
+ /** e.g. "16:9", "9:16", "1:1". Default "16:9". */
427
+ aspect_ratio?: string;
428
+ /** Duration in seconds (must be within the model's durationRange). */
429
+ duration?: number;
430
+ /** e.g. "720p" | "1080p". Default "720p". */
431
+ resolution?: string;
432
+ /** Bake an ElevenLabs voiceover into the render (requires `narration`). */
433
+ generate_audio?: boolean;
434
+ /** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */
435
+ narration?: string;
436
+ }
437
+ /** Returned when a video job is created (HTTP 202). */
438
+ interface VideoTaskCreated {
439
+ taskId: string;
440
+ status: "queued";
441
+ }
442
+ type VideoTaskStatus = "queued" | "rendering" | "completed" | "failed" | "cancelled" | (string & {});
443
+ /** A video job snapshot, as returned by `videos.getTask`. */
444
+ interface VideoTask {
445
+ taskId: string;
446
+ status: VideoTaskStatus;
447
+ progress?: {
448
+ current: number;
449
+ total: number;
450
+ message?: string;
451
+ };
452
+ /** Served media path (e.g. /generated/video-….mp4) once completed. */
453
+ outputUrl?: string;
454
+ mime?: string;
455
+ ext?: string;
456
+ /** Actual rendered duration in seconds. */
457
+ durationSec?: number;
458
+ error?: string;
459
+ model?: string;
460
+ tier?: string;
461
+ latencyMs?: number;
462
+ createdAt: string | Date;
463
+ completedAt: string | Date | null;
464
+ }
465
+ /** Options for polling / waiting on a video job. */
466
+ interface VideoWaitOptions {
467
+ /** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */
468
+ intervalMs?: number;
469
+ /** Upper bound for the backoff delay in ms (default 15000). */
470
+ maxIntervalMs?: number;
471
+ /** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */
472
+ timeoutMs?: number;
473
+ /** Abort polling at any time. */
474
+ signal?: AbortSignal;
475
+ /** Called after each poll with the latest job snapshot. */
476
+ onTick?: (task: VideoTask) => void;
477
+ }
478
+ /** Input for `audio.textToSpeech`. */
479
+ interface TtsInput {
480
+ /** Text to synthesize (max 3000 chars). */
481
+ text: string;
482
+ /** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */
483
+ voiceId?: string;
484
+ /** Voice stability 0..1 (default 0.5). */
485
+ stability?: number;
486
+ /** Similarity boost 0..1 (default 0.75). */
487
+ similarityBoost?: number;
488
+ }
489
+ /** Result of `audio.textToSpeech`. */
490
+ interface TtsResult {
491
+ /** Served audio path (e.g. /generated/tts-….mp3). */
492
+ url: string;
493
+ voiceId: string;
494
+ modelId: string;
495
+ bytes: number;
496
+ latencyMs: number;
497
+ }
498
+ /** A single ElevenLabs voice as returned by `audio.voices`. */
499
+ interface VoiceInfo {
500
+ id: string;
501
+ name: string;
502
+ }
503
+ /** Result of `audio.voices`. */
504
+ interface VoicesResult {
505
+ voices: VoiceInfo[];
506
+ /** "live" = fetched from the provider; "none" = no provider key configured. */
507
+ source: "live" | "none";
508
+ note?: string;
509
+ }
510
+ /** Result of `files.upload`. */
511
+ interface UploadedFile {
512
+ /** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */
513
+ url: string;
514
+ filename: string;
515
+ size: number;
516
+ contentType: string;
517
+ }
518
+ /** Options for `files.upload`. */
519
+ interface FileUploadOptions {
520
+ /** Override the stored display name (extension is kept from the file). */
521
+ filename?: string;
522
+ /**
523
+ * Coarse progress callback. Fetch does not expose upload byte progress, so this
524
+ * reports 0 at start and 100 on completion.
525
+ */
526
+ onProgress?: (percent: number) => void;
527
+ }
273
528
 
274
529
  declare function isTerminalTaskStatus(status: string): boolean;
275
530
  /**
@@ -288,15 +543,24 @@ declare class TaskHandle {
288
543
  get(signal?: AbortSignal): Promise<Task>;
289
544
  /** Alias of `get()` — perform one poll and return the latest snapshot. */
290
545
  poll(signal?: AbortSignal): Promise<Task>;
291
- /**
292
- * Poll until the task reaches a terminal status.
293
- *
294
- * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.
295
- * - Throws a QLError with code "timeout" if `timeoutMs` elapses first.
296
- * - Throws a QLError with code "aborted" if `signal` aborts.
297
- */
546
+ /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */
298
547
  wait(opts?: WaitOptions): Promise<Task>;
299
548
  }
549
+ /**
550
+ * A handle to a video job created via `videos.generate`.
551
+ * Polls the video-tasks endpoint until the job reaches a terminal status.
552
+ */
553
+ declare class VideoTaskHandle {
554
+ private readonly transport;
555
+ readonly taskId: string;
556
+ constructor(transport: Transport, taskId: string);
557
+ /** Fetch the current job snapshot (single request). */
558
+ get(signal?: AbortSignal): Promise<VideoTask>;
559
+ /** Alias of `get()` — perform one poll and return the latest snapshot. */
560
+ poll(signal?: AbortSignal): Promise<VideoTask>;
561
+ /** Poll until the job reaches a terminal status (completed/failed/cancelled). */
562
+ wait(opts?: VideoWaitOptions): Promise<VideoTask>;
563
+ }
300
564
 
301
565
  declare const DEFAULT_BASE_URL = "https://app.quantonlabs.com";
302
566
  interface QLClientOptions {
@@ -360,6 +624,46 @@ declare class TasksApi {
360
624
  /** Get a handle for polling / waiting on a task (poll(), wait()). */
361
625
  handle(taskId: string): TaskHandle;
362
626
  }
627
+ /** Images namespace (tiered image generation). */
628
+ declare class ImagesApi {
629
+ private readonly t;
630
+ constructor(t: Transport);
631
+ /** GET /api/v1/images/models — list tiered image models + runtime availability. */
632
+ listModels(): Promise<ImageModelsResult>;
633
+ /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */
634
+ generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult>;
635
+ }
636
+ /** Videos namespace (tiered video generation: submit → poll). */
637
+ declare class VideosApi {
638
+ private readonly t;
639
+ constructor(t: Transport);
640
+ /** GET /api/v1/videos/models — list tiered video models + engine availability. */
641
+ listModels(): Promise<VideoModelsResult>;
642
+ /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */
643
+ generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated>;
644
+ /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */
645
+ getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask>;
646
+ /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */
647
+ cancelTask(taskId: string): Promise<VideoTask>;
648
+ /** Get a handle for polling / waiting on a video job (poll(), wait()). */
649
+ handle(taskId: string): VideoTaskHandle;
650
+ }
651
+ /** Audio namespace (text-to-speech). */
652
+ declare class AudioApi {
653
+ private readonly t;
654
+ constructor(t: Transport);
655
+ /** GET /api/v1/audio/voices — list available TTS voices. */
656
+ voices(): Promise<VoicesResult>;
657
+ /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */
658
+ textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult>;
659
+ }
660
+ /** Files namespace (media uploads). */
661
+ declare class FilesApi {
662
+ private readonly t;
663
+ constructor(t: Transport);
664
+ /** POST /api/v1/files — upload a media file (multipart field "file"). */
665
+ upload(file: Blob, opts?: FileUploadOptions): Promise<UploadedFile>;
666
+ }
363
667
  /**
364
668
  * The public client. Example:
365
669
  * const ql = new QLClient({ apiKey: process.env.QL_API_KEY });
@@ -370,6 +674,10 @@ declare class QLClient {
370
674
  readonly agents: AgentsApi;
371
675
  readonly workflows: WorkflowsApi;
372
676
  readonly tasks: TasksApi;
677
+ readonly images: ImagesApi;
678
+ readonly videos: VideosApi;
679
+ readonly audio: AudioApi;
680
+ readonly files: FilesApi;
373
681
  private readonly transport;
374
682
  private readonly base;
375
683
  constructor(opts: QLClientOptions);
@@ -413,4 +721,4 @@ declare class QLError extends Error {
413
721
  get isNetworkError(): boolean;
414
722
  }
415
723
 
416
- export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, DEFAULT_BASE_URL, type HistoryPage, type HistoryParams, type MessageItem, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
724
+ export { API_ERROR_CODES, type AgentDetail, type AgentListResult, type AgentSummary, AgentsApi, type ApiErrorCode, AudioApi, type CapParamKind, type CapabilitiesResult, type CapabilityInfo, type CapabilityParam, type CapabilityResult, type CapabilityTemplate, type ChatInput, type ChatMessage, type ChatResult, type ChatStreamEvent, DEFAULT_BASE_URL, type FileUploadOptions, FilesApi, type GeneratedImage, type HistoryPage, type HistoryParams, type ImageGenerateInput, type ImageGenerateResult, type ImageModelInfo, type ImageModelsResult, type ImagePricingEntry, type ImageReferenceInput, type ImageTier, type ImageUsage, ImagesApi, type MessageItem, QLClient, type QLClientOptions, QLError, type QLErrorContext, type RunCapabilityInput, type RunCapabilityResult, type StreamOptions, type Task, type TaskCreateInput, type TaskCreated, TaskHandle, type TaskPriority, type TaskStatus, TasksApi, type TtsInput, type TtsResult, type UploadedFile, type VideoGenerateInput, type VideoModelInfo, type VideoModelsResult, type VideoPricingEntry, type VideoTask, type VideoTaskCreated, VideoTaskHandle, type VideoTaskStatus, type VideoTier, type VideoWaitOptions, VideosApi, type VoiceInfo, type VoicesResult, type WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
package/dist/index.js CHANGED
@@ -99,6 +99,12 @@ function createTransport(opts) {
99
99
  if (!res.ok) throw toHttpError(res.status, text, { method, url: res.url });
100
100
  return unwrap(text, { method, url: res.url });
101
101
  },
102
+ async form(path, reqOpts) {
103
+ const res = await doFormFetch(path, reqOpts);
104
+ const text = await res.text();
105
+ if (!res.ok) throw toHttpError(res.status, text, { method: "POST", url: res.url });
106
+ return unwrap(text, { method: "POST", url: res.url });
107
+ },
102
108
  async stream(method, path, reqOpts = {}) {
103
109
  const res = await doFetch(method, path, {
104
110
  ...reqOpts,
@@ -139,6 +145,22 @@ function createTransport(opts) {
139
145
  throw toNetworkError(err, { method, url });
140
146
  });
141
147
  }
148
+ function doFormFetch(path, reqOpts) {
149
+ const url = buildUrl(baseUrl, path);
150
+ const headers = {
151
+ authorization: `Bearer ${apiKey}`,
152
+ accept: "application/json",
153
+ ...reqOpts.headers ?? {}
154
+ };
155
+ return fetchImpl(url, {
156
+ method: "POST",
157
+ headers,
158
+ body: reqOpts.form,
159
+ signal: reqOpts.signal
160
+ }).catch((err) => {
161
+ throw toNetworkError(err, { method: "POST", url });
162
+ });
163
+ }
142
164
  }
143
165
  function unwrap(text, ctx) {
144
166
  const parsed = safeParse(text);
@@ -277,6 +299,27 @@ var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
277
299
  function isTerminalTaskStatus(status) {
278
300
  return TERMINAL_TASK_STATUSES.has(status);
279
301
  }
302
+ async function pollUntilTerminal(fetchSnapshot, isTerminal, onTick, opts) {
303
+ const intervalMs = opts.intervalMs ?? 2e3;
304
+ const maxIntervalMs = opts.maxIntervalMs ?? 15e3;
305
+ const signal = opts.signal;
306
+ const startedAt = Date.now();
307
+ let delay = intervalMs;
308
+ for (; ; ) {
309
+ if (signal?.aborted) throw abortError();
310
+ if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
311
+ throw timeoutError(opts.timeoutMs);
312
+ }
313
+ const snapshot = await fetchSnapshot(signal);
314
+ onTick?.(snapshot);
315
+ if (isTerminal(snapshot)) return snapshot;
316
+ if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
317
+ throw timeoutError(opts.timeoutMs);
318
+ }
319
+ await sleep(delay, signal);
320
+ delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));
321
+ }
322
+ }
280
323
  var TaskHandle = class {
281
324
  constructor(transport, taskId) {
282
325
  this.transport = transport;
@@ -290,33 +333,37 @@ var TaskHandle = class {
290
333
  poll(signal) {
291
334
  return this.get(signal);
292
335
  }
293
- /**
294
- * Poll until the task reaches a terminal status.
295
- *
296
- * - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.
297
- * - Throws a QLError with code "timeout" if `timeoutMs` elapses first.
298
- * - Throws a QLError with code "aborted" if `signal` aborts.
299
- */
336
+ /** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */
300
337
  async wait(opts = {}) {
301
- const intervalMs = opts.intervalMs ?? 2e3;
302
- const maxIntervalMs = opts.maxIntervalMs ?? 15e3;
303
- const signal = opts.signal;
304
- const startedAt = Date.now();
305
- let delay = intervalMs;
306
- for (; ; ) {
307
- if (signal?.aborted) throw abortError();
308
- if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
309
- throw timeoutError(opts.timeoutMs);
310
- }
311
- const task = await this.get(signal);
312
- opts.onTick?.(task);
313
- if (isTerminalTaskStatus(task.status)) return task;
314
- if (opts.timeoutMs !== void 0 && Date.now() - startedAt >= opts.timeoutMs) {
315
- throw timeoutError(opts.timeoutMs);
316
- }
317
- await sleep(delay, signal);
318
- delay = Math.min(maxIntervalMs, Math.round(delay * 1.5));
319
- }
338
+ return pollUntilTerminal(
339
+ (signal) => this.get(signal),
340
+ (task) => isTerminalTaskStatus(task.status),
341
+ opts.onTick,
342
+ opts
343
+ );
344
+ }
345
+ };
346
+ var VideoTaskHandle = class {
347
+ constructor(transport, taskId) {
348
+ this.transport = transport;
349
+ this.taskId = taskId;
350
+ }
351
+ /** Fetch the current job snapshot (single request). */
352
+ get(signal) {
353
+ return this.transport.json("GET", `/api/v1/video-tasks/${encodeURIComponent(this.taskId)}`, { signal });
354
+ }
355
+ /** Alias of `get()` — perform one poll and return the latest snapshot. */
356
+ poll(signal) {
357
+ return this.get(signal);
358
+ }
359
+ /** Poll until the job reaches a terminal status (completed/failed/cancelled). */
360
+ async wait(opts = {}) {
361
+ return pollUntilTerminal(
362
+ (signal) => this.get(signal),
363
+ (task) => isTerminalTaskStatus(task.status),
364
+ opts.onTick,
365
+ opts
366
+ );
320
367
  }
321
368
  };
322
369
  function sleep(ms, signal) {
@@ -441,6 +488,75 @@ var TasksApi = class {
441
488
  return new TaskHandle(this.t, taskId);
442
489
  }
443
490
  };
491
+ var ImagesApi = class {
492
+ constructor(t) {
493
+ this.t = t;
494
+ }
495
+ /** GET /api/v1/images/models — list tiered image models + runtime availability. */
496
+ listModels() {
497
+ return this.t.json("GET", "/api/v1/images/models");
498
+ }
499
+ /** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */
500
+ generate(agentId, input) {
501
+ return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });
502
+ }
503
+ };
504
+ var VideosApi = class {
505
+ constructor(t) {
506
+ this.t = t;
507
+ }
508
+ /** GET /api/v1/videos/models — list tiered video models + engine availability. */
509
+ listModels() {
510
+ return this.t.json("GET", "/api/v1/videos/models");
511
+ }
512
+ /** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */
513
+ generate(agentId, input) {
514
+ return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });
515
+ }
516
+ /** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */
517
+ getTask(taskId, signal) {
518
+ return this.t.json("GET", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });
519
+ }
520
+ /** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */
521
+ cancelTask(taskId) {
522
+ return this.t.json("DELETE", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);
523
+ }
524
+ /** Get a handle for polling / waiting on a video job (poll(), wait()). */
525
+ handle(taskId) {
526
+ return new VideoTaskHandle(this.t, taskId);
527
+ }
528
+ };
529
+ var AudioApi = class {
530
+ constructor(t) {
531
+ this.t = t;
532
+ }
533
+ /** GET /api/v1/audio/voices — list available TTS voices. */
534
+ voices() {
535
+ return this.t.json("GET", "/api/v1/audio/voices");
536
+ }
537
+ /** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */
538
+ textToSpeech(agentId, input) {
539
+ return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });
540
+ }
541
+ };
542
+ var FilesApi = class {
543
+ constructor(t) {
544
+ this.t = t;
545
+ }
546
+ /** POST /api/v1/files — upload a media file (multipart field "file"). */
547
+ async upload(file, opts = {}) {
548
+ const form = new FormData();
549
+ if (opts.filename !== void 0) {
550
+ form.append("file", file, opts.filename);
551
+ } else {
552
+ form.append("file", file);
553
+ }
554
+ opts.onProgress?.(0);
555
+ const result = await this.t.form("/api/v1/files", { form });
556
+ opts.onProgress?.(100);
557
+ return result;
558
+ }
559
+ };
444
560
  function readEnvBaseUrl() {
445
561
  try {
446
562
  if (typeof process !== "undefined" && process?.env) {
@@ -462,6 +578,10 @@ var QLClient = class {
462
578
  this.agents = new AgentsApi(this.transport);
463
579
  this.workflows = new WorkflowsApi(this.transport);
464
580
  this.tasks = new TasksApi(this.transport);
581
+ this.images = new ImagesApi(this.transport);
582
+ this.videos = new VideosApi(this.transport);
583
+ this.audio = new AudioApi(this.transport);
584
+ this.files = new FilesApi(this.transport);
465
585
  }
466
586
  /** The normalized base URL in use (not secret). */
467
587
  get baseUrl() {
@@ -481,11 +601,16 @@ var API_ERROR_CODES = {
481
601
  export {
482
602
  API_ERROR_CODES,
483
603
  AgentsApi,
604
+ AudioApi,
484
605
  DEFAULT_BASE_URL,
606
+ FilesApi,
607
+ ImagesApi,
485
608
  QLClient,
486
609
  QLError,
487
610
  TaskHandle,
488
611
  TasksApi,
612
+ VideoTaskHandle,
613
+ VideosApi,
489
614
  WorkflowsApi,
490
615
  WorkspaceApi,
491
616
  isTerminalTaskStatus