ql-agent-sdk 1.0.2 → 1.2.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 +169 -1
- package/dist/index.cjs +160 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -8
- package/dist/index.d.ts +331 -8
- package/dist/index.js +160 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
@@ -49,6 +56,8 @@ interface ChatInput {
|
|
|
49
56
|
messages: ChatMessage[];
|
|
50
57
|
/** Optional internal user id; defaults to the key's workspace when omitted. */
|
|
51
58
|
userId?: string;
|
|
59
|
+
/** Optional OpenRouter model id override — wins over the workspace director-panel default. */
|
|
60
|
+
modelId?: string;
|
|
52
61
|
/** Optional OpenRouter response-format hint (e.g. `{ type: "json_object" }`). */
|
|
53
62
|
response_format?: Record<string, unknown>;
|
|
54
63
|
}
|
|
@@ -328,6 +337,8 @@ interface ImageReferenceInput {
|
|
|
328
337
|
/** Input for `images.generate`. */
|
|
329
338
|
interface ImageGenerateInput {
|
|
330
339
|
prompt: string;
|
|
340
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
341
|
+
modelId?: string;
|
|
331
342
|
/** Explicit OpenRouter model id (wins over `tier`). */
|
|
332
343
|
model?: string;
|
|
333
344
|
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
@@ -359,6 +370,263 @@ interface ImageGenerateResult {
|
|
|
359
370
|
tier: string;
|
|
360
371
|
latencyMs: number;
|
|
361
372
|
}
|
|
373
|
+
type VideoTier = "standard" | "professional" | "advanced";
|
|
374
|
+
/** A single pricing entry for a video model. */
|
|
375
|
+
interface VideoPricingEntry {
|
|
376
|
+
/** What is billed, e.g. "output_video" / "voiceover". */
|
|
377
|
+
billable: string;
|
|
378
|
+
/** Billing unit: per rendered second, or flat per request. */
|
|
379
|
+
unit: "second" | "request";
|
|
380
|
+
costUsd: number;
|
|
381
|
+
}
|
|
382
|
+
/** A tiered video-generation model as returned by `videos.listModels`. */
|
|
383
|
+
interface VideoModelInfo {
|
|
384
|
+
id: string;
|
|
385
|
+
name: string;
|
|
386
|
+
tier: VideoTier;
|
|
387
|
+
description: string;
|
|
388
|
+
/** Short best-use-case label for UI copy. */
|
|
389
|
+
bestFor: string;
|
|
390
|
+
/** Execution engine (e.g. "motion-graphics"). */
|
|
391
|
+
engine: string;
|
|
392
|
+
supportsProductImages: boolean;
|
|
393
|
+
maxReferenceImages: number;
|
|
394
|
+
supportsReferenceVideos: boolean;
|
|
395
|
+
maxReferenceVideos: number;
|
|
396
|
+
supportedAspectRatios: string[];
|
|
397
|
+
supportedResolutions: string[];
|
|
398
|
+
/** Inclusive [min, max] duration in seconds. */
|
|
399
|
+
durationRange: [number, number];
|
|
400
|
+
voiceoverSupport: boolean;
|
|
401
|
+
pricing: {
|
|
402
|
+
summary: string;
|
|
403
|
+
entries: VideoPricingEntry[];
|
|
404
|
+
};
|
|
405
|
+
recommended: boolean;
|
|
406
|
+
enabled: boolean;
|
|
407
|
+
/** Runtime engine availability (render toolchain present). */
|
|
408
|
+
available: boolean;
|
|
409
|
+
}
|
|
410
|
+
/** Result of `videos.listModels`. */
|
|
411
|
+
interface VideoModelsResult {
|
|
412
|
+
models: VideoModelInfo[];
|
|
413
|
+
engine: {
|
|
414
|
+
available: boolean;
|
|
415
|
+
detail: string;
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/** Input for `videos.generate`. */
|
|
419
|
+
interface VideoGenerateInput {
|
|
420
|
+
/** The creative brief / script for the video. */
|
|
421
|
+
prompt: string;
|
|
422
|
+
/** Explicit registry model id override (wins over `model`, the workspace default, and `tier`). */
|
|
423
|
+
modelId?: string;
|
|
424
|
+
/** Explicit registry model id (wins over `tier`). */
|
|
425
|
+
model?: string;
|
|
426
|
+
/** Tier to resolve a model from (used when `model` is omitted). */
|
|
427
|
+
tier?: VideoTier | string;
|
|
428
|
+
/** Product/reference images — base64 data URLs or https URLs. Order defines IMG_0..N. */
|
|
429
|
+
images_list?: string[];
|
|
430
|
+
/** Reference (style) videos — https URLs only (upload local files via `files.upload`). */
|
|
431
|
+
video_files?: string[];
|
|
432
|
+
/** e.g. "16:9", "9:16", "1:1". Default "16:9". */
|
|
433
|
+
aspect_ratio?: string;
|
|
434
|
+
/** Duration in seconds (must be within the model's durationRange). */
|
|
435
|
+
duration?: number;
|
|
436
|
+
/** e.g. "720p" | "1080p". Default "720p". */
|
|
437
|
+
resolution?: string;
|
|
438
|
+
/** Bake an ElevenLabs voiceover into the render (requires `narration`). */
|
|
439
|
+
generate_audio?: boolean;
|
|
440
|
+
/** Voiceover text (used when `generate_audio` is true). Max 3000 chars. */
|
|
441
|
+
narration?: string;
|
|
442
|
+
}
|
|
443
|
+
/** Returned when a video job is created (HTTP 202). */
|
|
444
|
+
interface VideoTaskCreated {
|
|
445
|
+
taskId: string;
|
|
446
|
+
status: "queued";
|
|
447
|
+
}
|
|
448
|
+
type VideoTaskStatus = "queued" | "rendering" | "completed" | "failed" | "cancelled" | (string & {});
|
|
449
|
+
/** A video job snapshot, as returned by `videos.getTask`. */
|
|
450
|
+
interface VideoTask {
|
|
451
|
+
taskId: string;
|
|
452
|
+
status: VideoTaskStatus;
|
|
453
|
+
progress?: {
|
|
454
|
+
current: number;
|
|
455
|
+
total: number;
|
|
456
|
+
message?: string;
|
|
457
|
+
};
|
|
458
|
+
/** Served media path (e.g. /generated/video-….mp4) once completed. */
|
|
459
|
+
outputUrl?: string;
|
|
460
|
+
mime?: string;
|
|
461
|
+
ext?: string;
|
|
462
|
+
/** Actual rendered duration in seconds. */
|
|
463
|
+
durationSec?: number;
|
|
464
|
+
error?: string;
|
|
465
|
+
model?: string;
|
|
466
|
+
tier?: string;
|
|
467
|
+
latencyMs?: number;
|
|
468
|
+
createdAt: string | Date;
|
|
469
|
+
completedAt: string | Date | null;
|
|
470
|
+
}
|
|
471
|
+
/** Options for polling / waiting on a video job. */
|
|
472
|
+
interface VideoWaitOptions {
|
|
473
|
+
/** Base delay between polls in ms (default 2000). Grows with backoff up to `maxIntervalMs`. */
|
|
474
|
+
intervalMs?: number;
|
|
475
|
+
/** Upper bound for the backoff delay in ms (default 15000). */
|
|
476
|
+
maxIntervalMs?: number;
|
|
477
|
+
/** Stop waiting after this many ms and throw a timeout error. Omit to wait until terminal or abort. */
|
|
478
|
+
timeoutMs?: number;
|
|
479
|
+
/** Abort polling at any time. */
|
|
480
|
+
signal?: AbortSignal;
|
|
481
|
+
/** Called after each poll with the latest job snapshot. */
|
|
482
|
+
onTick?: (task: VideoTask) => void;
|
|
483
|
+
}
|
|
484
|
+
/** Per-role model defaults as configured in the director panel. */
|
|
485
|
+
interface WorkspaceModelConfig {
|
|
486
|
+
status: "active" | "inactive";
|
|
487
|
+
/** Masked OpenRouter key — the raw key is never returned by the API. */
|
|
488
|
+
keyMasked: string;
|
|
489
|
+
/** Optional chat-completions base URL override (empty = public OpenRouter API). */
|
|
490
|
+
baseUrl: string;
|
|
491
|
+
reasoning: string;
|
|
492
|
+
instruct: string;
|
|
493
|
+
response: string;
|
|
494
|
+
vision: string;
|
|
495
|
+
image: string;
|
|
496
|
+
video: string;
|
|
497
|
+
/** Ordered per-role fallback model ids (max 3 each), tried on provider failure. */
|
|
498
|
+
fallbacks: {
|
|
499
|
+
reasoning: string[];
|
|
500
|
+
instruct: string[];
|
|
501
|
+
response: string[];
|
|
502
|
+
vision: string[];
|
|
503
|
+
image: string[];
|
|
504
|
+
video: string[];
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/** Result of `workspace.getModels`. */
|
|
508
|
+
interface WorkspaceModelsResult {
|
|
509
|
+
openrouter: WorkspaceModelConfig;
|
|
510
|
+
}
|
|
511
|
+
/** Partial model-config update for `workspace.update` / `workspace.updateModels`. */
|
|
512
|
+
interface WorkspaceModelsUpdateInput {
|
|
513
|
+
status?: "active" | "inactive";
|
|
514
|
+
/** Full OpenRouter API key to store/rotate. Omit to leave unchanged. */
|
|
515
|
+
key?: string;
|
|
516
|
+
/** Optional chat-completions base URL override (defaults to the public OpenRouter API). */
|
|
517
|
+
baseUrl?: string;
|
|
518
|
+
reasoning?: string;
|
|
519
|
+
instruct?: string;
|
|
520
|
+
response?: string;
|
|
521
|
+
vision?: string;
|
|
522
|
+
image?: string;
|
|
523
|
+
video?: string;
|
|
524
|
+
/** Ordered per-role fallback model ids (max 3 each). */
|
|
525
|
+
fallbacks?: {
|
|
526
|
+
reasoning?: string[];
|
|
527
|
+
instruct?: string[];
|
|
528
|
+
response?: string[];
|
|
529
|
+
vision?: string[];
|
|
530
|
+
image?: string[];
|
|
531
|
+
video?: string[];
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** Input for `workspace.update`. */
|
|
535
|
+
interface WorkspaceUpdateInput {
|
|
536
|
+
name?: string;
|
|
537
|
+
config?: {
|
|
538
|
+
openrouter?: WorkspaceModelsUpdateInput;
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
/** A single OpenRouter catalog model. */
|
|
542
|
+
interface CatalogModel {
|
|
543
|
+
id: string;
|
|
544
|
+
name: string;
|
|
545
|
+
contextLength: number | null;
|
|
546
|
+
promptPrice: number | null;
|
|
547
|
+
completionPrice: number | null;
|
|
548
|
+
}
|
|
549
|
+
/** Result of `workspace.listCatalogModels`. */
|
|
550
|
+
interface CatalogResult {
|
|
551
|
+
models: CatalogModel[];
|
|
552
|
+
/** True when the upstream fetch failed and a cached snapshot was served. */
|
|
553
|
+
stale?: boolean;
|
|
554
|
+
}
|
|
555
|
+
/** Result of `workspace.verifyOpenRouterKey`. */
|
|
556
|
+
interface VerifyKeyResult {
|
|
557
|
+
valid: boolean;
|
|
558
|
+
error?: string;
|
|
559
|
+
}
|
|
560
|
+
/** A v1 API key with rotation metadata (hashes never leave the server). */
|
|
561
|
+
interface ApiKeyInfo {
|
|
562
|
+
_id: string;
|
|
563
|
+
name: string;
|
|
564
|
+
prefix: string;
|
|
565
|
+
scopes: string[];
|
|
566
|
+
createdAt: string | Date;
|
|
567
|
+
lastUsedAt: string | Date | null;
|
|
568
|
+
revokedAt: string | Date | null;
|
|
569
|
+
/** When the key is auto-deleted (createdAt + lifetime). */
|
|
570
|
+
rotatesAt: string | Date;
|
|
571
|
+
/** Whole days remaining until rotation (0 when expired). */
|
|
572
|
+
daysLeft: number;
|
|
573
|
+
}
|
|
574
|
+
/** Result of `workspace.listKeys`. */
|
|
575
|
+
interface KeysResult {
|
|
576
|
+
/** Key lifetime in days before auto-deletion. */
|
|
577
|
+
lifetimeDays: number;
|
|
578
|
+
keys: ApiKeyInfo[];
|
|
579
|
+
}
|
|
580
|
+
/** Input for `audio.textToSpeech`. */
|
|
581
|
+
interface TtsInput {
|
|
582
|
+
/** Text to synthesize (max 3000 chars). */
|
|
583
|
+
text: string;
|
|
584
|
+
/** ElevenLabs voice id (list via `audio.voices`). Defaults to the platform voice. */
|
|
585
|
+
voiceId?: string;
|
|
586
|
+
/** Voice stability 0..1 (default 0.5). */
|
|
587
|
+
stability?: number;
|
|
588
|
+
/** Similarity boost 0..1 (default 0.75). */
|
|
589
|
+
similarityBoost?: number;
|
|
590
|
+
}
|
|
591
|
+
/** Result of `audio.textToSpeech`. */
|
|
592
|
+
interface TtsResult {
|
|
593
|
+
/** Served audio path (e.g. /generated/tts-….mp3). */
|
|
594
|
+
url: string;
|
|
595
|
+
voiceId: string;
|
|
596
|
+
modelId: string;
|
|
597
|
+
bytes: number;
|
|
598
|
+
latencyMs: number;
|
|
599
|
+
}
|
|
600
|
+
/** A single ElevenLabs voice as returned by `audio.voices`. */
|
|
601
|
+
interface VoiceInfo {
|
|
602
|
+
id: string;
|
|
603
|
+
name: string;
|
|
604
|
+
}
|
|
605
|
+
/** Result of `audio.voices`. */
|
|
606
|
+
interface VoicesResult {
|
|
607
|
+
voices: VoiceInfo[];
|
|
608
|
+
/** "live" = fetched from the provider; "none" = no provider key configured. */
|
|
609
|
+
source: "live" | "none";
|
|
610
|
+
note?: string;
|
|
611
|
+
}
|
|
612
|
+
/** Result of `files.upload`. */
|
|
613
|
+
interface UploadedFile {
|
|
614
|
+
/** Stable served path (e.g. /uploads/<workspace>/<file>) usable as a media input URL. */
|
|
615
|
+
url: string;
|
|
616
|
+
filename: string;
|
|
617
|
+
size: number;
|
|
618
|
+
contentType: string;
|
|
619
|
+
}
|
|
620
|
+
/** Options for `files.upload`. */
|
|
621
|
+
interface FileUploadOptions {
|
|
622
|
+
/** Override the stored display name (extension is kept from the file). */
|
|
623
|
+
filename?: string;
|
|
624
|
+
/**
|
|
625
|
+
* Coarse progress callback. Fetch does not expose upload byte progress, so this
|
|
626
|
+
* reports 0 at start and 100 on completion.
|
|
627
|
+
*/
|
|
628
|
+
onProgress?: (percent: number) => void;
|
|
629
|
+
}
|
|
362
630
|
|
|
363
631
|
declare function isTerminalTaskStatus(status: string): boolean;
|
|
364
632
|
/**
|
|
@@ -377,15 +645,24 @@ declare class TaskHandle {
|
|
|
377
645
|
get(signal?: AbortSignal): Promise<Task>;
|
|
378
646
|
/** Alias of `get()` — perform one poll and return the latest snapshot. */
|
|
379
647
|
poll(signal?: AbortSignal): Promise<Task>;
|
|
380
|
-
/**
|
|
381
|
-
* Poll until the task reaches a terminal status.
|
|
382
|
-
*
|
|
383
|
-
* - Uses exponential-ish backoff from `intervalMs` up to `maxIntervalMs`.
|
|
384
|
-
* - Throws a QLError with code "timeout" if `timeoutMs` elapses first.
|
|
385
|
-
* - Throws a QLError with code "aborted" if `signal` aborts.
|
|
386
|
-
*/
|
|
648
|
+
/** Poll until the task reaches a terminal status (see pollUntilTerminal for semantics). */
|
|
387
649
|
wait(opts?: WaitOptions): Promise<Task>;
|
|
388
650
|
}
|
|
651
|
+
/**
|
|
652
|
+
* A handle to a video job created via `videos.generate`.
|
|
653
|
+
* Polls the video-tasks endpoint until the job reaches a terminal status.
|
|
654
|
+
*/
|
|
655
|
+
declare class VideoTaskHandle {
|
|
656
|
+
private readonly transport;
|
|
657
|
+
readonly taskId: string;
|
|
658
|
+
constructor(transport: Transport, taskId: string);
|
|
659
|
+
/** Fetch the current job snapshot (single request). */
|
|
660
|
+
get(signal?: AbortSignal): Promise<VideoTask>;
|
|
661
|
+
/** Alias of `get()` — perform one poll and return the latest snapshot. */
|
|
662
|
+
poll(signal?: AbortSignal): Promise<VideoTask>;
|
|
663
|
+
/** Poll until the job reaches a terminal status (completed/failed/cancelled). */
|
|
664
|
+
wait(opts?: VideoWaitOptions): Promise<VideoTask>;
|
|
665
|
+
}
|
|
389
666
|
|
|
390
667
|
declare const DEFAULT_BASE_URL = "https://app.quantonlabs.com";
|
|
391
668
|
interface QLClientOptions {
|
|
@@ -402,6 +679,18 @@ declare class WorkspaceApi {
|
|
|
402
679
|
constructor(t: Transport);
|
|
403
680
|
/** GET /api/v1/workspace */
|
|
404
681
|
get(): Promise<Workspace>;
|
|
682
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
683
|
+
getModels(): Promise<WorkspaceModelsResult>;
|
|
684
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
685
|
+
update(input: WorkspaceUpdateInput): Promise<Workspace>;
|
|
686
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
687
|
+
updateModels(input: WorkspaceModelsUpdateInput): Promise<Workspace>;
|
|
688
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
689
|
+
listCatalogModels(): Promise<CatalogResult>;
|
|
690
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
691
|
+
verifyOpenRouterKey(key: string, model?: string, baseUrl?: string): Promise<VerifyKeyResult>;
|
|
692
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
693
|
+
listKeys(): Promise<KeysResult>;
|
|
405
694
|
}
|
|
406
695
|
/** Agents namespace. */
|
|
407
696
|
declare class AgentsApi {
|
|
@@ -458,6 +747,37 @@ declare class ImagesApi {
|
|
|
458
747
|
/** POST /api/v1/agents/:agentId/images — generate image(s) via a tiered model. */
|
|
459
748
|
generate(agentId: string, input: ImageGenerateInput): Promise<ImageGenerateResult>;
|
|
460
749
|
}
|
|
750
|
+
/** Videos namespace (tiered video generation: submit → poll). */
|
|
751
|
+
declare class VideosApi {
|
|
752
|
+
private readonly t;
|
|
753
|
+
constructor(t: Transport);
|
|
754
|
+
/** GET /api/v1/videos/models — list tiered video models + engine availability. */
|
|
755
|
+
listModels(): Promise<VideoModelsResult>;
|
|
756
|
+
/** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */
|
|
757
|
+
generate(agentId: string, input: VideoGenerateInput): Promise<VideoTaskCreated>;
|
|
758
|
+
/** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */
|
|
759
|
+
getTask(taskId: string, signal?: AbortSignal): Promise<VideoTask>;
|
|
760
|
+
/** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */
|
|
761
|
+
cancelTask(taskId: string): Promise<VideoTask>;
|
|
762
|
+
/** Get a handle for polling / waiting on a video job (poll(), wait()). */
|
|
763
|
+
handle(taskId: string): VideoTaskHandle;
|
|
764
|
+
}
|
|
765
|
+
/** Audio namespace (text-to-speech). */
|
|
766
|
+
declare class AudioApi {
|
|
767
|
+
private readonly t;
|
|
768
|
+
constructor(t: Transport);
|
|
769
|
+
/** GET /api/v1/audio/voices — list available TTS voices. */
|
|
770
|
+
voices(): Promise<VoicesResult>;
|
|
771
|
+
/** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */
|
|
772
|
+
textToSpeech(agentId: string, input: TtsInput): Promise<TtsResult>;
|
|
773
|
+
}
|
|
774
|
+
/** Files namespace (media uploads). */
|
|
775
|
+
declare class FilesApi {
|
|
776
|
+
private readonly t;
|
|
777
|
+
constructor(t: Transport);
|
|
778
|
+
/** POST /api/v1/files — upload a media file (multipart field "file"). */
|
|
779
|
+
upload(file: Blob, opts?: FileUploadOptions): Promise<UploadedFile>;
|
|
780
|
+
}
|
|
461
781
|
/**
|
|
462
782
|
* The public client. Example:
|
|
463
783
|
* const ql = new QLClient({ apiKey: process.env.QL_API_KEY });
|
|
@@ -469,6 +789,9 @@ declare class QLClient {
|
|
|
469
789
|
readonly workflows: WorkflowsApi;
|
|
470
790
|
readonly tasks: TasksApi;
|
|
471
791
|
readonly images: ImagesApi;
|
|
792
|
+
readonly videos: VideosApi;
|
|
793
|
+
readonly audio: AudioApi;
|
|
794
|
+
readonly files: FilesApi;
|
|
472
795
|
private readonly transport;
|
|
473
796
|
private readonly base;
|
|
474
797
|
constructor(opts: QLClientOptions);
|
|
@@ -512,4 +835,4 @@ declare class QLError extends Error {
|
|
|
512
835
|
get isNetworkError(): boolean;
|
|
513
836
|
}
|
|
514
837
|
|
|
515
|
-
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 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 WaitOptions, type WorkflowRun, type WorkflowRunInput, type WorkflowRunStart, type WorkflowRunStatus, WorkflowsApi, type Workspace, WorkspaceApi, isTerminalTaskStatus };
|
|
838
|
+
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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) {
|
|
@@ -351,6 +398,30 @@ var WorkspaceApi = class {
|
|
|
351
398
|
get() {
|
|
352
399
|
return this.t.json("GET", "/api/v1/workspace");
|
|
353
400
|
}
|
|
401
|
+
/** GET /api/v1/workspace/models — current model config (OpenRouter key masked). */
|
|
402
|
+
getModels() {
|
|
403
|
+
return this.t.json("GET", "/api/v1/workspace/models");
|
|
404
|
+
}
|
|
405
|
+
/** PATCH /api/v1/workspace — update the workspace name and/or OpenRouter model config (partial). */
|
|
406
|
+
update(input) {
|
|
407
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: input });
|
|
408
|
+
}
|
|
409
|
+
/** PATCH /api/v1/workspace — convenience wrapper that only touches `config.openrouter`. */
|
|
410
|
+
updateModels(input) {
|
|
411
|
+
return this.t.json("PATCH", "/api/v1/workspace", { body: { config: { openrouter: input } } });
|
|
412
|
+
}
|
|
413
|
+
/** GET /api/v1/workspace/models/catalog — OpenRouter model catalog (server-side cached). */
|
|
414
|
+
listCatalogModels() {
|
|
415
|
+
return this.t.json("GET", "/api/v1/workspace/models/catalog");
|
|
416
|
+
}
|
|
417
|
+
/** POST /api/v1/workspace/models/verify — check an OpenRouter key with a 1-token completion. */
|
|
418
|
+
verifyOpenRouterKey(key, model, baseUrl) {
|
|
419
|
+
return this.t.json("POST", "/api/v1/workspace/models/verify", { body: { key, model, baseUrl } });
|
|
420
|
+
}
|
|
421
|
+
/** GET /api/v1/workspace/keys — API keys with rotation metadata (rotatesAt, daysLeft). */
|
|
422
|
+
listKeys() {
|
|
423
|
+
return this.t.json("GET", "/api/v1/workspace/keys");
|
|
424
|
+
}
|
|
354
425
|
};
|
|
355
426
|
var AgentsApi = class {
|
|
356
427
|
constructor(t) {
|
|
@@ -454,6 +525,62 @@ var ImagesApi = class {
|
|
|
454
525
|
return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/images`, { body: input });
|
|
455
526
|
}
|
|
456
527
|
};
|
|
528
|
+
var VideosApi = class {
|
|
529
|
+
constructor(t) {
|
|
530
|
+
this.t = t;
|
|
531
|
+
}
|
|
532
|
+
/** GET /api/v1/videos/models — list tiered video models + engine availability. */
|
|
533
|
+
listModels() {
|
|
534
|
+
return this.t.json("GET", "/api/v1/videos/models");
|
|
535
|
+
}
|
|
536
|
+
/** POST /api/v1/agents/:agentId/videos — start a video job (returns the queued task, HTTP 202). */
|
|
537
|
+
generate(agentId, input) {
|
|
538
|
+
return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/videos`, { body: input });
|
|
539
|
+
}
|
|
540
|
+
/** GET /api/v1/video-tasks/:taskId — fetch the current job snapshot. */
|
|
541
|
+
getTask(taskId, signal) {
|
|
542
|
+
return this.t.json("GET", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`, { signal });
|
|
543
|
+
}
|
|
544
|
+
/** DELETE /api/v1/video-tasks/:taskId — cancel a queued/rendering job (409 if already terminal). */
|
|
545
|
+
cancelTask(taskId) {
|
|
546
|
+
return this.t.json("DELETE", `/api/v1/video-tasks/${encodeURIComponent(taskId)}`);
|
|
547
|
+
}
|
|
548
|
+
/** Get a handle for polling / waiting on a video job (poll(), wait()). */
|
|
549
|
+
handle(taskId) {
|
|
550
|
+
return new VideoTaskHandle(this.t, taskId);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
var AudioApi = class {
|
|
554
|
+
constructor(t) {
|
|
555
|
+
this.t = t;
|
|
556
|
+
}
|
|
557
|
+
/** GET /api/v1/audio/voices — list available TTS voices. */
|
|
558
|
+
voices() {
|
|
559
|
+
return this.t.json("GET", "/api/v1/audio/voices");
|
|
560
|
+
}
|
|
561
|
+
/** POST /api/v1/agents/:agentId/tts — synthesize speech (synchronous). */
|
|
562
|
+
textToSpeech(agentId, input) {
|
|
563
|
+
return this.t.json("POST", `/api/v1/agents/${encodeURIComponent(agentId)}/tts`, { body: input });
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
var FilesApi = class {
|
|
567
|
+
constructor(t) {
|
|
568
|
+
this.t = t;
|
|
569
|
+
}
|
|
570
|
+
/** POST /api/v1/files — upload a media file (multipart field "file"). */
|
|
571
|
+
async upload(file, opts = {}) {
|
|
572
|
+
const form = new FormData();
|
|
573
|
+
if (opts.filename !== void 0) {
|
|
574
|
+
form.append("file", file, opts.filename);
|
|
575
|
+
} else {
|
|
576
|
+
form.append("file", file);
|
|
577
|
+
}
|
|
578
|
+
opts.onProgress?.(0);
|
|
579
|
+
const result = await this.t.form("/api/v1/files", { form });
|
|
580
|
+
opts.onProgress?.(100);
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
};
|
|
457
584
|
function readEnvBaseUrl() {
|
|
458
585
|
try {
|
|
459
586
|
if (typeof process !== "undefined" && process?.env) {
|
|
@@ -476,6 +603,9 @@ var QLClient = class {
|
|
|
476
603
|
this.workflows = new WorkflowsApi(this.transport);
|
|
477
604
|
this.tasks = new TasksApi(this.transport);
|
|
478
605
|
this.images = new ImagesApi(this.transport);
|
|
606
|
+
this.videos = new VideosApi(this.transport);
|
|
607
|
+
this.audio = new AudioApi(this.transport);
|
|
608
|
+
this.files = new FilesApi(this.transport);
|
|
479
609
|
}
|
|
480
610
|
/** The normalized base URL in use (not secret). */
|
|
481
611
|
get baseUrl() {
|
|
@@ -495,12 +625,16 @@ var API_ERROR_CODES = {
|
|
|
495
625
|
export {
|
|
496
626
|
API_ERROR_CODES,
|
|
497
627
|
AgentsApi,
|
|
628
|
+
AudioApi,
|
|
498
629
|
DEFAULT_BASE_URL,
|
|
630
|
+
FilesApi,
|
|
499
631
|
ImagesApi,
|
|
500
632
|
QLClient,
|
|
501
633
|
QLError,
|
|
502
634
|
TaskHandle,
|
|
503
635
|
TasksApi,
|
|
636
|
+
VideoTaskHandle,
|
|
637
|
+
VideosApi,
|
|
504
638
|
WorkflowsApi,
|
|
505
639
|
WorkspaceApi,
|
|
506
640
|
isTerminalTaskStatus
|