@curvet/sdk 0.1.0 → 0.2.1
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 +53 -1
- package/dist/index.cjs +188 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -24
- package/dist/index.d.ts +159 -24
- package/dist/index.js +180 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -125,8 +125,12 @@ var HttpClient = class {
|
|
|
125
125
|
};
|
|
126
126
|
let payload;
|
|
127
127
|
if (body !== void 0) {
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
if (typeof FormData !== "undefined" && body instanceof FormData) {
|
|
129
|
+
payload = body;
|
|
130
|
+
} else {
|
|
131
|
+
headers["content-type"] = "application/json";
|
|
132
|
+
payload = JSON.stringify(body);
|
|
133
|
+
}
|
|
130
134
|
}
|
|
131
135
|
let attempt = 0;
|
|
132
136
|
for (; ; ) {
|
|
@@ -360,20 +364,17 @@ var Job = class {
|
|
|
360
364
|
}
|
|
361
365
|
};
|
|
362
366
|
|
|
363
|
-
// src/resources/
|
|
364
|
-
var
|
|
365
|
-
constructor(client, defaults, path
|
|
367
|
+
// src/resources/media.ts
|
|
368
|
+
var MediaResource = class {
|
|
369
|
+
constructor(client, defaults, path) {
|
|
366
370
|
this.client = client;
|
|
367
371
|
this.defaults = defaults;
|
|
368
372
|
this.path = path;
|
|
369
373
|
}
|
|
370
374
|
/**
|
|
371
|
-
* Submit
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* The media POST long-polls server-side and can block well past a normal
|
|
375
|
-
* request timeout, so we default its timeout to the poll budget and disable
|
|
376
|
-
* auto-retry (a retried POST would enqueue a duplicate, double-charged job).
|
|
375
|
+
* Submit WITHOUT polling. The media POST long-polls server-side and can block
|
|
376
|
+
* well past a normal request timeout, so we default its timeout to the poll
|
|
377
|
+
* budget and disable auto-retry (a retried POST would enqueue a duplicate job).
|
|
377
378
|
*/
|
|
378
379
|
async submit(params, options) {
|
|
379
380
|
const reqOptions = {
|
|
@@ -389,10 +390,7 @@ var Video = class {
|
|
|
389
390
|
});
|
|
390
391
|
return normalizeMediaPost(body);
|
|
391
392
|
}
|
|
392
|
-
/**
|
|
393
|
-
* Submit and resolve to the finished media. Handles the 200-vs-202 split and
|
|
394
|
-
* polls `/jobs/:id` internally. Throws JobFailedError / JobTimeoutError.
|
|
395
|
-
*/
|
|
393
|
+
/** Submit and resolve to the finished media (auto-polls /jobs/:id). */
|
|
396
394
|
async generate(params, options) {
|
|
397
395
|
const submitted = await this.submit(params, options);
|
|
398
396
|
if (submitted.status === "completed" || submitted.status === "failed") {
|
|
@@ -413,6 +411,27 @@ var Video = class {
|
|
|
413
411
|
}
|
|
414
412
|
};
|
|
415
413
|
|
|
414
|
+
// src/resources/video.ts
|
|
415
|
+
var Video = class extends MediaResource {
|
|
416
|
+
constructor(client, defaults) {
|
|
417
|
+
super(client, defaults, "/video");
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/resources/audio.ts
|
|
422
|
+
var Audio = class extends MediaResource {
|
|
423
|
+
constructor(client, defaults) {
|
|
424
|
+
super(client, defaults, "/audio");
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// src/resources/threeD.ts
|
|
429
|
+
var ThreeD = class extends MediaResource {
|
|
430
|
+
constructor(client, defaults) {
|
|
431
|
+
super(client, defaults, "/3d");
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
|
|
416
435
|
// src/resources/models.ts
|
|
417
436
|
var Models = class {
|
|
418
437
|
constructor(client, cacheTtlMs = 6e4) {
|
|
@@ -465,6 +484,132 @@ var Balance = class {
|
|
|
465
484
|
}
|
|
466
485
|
};
|
|
467
486
|
|
|
487
|
+
// src/resources/analytics.ts
|
|
488
|
+
var Analytics = class {
|
|
489
|
+
constructor(client) {
|
|
490
|
+
this.client = client;
|
|
491
|
+
}
|
|
492
|
+
/** Usage analytics for the app, optionally bounded by a date range. */
|
|
493
|
+
async get(params = {}) {
|
|
494
|
+
const { startDate, endDate, ...options } = params;
|
|
495
|
+
const body = await this.client.request({
|
|
496
|
+
method: "GET",
|
|
497
|
+
path: "/analytics",
|
|
498
|
+
query: { startDate, endDate },
|
|
499
|
+
options
|
|
500
|
+
});
|
|
501
|
+
return body.analytics;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/resources/workflows.ts
|
|
506
|
+
var Workflows = class {
|
|
507
|
+
constructor(client) {
|
|
508
|
+
this.client = client;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Execute a visual-builder workflow by id. Sends JSON when there are no file
|
|
512
|
+
* inputs, multipart/form-data when files are provided. Not auto-retried (a
|
|
513
|
+
* workflow run executes and may consume credits).
|
|
514
|
+
*/
|
|
515
|
+
async run(id, params = {}, options) {
|
|
516
|
+
const reqOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };
|
|
517
|
+
const hasFiles = params.files && Object.keys(params.files).length > 0;
|
|
518
|
+
let body;
|
|
519
|
+
if (hasFiles) {
|
|
520
|
+
const form = new FormData();
|
|
521
|
+
form.append("inputs", JSON.stringify(params.inputs ?? {}));
|
|
522
|
+
if (params.includeFullState !== void 0) {
|
|
523
|
+
form.append("includeFullState", String(params.includeFullState));
|
|
524
|
+
}
|
|
525
|
+
for (const [field, file] of Object.entries(params.files)) {
|
|
526
|
+
form.append(field, file);
|
|
527
|
+
}
|
|
528
|
+
body = form;
|
|
529
|
+
} else {
|
|
530
|
+
body = { inputs: params.inputs ?? {}, includeFullState: params.includeFullState };
|
|
531
|
+
}
|
|
532
|
+
return this.client.request({
|
|
533
|
+
method: "POST",
|
|
534
|
+
path: `/workflows/${encodeURIComponent(id)}/run`,
|
|
535
|
+
body,
|
|
536
|
+
options: reqOptions
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
// src/resources/food.ts
|
|
542
|
+
var Food = class {
|
|
543
|
+
constructor(client) {
|
|
544
|
+
this.client = client;
|
|
545
|
+
}
|
|
546
|
+
/** List dishes (default limit 20). */
|
|
547
|
+
async list(opts) {
|
|
548
|
+
const { limit, ...options } = opts ?? {};
|
|
549
|
+
const body = await this.client.request({
|
|
550
|
+
method: "GET",
|
|
551
|
+
path: "/food",
|
|
552
|
+
query: { limit },
|
|
553
|
+
options
|
|
554
|
+
});
|
|
555
|
+
return body.data;
|
|
556
|
+
}
|
|
557
|
+
/** Full-text search for dishes. */
|
|
558
|
+
async search(query, opts) {
|
|
559
|
+
const { limit, ...options } = opts ?? {};
|
|
560
|
+
const body = await this.client.request({
|
|
561
|
+
method: "GET",
|
|
562
|
+
path: "/food/search",
|
|
563
|
+
query: { q: query, limit },
|
|
564
|
+
options
|
|
565
|
+
});
|
|
566
|
+
return body.data;
|
|
567
|
+
}
|
|
568
|
+
/** Natural-language dish recommendations. */
|
|
569
|
+
async recommendations(prompt, options) {
|
|
570
|
+
const body = await this.client.request({
|
|
571
|
+
method: "POST",
|
|
572
|
+
path: "/food/recommendations",
|
|
573
|
+
body: { prompt },
|
|
574
|
+
options
|
|
575
|
+
});
|
|
576
|
+
return body.data;
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
// src/resources/voice.ts
|
|
581
|
+
var Voice = class {
|
|
582
|
+
constructor(client) {
|
|
583
|
+
this.client = client;
|
|
584
|
+
}
|
|
585
|
+
async stt(params, options) {
|
|
586
|
+
const form = new FormData();
|
|
587
|
+
form.append("audio", toBlob(params.audio), params.filename ?? "audio");
|
|
588
|
+
if (params.provider) form.append("provider", params.provider);
|
|
589
|
+
if (params.model) form.append("model", params.model);
|
|
590
|
+
if (params.prompt) form.append("prompt", params.prompt);
|
|
591
|
+
if (params.languageCode) form.append("languageCode", params.languageCode);
|
|
592
|
+
if (params.allowFallback !== void 0) {
|
|
593
|
+
form.append("allowFallback", String(params.allowFallback));
|
|
594
|
+
}
|
|
595
|
+
const reqOptions = {
|
|
596
|
+
...options,
|
|
597
|
+
timeout: options?.timeout ?? 12e4,
|
|
598
|
+
maxRetries: options?.maxRetries ?? 0
|
|
599
|
+
};
|
|
600
|
+
return this.client.request({
|
|
601
|
+
method: "POST",
|
|
602
|
+
path: "/voice/stt/public",
|
|
603
|
+
body: form,
|
|
604
|
+
options: reqOptions
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
function toBlob(audio) {
|
|
609
|
+
if (typeof Blob !== "undefined" && audio instanceof Blob) return audio;
|
|
610
|
+
return new Blob([audio]);
|
|
611
|
+
}
|
|
612
|
+
|
|
468
613
|
// src/client.ts
|
|
469
614
|
var DEFAULT_BASE_URL = "https://curvet.ai/api/v1/playground";
|
|
470
615
|
var Curvet = class {
|
|
@@ -481,13 +626,16 @@ var Curvet = class {
|
|
|
481
626
|
"No fetch implementation available. Use Node 18+ or pass { fetch }."
|
|
482
627
|
);
|
|
483
628
|
}
|
|
484
|
-
const
|
|
629
|
+
const playgroundBase = options.baseURL ?? DEFAULT_BASE_URL;
|
|
630
|
+
const v1Base = playgroundBase.replace(/\/playground\/?$/, "");
|
|
631
|
+
const shared = {
|
|
485
632
|
appKey,
|
|
486
|
-
baseURL: options.baseURL ?? DEFAULT_BASE_URL,
|
|
487
633
|
timeout: options.timeout ?? 6e4,
|
|
488
634
|
maxRetries: options.maxRetries ?? 2,
|
|
489
635
|
fetch: fetchImpl
|
|
490
|
-
}
|
|
636
|
+
};
|
|
637
|
+
const client = new HttpClient({ ...shared, baseURL: playgroundBase });
|
|
638
|
+
const v1Client = new HttpClient({ ...shared, baseURL: v1Base });
|
|
491
639
|
const jobDefaults = {
|
|
492
640
|
pollIntervalMs: options.defaultPollIntervalMs ?? 2500,
|
|
493
641
|
pollTimeoutMs: options.defaultPollTimeoutMs ?? 18e4
|
|
@@ -496,8 +644,14 @@ var Curvet = class {
|
|
|
496
644
|
this.image = new Images(client);
|
|
497
645
|
this.jobs = new Jobs(client, jobDefaults);
|
|
498
646
|
this.video = new Video(client, jobDefaults);
|
|
647
|
+
this.audio = new Audio(client, jobDefaults);
|
|
648
|
+
this.threeD = new ThreeD(client, jobDefaults);
|
|
499
649
|
this.models = new Models(client);
|
|
500
650
|
this.balance = new Balance(client);
|
|
651
|
+
this.analytics = new Analytics(client);
|
|
652
|
+
this.workflows = new Workflows(client);
|
|
653
|
+
this.food = new Food(v1Client);
|
|
654
|
+
this.voice = new Voice(v1Client);
|
|
501
655
|
}
|
|
502
656
|
};
|
|
503
657
|
function envKey() {
|
|
@@ -509,6 +663,8 @@ function defaultFetch() {
|
|
|
509
663
|
}
|
|
510
664
|
export {
|
|
511
665
|
APIError,
|
|
666
|
+
Analytics,
|
|
667
|
+
Audio,
|
|
512
668
|
AuthError,
|
|
513
669
|
BadRequestError,
|
|
514
670
|
Balance,
|
|
@@ -517,16 +673,21 @@ export {
|
|
|
517
673
|
Curvet,
|
|
518
674
|
CurvetError,
|
|
519
675
|
DEFAULT_BASE_URL,
|
|
676
|
+
Food,
|
|
520
677
|
Images,
|
|
521
678
|
InsufficientBalanceError,
|
|
522
679
|
Job,
|
|
523
680
|
JobFailedError,
|
|
524
681
|
JobTimeoutError,
|
|
525
682
|
Jobs,
|
|
683
|
+
MediaResource,
|
|
526
684
|
Models,
|
|
527
685
|
NotFoundError,
|
|
528
686
|
PermissionError,
|
|
529
687
|
RateLimitError,
|
|
530
|
-
|
|
688
|
+
ThreeD,
|
|
689
|
+
Video,
|
|
690
|
+
Voice,
|
|
691
|
+
Workflows
|
|
531
692
|
};
|
|
532
693
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/errors.ts","../src/core/retry.ts","../src/core/http.ts","../src/resources/chat.ts","../src/resources/image.ts","../src/core/normalize.ts","../src/core/poll.ts","../src/resources/jobs.ts","../src/resources/video.ts","../src/resources/models.ts","../src/resources/balance.ts","../src/client.ts"],"sourcesContent":["export interface CurvetErrorOptions {\n status?: number;\n requestId?: string;\n raw?: unknown;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class CurvetError extends Error {\n readonly status?: number;\n readonly requestId?: string;\n readonly raw?: unknown;\n\n constructor(message: string, opts: CurvetErrorOptions = {}) {\n super(message);\n this.name = new.target.name;\n this.status = opts.status;\n this.requestId = opts.requestId;\n this.raw = opts.raw;\n // Restore prototype chain so `instanceof` works after transpilation.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401 — missing or invalid `x-app-key`. */\nexport class AuthError extends CurvetError {}\n/** 403 — app not active, playground not enabled, or model/category not allowed. */\nexport class PermissionError extends CurvetError {}\n/** 400 — invalid/unknown model or malformed payload. */\nexport class BadRequestError extends CurvetError {}\n/** 404 — job or workflow not found. */\nexport class NotFoundError extends CurvetError {}\n/** 5xx — upstream/server error (retried automatically). */\nexport class APIError extends CurvetError {}\n/** Network failure or timeout before a response was received. */\nexport class ConnectionError extends CurvetError {}\n\n/** 402 — not enough credits to complete the request. */\nexport class InsufficientBalanceError extends CurvetError {\n required?: number;\n available?: number;\n}\n\n/** 429 — hourly request limit or daily cost cap exceeded. */\nexport class RateLimitError extends CurvetError {\n kind?: \"rate\" | \"cost\";\n limit?: number;\n used?: number;\n resetsAt?: Date;\n retryAfterMs?: number;\n}\n\n/** An async media job finished with status \"failed\". */\nexport class JobFailedError extends CurvetError {\n readonly jobId: string;\n constructor(message: string, jobId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.jobId = jobId;\n }\n}\n\n/** An async media job did not finish within the poll timeout. */\nexport class JobTimeoutError extends CurvetError {\n readonly jobId: string;\n constructor(message: string, jobId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.jobId = jobId;\n }\n}\n\ninterface HeaderBag {\n get(name: string): string | null;\n}\n\n/** Map an HTTP status + JSON error body to the right typed error. */\nexport function errorFromResponse(\n status: number,\n body: unknown,\n requestId?: string,\n headers?: HeaderBag,\n): CurvetError {\n const b = (body ?? {}) as Record<string, any>;\n const message =\n typeof b.error === \"string\" ? b.error : `HTTP ${status}`;\n const base: CurvetErrorOptions = { status, requestId, raw: body };\n\n switch (status) {\n case 400:\n return new BadRequestError(message, base);\n case 401:\n return new AuthError(message, base);\n case 402: {\n const e = new InsufficientBalanceError(message, base);\n e.required = b.required;\n e.available = b.available;\n return e;\n }\n case 403:\n return new PermissionError(message, base);\n case 404:\n return new NotFoundError(message, base);\n case 429: {\n const e = new RateLimitError(message, base);\n const info = b.rateLimitInfo ?? b.costCapInfo;\n e.kind = b.costCapInfo ? \"cost\" : \"rate\";\n if (info) {\n e.limit = info.limit;\n e.used = info.used;\n if (info.resetsAt) e.resetsAt = new Date(info.resetsAt);\n }\n const retryAfter = headers?.get?.(\"retry-after\");\n if (info?.resetsIn != null) e.retryAfterMs = Number(info.resetsIn) * 1000;\n else if (retryAfter) e.retryAfterMs = Number(retryAfter) * 1000;\n else if (e.resetsAt) e.retryAfterMs = Math.max(0, e.resetsAt.getTime() - Date.now());\n return e;\n }\n default:\n return new APIError(message, base);\n }\n}\n","/** Exponential backoff with full jitter. */\nexport function fullJitterBackoff(attempt: number, baseMs = 500, capMs = 8000): number {\n const exp = Math.min(capMs, baseMs * 2 ** attempt);\n return Math.random() * exp;\n}\n\n/** Sleep that rejects with an AbortError if the signal fires. */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(abortError());\n const onAbort = () => {\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport function abortError(): Error {\n const e = new Error(\"The operation was aborted.\");\n e.name = \"AbortError\";\n return e;\n}\n\n/** Only 429 and 5xx are safe to retry. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || status >= 500;\n}\n","import type { FetchLike, RequestOptions } from \"../types/common\";\nimport {\n CurvetError,\n ConnectionError,\n RateLimitError,\n errorFromResponse,\n} from \"./errors\";\nimport { fullJitterBackoff, isRetryableStatus, sleep } from \"./retry\";\n\nexport interface HttpClientOptions {\n appKey: string;\n baseURL: string;\n timeout: number;\n maxRetries: number;\n fetch: FetchLike;\n}\n\nexport interface RequestArgs {\n method: string;\n path: string;\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n options?: RequestOptions;\n}\n\n/**\n * The single place that knows about fetch, headers, base URL, error mapping,\n * and retries. Resources call `request()`; everything else stays mockable.\n */\nexport class HttpClient {\n constructor(private opts: HttpClientOptions) {}\n\n async request<T = any>(args: RequestArgs): Promise<T> {\n const { method, path, body, query, options } = args;\n const url = this.buildUrl(path, query);\n const maxRetries = options?.maxRetries ?? this.opts.maxRetries;\n const timeout = options?.timeout ?? this.opts.timeout;\n\n const headers: Record<string, string> = {\n \"x-app-key\": this.opts.appKey,\n accept: \"application/json\",\n ...(options?.headers ?? {}),\n };\n let payload: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n\n let attempt = 0;\n for (;;) {\n const { signal, done } = this.makeSignal(timeout, options?.signal);\n try {\n const res = await this.opts.fetch(url, { method, headers, body: payload, signal });\n const text = await res.text();\n const parsed = text ? safeJson(text) : undefined;\n\n if (res.ok) return parsed as T;\n\n const requestId =\n res.headers.get(\"x-request-id\") ??\n (parsed as any)?.metadata?.requestId ??\n undefined;\n const err = errorFromResponse(res.status, parsed, requestId, res.headers);\n\n if (isRetryableStatus(res.status) && attempt < maxRetries) {\n await this.backoff(err, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw err;\n } catch (e: any) {\n if (e instanceof CurvetError) throw e;\n // AbortError: distinguish user-abort (rethrow) from our timeout (retry/ConnectionError).\n if (e?.name === \"AbortError\") {\n if (options?.signal?.aborted) throw e;\n if (attempt < maxRetries) {\n await this.backoff(undefined, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw new ConnectionError(\"Request timed out\", { raw: e });\n }\n // Network error before any response — safe to retry.\n if (attempt < maxRetries) {\n await this.backoff(undefined, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw new ConnectionError(e?.message ?? \"Network request failed\", { raw: e });\n } finally {\n done();\n }\n }\n }\n\n private async backoff(err: CurvetError | undefined, attempt: number, signal?: AbortSignal) {\n let delay = fullJitterBackoff(attempt);\n if (err instanceof RateLimitError && err.retryAfterMs != null) {\n delay = Math.min(err.retryAfterMs, 30000);\n }\n await sleep(delay, signal);\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>) {\n const base = this.opts.baseURL.replace(/\\/$/, \"\");\n let url = base + (path.startsWith(\"/\") ? path : \"/\" + path);\n if (query) {\n const qs = Object.entries(query)\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join(\"&\");\n if (qs) url += \"?\" + qs;\n }\n return url;\n }\n\n /** Combine a per-request timeout with an optional user AbortSignal. */\n private makeSignal(timeout: number, userSignal?: AbortSignal) {\n const controller = new AbortController();\n const onUserAbort = () => controller.abort();\n if (userSignal) {\n if (userSignal.aborted) controller.abort();\n else userSignal.addEventListener(\"abort\", onUserAbort, { once: true });\n }\n const timer = setTimeout(() => controller.abort(), timeout);\n return {\n signal: controller.signal,\n done: () => {\n clearTimeout(timer);\n userSignal?.removeEventListener(\"abort\", onUserAbort);\n },\n };\n }\n}\n\nfunction safeJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ChatCreateParams, ChatResponse } from \"../types/chat\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport class Chat {\n constructor(private client: HttpClient) {}\n\n /** Create a chat completion. Synchronous — resolves with the model's reply. */\n create(params: ChatCreateParams, options?: RequestOptions): Promise<ChatResponse> {\n return this.client.request<ChatResponse>({\n method: \"POST\",\n path: \"/chat\",\n body: params,\n options,\n });\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ImageGenerateParams, ImageResponse } from \"../types/image\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport class Images {\n constructor(private client: HttpClient) {}\n\n /** Generate an image from a prompt. Synchronous — resolves with `imageUrl`. */\n generate(params: ImageGenerateParams, options?: RequestOptions): Promise<ImageResponse> {\n return this.client.request<ImageResponse>({\n method: \"POST\",\n path: \"/image\",\n body: params,\n options,\n });\n }\n}\n","import type { MediaJob, JobStatus } from \"../types/job\";\n\n/**\n * The API returns the output URL under three different keys depending on the\n * endpoint: `videoUrl` (/video), `audioUrl` (/audio), `modelUrl` (/3d), and\n * `output.mediaUrl` (GET /jobs/:id). Unify them.\n */\nfunction pickMediaUrl(body: Record<string, any>): string | undefined {\n return (\n body?.videoUrl ??\n body?.audioUrl ??\n body?.modelUrl ??\n body?.output?.mediaUrl ??\n body?.mediaUrl ??\n undefined\n );\n}\n\n/**\n * Normalize a POST /video|/audio|/3d response, which is EITHER a 200 with the\n * final media URL (job already done) OR a 202 with just a `jobId` to poll.\n */\nexport function normalizeMediaPost(body: unknown): MediaJob {\n const b = (body ?? {}) as Record<string, any>;\n const mediaUrl = pickMediaUrl(b);\n const jobId = b.jobId ?? b.metadata?.jobId;\n const status: JobStatus = mediaUrl\n ? \"completed\"\n : b.status === \"failed\"\n ? \"failed\"\n : \"processing\";\n return {\n jobId,\n status,\n mediaUrl,\n usage: b.usage,\n metadata: b.metadata,\n error: b.error ?? null,\n raw: body,\n };\n}\n\n/** Normalize a GET /jobs/:id response. */\nexport function normalizeJob(body: unknown): MediaJob {\n const b = (body ?? {}) as Record<string, any>;\n const mediaUrl = pickMediaUrl(b);\n const status: JobStatus = (b.status as JobStatus) ?? (mediaUrl ? \"completed\" : \"processing\");\n return {\n jobId: b.jobId,\n status,\n progress: b.progress,\n mediaUrl,\n metadata: b.output?.metadata ?? b.metadata,\n error: b.error ?? null,\n cost: b.cost,\n eta: b.eta,\n raw: body,\n };\n}\n","import { sleep } from \"./retry\";\n\n/** Thrown internally when a poll loop exceeds its timeout. */\nexport class PollTimeoutError extends Error {\n constructor(message = \"Polling timed out\") {\n super(message);\n this.name = \"PollTimeoutError\";\n }\n}\n\nexport interface PollConfig<T> {\n isTerminal: (result: T) => boolean;\n intervalMs: number;\n timeoutMs: number;\n signal?: AbortSignal;\n onTick?: (result: T) => void;\n}\n\n/**\n * Repeatedly call `fn` until `isTerminal` is true (resolves the result) or the\n * timeout elapses (throws PollTimeoutError). Polls immediately, then every\n * `intervalMs`. Honors an AbortSignal between ticks.\n */\nexport async function pollUntil<T>(fn: () => Promise<T>, cfg: PollConfig<T>): Promise<T> {\n const start = Date.now();\n for (;;) {\n const result = await fn();\n cfg.onTick?.(result);\n if (cfg.isTerminal(result)) return result;\n const elapsed = Date.now() - start;\n if (elapsed >= cfg.timeoutMs) throw new PollTimeoutError();\n const remaining = cfg.timeoutMs - elapsed;\n await sleep(Math.min(cfg.intervalMs, Math.max(0, remaining)), cfg.signal);\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { MediaJob, PollOptions } from \"../types/job\";\nimport type { RequestOptions } from \"../types/common\";\nimport { normalizeJob } from \"../core/normalize\";\nimport { pollUntil, PollTimeoutError } from \"../core/poll\";\nimport { JobFailedError, JobTimeoutError } from \"../core/errors\";\n\nexport interface JobDefaults {\n pollIntervalMs: number;\n pollTimeoutMs: number;\n}\n\nexport class Jobs {\n constructor(\n private client: HttpClient,\n private defaults: JobDefaults,\n ) {}\n\n /** Fetch the current status of an async job once (no polling). */\n async retrieve(jobId: string, options?: RequestOptions): Promise<MediaJob> {\n const body = await this.client.request({\n method: \"GET\",\n path: `/jobs/${encodeURIComponent(jobId)}`,\n options,\n });\n return normalizeJob(body);\n }\n\n /** Get a {@link Job} handle to poll/await an existing job by id. */\n handle(jobId: string): Job {\n return new Job(jobId, this.client, this.defaults);\n }\n}\n\n/** A handle to a single async media job. */\nexport class Job {\n constructor(\n readonly id: string,\n private client: HttpClient,\n private defaults: JobDefaults,\n ) {}\n\n /** One status fetch (no polling). */\n retrieve(options?: RequestOptions): Promise<MediaJob> {\n return new Jobs(this.client, this.defaults).retrieve(this.id, options);\n }\n\n /**\n * Poll until the job reaches a terminal state.\n * Resolves with the completed job, or throws JobFailedError / JobTimeoutError.\n */\n async wait(opts: PollOptions = {}): Promise<MediaJob> {\n const intervalMs = opts.pollIntervalMs ?? this.defaults.pollIntervalMs;\n const timeoutMs = opts.pollTimeoutMs ?? this.defaults.pollTimeoutMs;\n\n let result: MediaJob;\n try {\n result = await pollUntil(() => this.retrieve({ signal: opts.signal }), {\n intervalMs,\n timeoutMs,\n signal: opts.signal,\n isTerminal: (r) => r.status === \"completed\" || r.status === \"failed\",\n onTick: (r) => opts.onProgress?.(r.progress ?? 0, r.eta),\n });\n } catch (e) {\n if (e instanceof PollTimeoutError) {\n throw new JobTimeoutError(\n `Job ${this.id} did not complete within ${timeoutMs}ms`,\n this.id,\n );\n }\n throw e;\n }\n\n if (result.status === \"failed\") {\n throw new JobFailedError(result.error || `Job ${this.id} failed`, this.id, {\n raw: result.raw,\n });\n }\n return result;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { MediaJob, VideoGenerateParams, PollOptions } from \"../types/job\";\nimport type { RequestOptions } from \"../types/common\";\nimport { normalizeMediaPost } from \"../core/normalize\";\nimport { Job, type JobDefaults } from \"./jobs\";\nimport { CurvetError } from \"../core/errors\";\n\n/**\n * Video generation. Backed by an async job queue: `generate()` submits and\n * polls to completion (the common case); `submit()` fires and returns the job\n * handle for manual polling.\n *\n * The same implementation backs audio and 3D (v1.1) via the `path` arg.\n */\nexport class Video {\n constructor(\n private client: HttpClient,\n private defaults: JobDefaults,\n private path: string = \"/video\",\n ) {}\n\n /**\n * Submit a job WITHOUT polling. Returns once the server responds — either the\n * 200 fast-path (already done) or a 202 with a jobId.\n *\n * The media POST long-polls server-side and can block well past a normal\n * request timeout, so we default its timeout to the poll budget and disable\n * auto-retry (a retried POST would enqueue a duplicate, double-charged job).\n */\n async submit(params: VideoGenerateParams, options?: RequestOptions): Promise<MediaJob> {\n const reqOptions: RequestOptions = {\n ...options,\n timeout: options?.timeout ?? this.defaults.pollTimeoutMs,\n maxRetries: options?.maxRetries ?? 0,\n };\n const body = await this.client.request({\n method: \"POST\",\n path: this.path,\n body: params,\n options: reqOptions,\n });\n return normalizeMediaPost(body);\n }\n\n /**\n * Submit and resolve to the finished media. Handles the 200-vs-202 split and\n * polls `/jobs/:id` internally. Throws JobFailedError / JobTimeoutError.\n */\n async generate(\n params: VideoGenerateParams,\n options?: RequestOptions & PollOptions,\n ): Promise<MediaJob> {\n const submitted = await this.submit(params, options);\n if (submitted.status === \"completed\" || submitted.status === \"failed\") {\n return submitted;\n }\n if (!submitted.jobId) {\n throw new CurvetError(\"Async job did not return a jobId to poll\", {\n raw: submitted.raw,\n });\n }\n const job = new Job(submitted.jobId, this.client, this.defaults);\n return job.wait({\n pollIntervalMs: options?.pollIntervalMs,\n pollTimeoutMs: options?.pollTimeoutMs,\n signal: options?.signal,\n onProgress: options?.onProgress,\n });\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ModelInfo, RateLimits } from \"../types/models\";\nimport type { RequestOptions } from \"../types/common\";\n\ninterface ModelsListResponse {\n success: boolean;\n models: ModelInfo[];\n rateLimits: RateLimits;\n}\n\nexport interface ModelsListOptions extends RequestOptions {\n /** Filter to a single model type (e.g. \"chat\", \"image\", \"video\"). */\n type?: string;\n /** Bypass the in-memory cache and fetch fresh. */\n refresh?: boolean;\n}\n\n/**\n * Live model catalog. The list is dynamic and per-app filtered server-side, so\n * it is always fetched (with a short in-memory cache), never hardcoded.\n */\nexport class Models {\n private cache?: { at: number; data: ModelsListResponse };\n\n constructor(\n private client: HttpClient,\n private cacheTtlMs = 60_000,\n ) {}\n\n private async load(options?: RequestOptions): Promise<ModelsListResponse> {\n return this.client.request<ModelsListResponse>({\n method: \"GET\",\n path: \"/models\",\n options,\n });\n }\n\n private async ensure(options?: ModelsListOptions): Promise<ModelsListResponse> {\n const stale = !this.cache || Date.now() - this.cache.at > this.cacheTtlMs;\n if (options?.refresh || stale) {\n this.cache = { at: Date.now(), data: await this.load(options) };\n }\n return this.cache!.data;\n }\n\n /** List available models, optionally filtered by `type`. */\n async list(options?: ModelsListOptions): Promise<ModelInfo[]> {\n const data = await this.ensure(options);\n const models = data.models ?? [];\n return options?.type ? models.filter((m) => m.type === options.type) : models;\n }\n\n /** Find a single model by id (or undefined). */\n async get(id: string, options?: ModelsListOptions): Promise<ModelInfo | undefined> {\n return (await this.list(options)).find((m) => m.id === id);\n }\n\n /** The app's rate limits as reported by GET /models. */\n async rateLimits(options?: ModelsListOptions): Promise<RateLimits | undefined> {\n return (await this.ensure(options)).rateLimits;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface BalanceInfo {\n walletBalance?: number;\n totalAvailableUSD: number;\n totalPoints?: number;\n breakdown?: {\n walletCredits?: number;\n totalCredits?: number;\n organizationLimit?: number;\n monthlyUsed?: number;\n isEnterprise?: boolean;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport class Balance {\n constructor(private client: HttpClient) {}\n\n /** Get the current credit balance for the app owner. */\n async get(options?: RequestOptions): Promise<BalanceInfo> {\n const body = await this.client.request<{ success: boolean; balance: BalanceInfo }>({\n method: \"GET\",\n path: \"/balance\",\n options,\n });\n return body.balance;\n }\n}\n","import { HttpClient } from \"./core/http\";\nimport { CurvetError } from \"./core/errors\";\nimport type { FetchLike } from \"./types/common\";\nimport { Chat } from \"./resources/chat\";\nimport { Images } from \"./resources/image\";\nimport { Video } from \"./resources/video\";\nimport { Jobs } from \"./resources/jobs\";\nimport { Models } from \"./resources/models\";\nimport { Balance } from \"./resources/balance\";\n\nexport const DEFAULT_BASE_URL = \"https://curvet.ai/api/v1/playground\";\n\nexport interface CurvetOptions {\n /** Your app key. Falls back to the CURVET_APP_KEY env var. */\n appKey?: string;\n /** Override the gateway base URL (defaults to production). */\n baseURL?: string;\n /** Per-request timeout in ms (default 60000). */\n timeout?: number;\n /** Max automatic retries for 429/5xx and network errors (default 2). */\n maxRetries?: number;\n /** Inject a fetch implementation (defaults to global fetch on Node 18+). */\n fetch?: FetchLike;\n /** Default poll interval for async media jobs, in ms (default 2500). */\n defaultPollIntervalMs?: number;\n /** Default poll timeout for async media jobs, in ms (default 180000). */\n defaultPollTimeoutMs?: number;\n}\n\n/**\n * The Curvet client. One instance per app key.\n *\n * ```ts\n * const curvet = new Curvet({ appKey: process.env.CURVET_APP_KEY });\n * const { response } = await curvet.chat.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hi\" }],\n * });\n * ```\n */\nexport class Curvet {\n readonly chat: Chat;\n readonly image: Images;\n readonly video: Video;\n readonly jobs: Jobs;\n readonly models: Models;\n readonly balance: Balance;\n\n constructor(options: CurvetOptions = {}) {\n const appKey = options.appKey ?? envKey();\n if (!appKey) {\n throw new CurvetError(\n \"Missing Curvet app key. Pass { appKey } or set the CURVET_APP_KEY environment variable.\",\n );\n }\n const fetchImpl = options.fetch ?? defaultFetch();\n if (!fetchImpl) {\n throw new CurvetError(\n \"No fetch implementation available. Use Node 18+ or pass { fetch }.\",\n );\n }\n\n const client = new HttpClient({\n appKey,\n baseURL: options.baseURL ?? DEFAULT_BASE_URL,\n timeout: options.timeout ?? 60_000,\n maxRetries: options.maxRetries ?? 2,\n fetch: fetchImpl,\n });\n\n const jobDefaults = {\n pollIntervalMs: options.defaultPollIntervalMs ?? 2500,\n pollTimeoutMs: options.defaultPollTimeoutMs ?? 180_000,\n };\n\n this.chat = new Chat(client);\n this.image = new Images(client);\n this.jobs = new Jobs(client, jobDefaults);\n this.video = new Video(client, jobDefaults);\n this.models = new Models(client);\n this.balance = new Balance(client);\n }\n}\n\nfunction envKey(): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.CURVET_APP_KEY : undefined;\n}\n\nfunction defaultFetch(): FetchLike | undefined {\n const f = (globalThis as { fetch?: unknown }).fetch;\n return typeof f === \"function\" ? (f.bind(globalThis) as FetchLike) : undefined;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts","../src/core/retry.ts","../src/core/http.ts","../src/resources/chat.ts","../src/resources/image.ts","../src/core/normalize.ts","../src/core/poll.ts","../src/resources/jobs.ts","../src/resources/media.ts","../src/resources/video.ts","../src/resources/audio.ts","../src/resources/threeD.ts","../src/resources/models.ts","../src/resources/balance.ts","../src/resources/analytics.ts","../src/resources/workflows.ts","../src/resources/food.ts","../src/resources/voice.ts","../src/client.ts"],"sourcesContent":["export interface CurvetErrorOptions {\n status?: number;\n requestId?: string;\n raw?: unknown;\n}\n\n/** Base class for every error thrown by the SDK. */\nexport class CurvetError extends Error {\n readonly status?: number;\n readonly requestId?: string;\n readonly raw?: unknown;\n\n constructor(message: string, opts: CurvetErrorOptions = {}) {\n super(message);\n this.name = new.target.name;\n this.status = opts.status;\n this.requestId = opts.requestId;\n this.raw = opts.raw;\n // Restore prototype chain so `instanceof` works after transpilation.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** 401 — missing or invalid `x-app-key`. */\nexport class AuthError extends CurvetError {}\n/** 403 — app not active, playground not enabled, or model/category not allowed. */\nexport class PermissionError extends CurvetError {}\n/** 400 — invalid/unknown model or malformed payload. */\nexport class BadRequestError extends CurvetError {}\n/** 404 — job or workflow not found. */\nexport class NotFoundError extends CurvetError {}\n/** 5xx — upstream/server error (retried automatically). */\nexport class APIError extends CurvetError {}\n/** Network failure or timeout before a response was received. */\nexport class ConnectionError extends CurvetError {}\n\n/** 402 — not enough credits to complete the request. */\nexport class InsufficientBalanceError extends CurvetError {\n required?: number;\n available?: number;\n}\n\n/** 429 — hourly request limit or daily cost cap exceeded. */\nexport class RateLimitError extends CurvetError {\n kind?: \"rate\" | \"cost\";\n limit?: number;\n used?: number;\n resetsAt?: Date;\n retryAfterMs?: number;\n}\n\n/** An async media job finished with status \"failed\". */\nexport class JobFailedError extends CurvetError {\n readonly jobId: string;\n constructor(message: string, jobId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.jobId = jobId;\n }\n}\n\n/** An async media job did not finish within the poll timeout. */\nexport class JobTimeoutError extends CurvetError {\n readonly jobId: string;\n constructor(message: string, jobId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.jobId = jobId;\n }\n}\n\ninterface HeaderBag {\n get(name: string): string | null;\n}\n\n/** Map an HTTP status + JSON error body to the right typed error. */\nexport function errorFromResponse(\n status: number,\n body: unknown,\n requestId?: string,\n headers?: HeaderBag,\n): CurvetError {\n const b = (body ?? {}) as Record<string, any>;\n const message =\n typeof b.error === \"string\" ? b.error : `HTTP ${status}`;\n const base: CurvetErrorOptions = { status, requestId, raw: body };\n\n switch (status) {\n case 400:\n return new BadRequestError(message, base);\n case 401:\n return new AuthError(message, base);\n case 402: {\n const e = new InsufficientBalanceError(message, base);\n e.required = b.required;\n e.available = b.available;\n return e;\n }\n case 403:\n return new PermissionError(message, base);\n case 404:\n return new NotFoundError(message, base);\n case 429: {\n const e = new RateLimitError(message, base);\n const info = b.rateLimitInfo ?? b.costCapInfo;\n e.kind = b.costCapInfo ? \"cost\" : \"rate\";\n if (info) {\n e.limit = info.limit;\n e.used = info.used;\n if (info.resetsAt) e.resetsAt = new Date(info.resetsAt);\n }\n const retryAfter = headers?.get?.(\"retry-after\");\n if (info?.resetsIn != null) e.retryAfterMs = Number(info.resetsIn) * 1000;\n else if (retryAfter) e.retryAfterMs = Number(retryAfter) * 1000;\n else if (e.resetsAt) e.retryAfterMs = Math.max(0, e.resetsAt.getTime() - Date.now());\n return e;\n }\n default:\n return new APIError(message, base);\n }\n}\n","/** Exponential backoff with full jitter. */\nexport function fullJitterBackoff(attempt: number, baseMs = 500, capMs = 8000): number {\n const exp = Math.min(capMs, baseMs * 2 ** attempt);\n return Math.random() * exp;\n}\n\n/** Sleep that rejects with an AbortError if the signal fires. */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(abortError());\n const onAbort = () => {\n cleanup();\n reject(abortError());\n };\n const cleanup = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nexport function abortError(): Error {\n const e = new Error(\"The operation was aborted.\");\n e.name = \"AbortError\";\n return e;\n}\n\n/** Only 429 and 5xx are safe to retry. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 429 || status >= 500;\n}\n","import type { FetchLike, RequestOptions } from \"../types/common\";\nimport {\n CurvetError,\n ConnectionError,\n RateLimitError,\n errorFromResponse,\n} from \"./errors\";\nimport { fullJitterBackoff, isRetryableStatus, sleep } from \"./retry\";\n\nexport interface HttpClientOptions {\n appKey: string;\n baseURL: string;\n timeout: number;\n maxRetries: number;\n fetch: FetchLike;\n}\n\nexport interface RequestArgs {\n method: string;\n path: string;\n body?: unknown;\n query?: Record<string, string | number | undefined>;\n options?: RequestOptions;\n}\n\n/**\n * The single place that knows about fetch, headers, base URL, error mapping,\n * and retries. Resources call `request()`; everything else stays mockable.\n */\nexport class HttpClient {\n constructor(private opts: HttpClientOptions) {}\n\n async request<T = any>(args: RequestArgs): Promise<T> {\n const { method, path, body, query, options } = args;\n const url = this.buildUrl(path, query);\n const maxRetries = options?.maxRetries ?? this.opts.maxRetries;\n const timeout = options?.timeout ?? this.opts.timeout;\n\n const headers: Record<string, string> = {\n \"x-app-key\": this.opts.appKey,\n accept: \"application/json\",\n ...(options?.headers ?? {}),\n };\n let payload: string | FormData | undefined;\n if (body !== undefined) {\n if (typeof FormData !== \"undefined\" && body instanceof FormData) {\n // Multipart — let fetch set the content-type (with boundary).\n payload = body;\n } else {\n headers[\"content-type\"] = \"application/json\";\n payload = JSON.stringify(body);\n }\n }\n\n let attempt = 0;\n for (;;) {\n const { signal, done } = this.makeSignal(timeout, options?.signal);\n try {\n const res = await this.opts.fetch(url, { method, headers, body: payload, signal });\n const text = await res.text();\n const parsed = text ? safeJson(text) : undefined;\n\n if (res.ok) return parsed as T;\n\n const requestId =\n res.headers.get(\"x-request-id\") ??\n (parsed as any)?.metadata?.requestId ??\n undefined;\n const err = errorFromResponse(res.status, parsed, requestId, res.headers);\n\n if (isRetryableStatus(res.status) && attempt < maxRetries) {\n await this.backoff(err, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw err;\n } catch (e: any) {\n if (e instanceof CurvetError) throw e;\n // AbortError: distinguish user-abort (rethrow) from our timeout (retry/ConnectionError).\n if (e?.name === \"AbortError\") {\n if (options?.signal?.aborted) throw e;\n if (attempt < maxRetries) {\n await this.backoff(undefined, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw new ConnectionError(\"Request timed out\", { raw: e });\n }\n // Network error before any response — safe to retry.\n if (attempt < maxRetries) {\n await this.backoff(undefined, attempt, options?.signal);\n attempt++;\n continue;\n }\n throw new ConnectionError(e?.message ?? \"Network request failed\", { raw: e });\n } finally {\n done();\n }\n }\n }\n\n private async backoff(err: CurvetError | undefined, attempt: number, signal?: AbortSignal) {\n let delay = fullJitterBackoff(attempt);\n if (err instanceof RateLimitError && err.retryAfterMs != null) {\n delay = Math.min(err.retryAfterMs, 30000);\n }\n await sleep(delay, signal);\n }\n\n private buildUrl(path: string, query?: Record<string, string | number | undefined>) {\n const base = this.opts.baseURL.replace(/\\/$/, \"\");\n let url = base + (path.startsWith(\"/\") ? path : \"/\" + path);\n if (query) {\n const qs = Object.entries(query)\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join(\"&\");\n if (qs) url += \"?\" + qs;\n }\n return url;\n }\n\n /** Combine a per-request timeout with an optional user AbortSignal. */\n private makeSignal(timeout: number, userSignal?: AbortSignal) {\n const controller = new AbortController();\n const onUserAbort = () => controller.abort();\n if (userSignal) {\n if (userSignal.aborted) controller.abort();\n else userSignal.addEventListener(\"abort\", onUserAbort, { once: true });\n }\n const timer = setTimeout(() => controller.abort(), timeout);\n return {\n signal: controller.signal,\n done: () => {\n clearTimeout(timer);\n userSignal?.removeEventListener(\"abort\", onUserAbort);\n },\n };\n }\n}\n\nfunction safeJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ChatCreateParams, ChatResponse } from \"../types/chat\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport class Chat {\n constructor(private client: HttpClient) {}\n\n /** Create a chat completion. Synchronous — resolves with the model's reply. */\n create(params: ChatCreateParams, options?: RequestOptions): Promise<ChatResponse> {\n return this.client.request<ChatResponse>({\n method: \"POST\",\n path: \"/chat\",\n body: params,\n options,\n });\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ImageGenerateParams, ImageResponse } from \"../types/image\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport class Images {\n constructor(private client: HttpClient) {}\n\n /** Generate an image from a prompt. Synchronous — resolves with `imageUrl`. */\n generate(params: ImageGenerateParams, options?: RequestOptions): Promise<ImageResponse> {\n return this.client.request<ImageResponse>({\n method: \"POST\",\n path: \"/image\",\n body: params,\n options,\n });\n }\n}\n","import type { MediaJob, JobStatus } from \"../types/job\";\n\n/**\n * The API returns the output URL under three different keys depending on the\n * endpoint: `videoUrl` (/video), `audioUrl` (/audio), `modelUrl` (/3d), and\n * `output.mediaUrl` (GET /jobs/:id). Unify them.\n */\nfunction pickMediaUrl(body: Record<string, any>): string | undefined {\n return (\n body?.videoUrl ??\n body?.audioUrl ??\n body?.modelUrl ??\n body?.output?.mediaUrl ??\n body?.mediaUrl ??\n undefined\n );\n}\n\n/**\n * Normalize a POST /video|/audio|/3d response, which is EITHER a 200 with the\n * final media URL (job already done) OR a 202 with just a `jobId` to poll.\n */\nexport function normalizeMediaPost(body: unknown): MediaJob {\n const b = (body ?? {}) as Record<string, any>;\n const mediaUrl = pickMediaUrl(b);\n const jobId = b.jobId ?? b.metadata?.jobId;\n const status: JobStatus = mediaUrl\n ? \"completed\"\n : b.status === \"failed\"\n ? \"failed\"\n : \"processing\";\n return {\n jobId,\n status,\n mediaUrl,\n usage: b.usage,\n metadata: b.metadata,\n error: b.error ?? null,\n raw: body,\n };\n}\n\n/** Normalize a GET /jobs/:id response. */\nexport function normalizeJob(body: unknown): MediaJob {\n const b = (body ?? {}) as Record<string, any>;\n const mediaUrl = pickMediaUrl(b);\n const status: JobStatus = (b.status as JobStatus) ?? (mediaUrl ? \"completed\" : \"processing\");\n return {\n jobId: b.jobId,\n status,\n progress: b.progress,\n mediaUrl,\n metadata: b.output?.metadata ?? b.metadata,\n error: b.error ?? null,\n cost: b.cost,\n eta: b.eta,\n raw: body,\n };\n}\n","import { sleep } from \"./retry\";\n\n/** Thrown internally when a poll loop exceeds its timeout. */\nexport class PollTimeoutError extends Error {\n constructor(message = \"Polling timed out\") {\n super(message);\n this.name = \"PollTimeoutError\";\n }\n}\n\nexport interface PollConfig<T> {\n isTerminal: (result: T) => boolean;\n intervalMs: number;\n timeoutMs: number;\n signal?: AbortSignal;\n onTick?: (result: T) => void;\n}\n\n/**\n * Repeatedly call `fn` until `isTerminal` is true (resolves the result) or the\n * timeout elapses (throws PollTimeoutError). Polls immediately, then every\n * `intervalMs`. Honors an AbortSignal between ticks.\n */\nexport async function pollUntil<T>(fn: () => Promise<T>, cfg: PollConfig<T>): Promise<T> {\n const start = Date.now();\n for (;;) {\n const result = await fn();\n cfg.onTick?.(result);\n if (cfg.isTerminal(result)) return result;\n const elapsed = Date.now() - start;\n if (elapsed >= cfg.timeoutMs) throw new PollTimeoutError();\n const remaining = cfg.timeoutMs - elapsed;\n await sleep(Math.min(cfg.intervalMs, Math.max(0, remaining)), cfg.signal);\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { MediaJob, PollOptions } from \"../types/job\";\nimport type { RequestOptions } from \"../types/common\";\nimport { normalizeJob } from \"../core/normalize\";\nimport { pollUntil, PollTimeoutError } from \"../core/poll\";\nimport { JobFailedError, JobTimeoutError } from \"../core/errors\";\n\nexport interface JobDefaults {\n pollIntervalMs: number;\n pollTimeoutMs: number;\n}\n\nexport class Jobs {\n constructor(\n private client: HttpClient,\n private defaults: JobDefaults,\n ) {}\n\n /** Fetch the current status of an async job once (no polling). */\n async retrieve(jobId: string, options?: RequestOptions): Promise<MediaJob> {\n const body = await this.client.request({\n method: \"GET\",\n path: `/jobs/${encodeURIComponent(jobId)}`,\n options,\n });\n return normalizeJob(body);\n }\n\n /** Get a {@link Job} handle to poll/await an existing job by id. */\n handle(jobId: string): Job {\n return new Job(jobId, this.client, this.defaults);\n }\n}\n\n/** A handle to a single async media job. */\nexport class Job {\n constructor(\n readonly id: string,\n private client: HttpClient,\n private defaults: JobDefaults,\n ) {}\n\n /** One status fetch (no polling). */\n retrieve(options?: RequestOptions): Promise<MediaJob> {\n return new Jobs(this.client, this.defaults).retrieve(this.id, options);\n }\n\n /**\n * Poll until the job reaches a terminal state.\n * Resolves with the completed job, or throws JobFailedError / JobTimeoutError.\n */\n async wait(opts: PollOptions = {}): Promise<MediaJob> {\n const intervalMs = opts.pollIntervalMs ?? this.defaults.pollIntervalMs;\n const timeoutMs = opts.pollTimeoutMs ?? this.defaults.pollTimeoutMs;\n\n let result: MediaJob;\n try {\n result = await pollUntil(() => this.retrieve({ signal: opts.signal }), {\n intervalMs,\n timeoutMs,\n signal: opts.signal,\n isTerminal: (r) => r.status === \"completed\" || r.status === \"failed\",\n onTick: (r) => opts.onProgress?.(r.progress ?? 0, r.eta),\n });\n } catch (e) {\n if (e instanceof PollTimeoutError) {\n throw new JobTimeoutError(\n `Job ${this.id} did not complete within ${timeoutMs}ms`,\n this.id,\n );\n }\n throw e;\n }\n\n if (result.status === \"failed\") {\n throw new JobFailedError(result.error || `Job ${this.id} failed`, this.id, {\n raw: result.raw,\n });\n }\n return result;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { MediaJob, PollOptions } from \"../types/job\";\nimport type { RequestOptions } from \"../types/common\";\nimport { normalizeMediaPost } from \"../core/normalize\";\nimport { Job, type JobDefaults } from \"./jobs\";\nimport { CurvetError } from \"../core/errors\";\n\nexport interface MediaParamsBase {\n model: string;\n prompt: string;\n [key: string]: unknown;\n}\n\n/**\n * Generic engine for the async media endpoints (video / audio / 3d). They all\n * enqueue the same server-side job queue, so they share one implementation\n * parameterized by `path` and request param type.\n *\n * `generate()` submits and polls to completion; `submit()` fires without polling.\n */\nexport class MediaResource<P extends MediaParamsBase> {\n constructor(\n protected client: HttpClient,\n protected defaults: JobDefaults,\n protected path: string,\n ) {}\n\n /**\n * Submit WITHOUT polling. The media POST long-polls server-side and can block\n * well past a normal request timeout, so we default its timeout to the poll\n * budget and disable auto-retry (a retried POST would enqueue a duplicate job).\n */\n async submit(params: P, options?: RequestOptions): Promise<MediaJob> {\n const reqOptions: RequestOptions = {\n ...options,\n timeout: options?.timeout ?? this.defaults.pollTimeoutMs,\n maxRetries: options?.maxRetries ?? 0,\n };\n const body = await this.client.request({\n method: \"POST\",\n path: this.path,\n body: params,\n options: reqOptions,\n });\n return normalizeMediaPost(body);\n }\n\n /** Submit and resolve to the finished media (auto-polls /jobs/:id). */\n async generate(params: P, options?: RequestOptions & PollOptions): Promise<MediaJob> {\n const submitted = await this.submit(params, options);\n if (submitted.status === \"completed\" || submitted.status === \"failed\") {\n return submitted;\n }\n if (!submitted.jobId) {\n throw new CurvetError(\"Async job did not return a jobId to poll\", {\n raw: submitted.raw,\n });\n }\n const job = new Job(submitted.jobId, this.client, this.defaults);\n return job.wait({\n pollIntervalMs: options?.pollIntervalMs,\n pollTimeoutMs: options?.pollTimeoutMs,\n signal: options?.signal,\n onProgress: options?.onProgress,\n });\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { JobDefaults } from \"./jobs\";\nimport type { VideoGenerateParams } from \"../types/job\";\nimport { MediaResource } from \"./media\";\n\n/** Video generation (async). `curvet.video.generate(...)` auto-polls to completion. */\nexport class Video extends MediaResource<VideoGenerateParams> {\n constructor(client: HttpClient, defaults: JobDefaults) {\n super(client, defaults, \"/video\");\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { JobDefaults } from \"./jobs\";\nimport type { AudioGenerateParams } from \"../types/job\";\nimport { MediaResource } from \"./media\";\n\n/** Audio generation (async). `curvet.audio.generate(...)` auto-polls to completion. */\nexport class Audio extends MediaResource<AudioGenerateParams> {\n constructor(client: HttpClient, defaults: JobDefaults) {\n super(client, defaults, \"/audio\");\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { JobDefaults } from \"./jobs\";\nimport type { ThreeDGenerateParams } from \"../types/job\";\nimport { MediaResource } from \"./media\";\n\n/** 3D model generation (async). `curvet.threeD.generate(...)` auto-polls to completion. */\nexport class ThreeD extends MediaResource<ThreeDGenerateParams> {\n constructor(client: HttpClient, defaults: JobDefaults) {\n super(client, defaults, \"/3d\");\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { ModelInfo, RateLimits } from \"../types/models\";\nimport type { RequestOptions } from \"../types/common\";\n\ninterface ModelsListResponse {\n success: boolean;\n models: ModelInfo[];\n rateLimits: RateLimits;\n}\n\nexport interface ModelsListOptions extends RequestOptions {\n /** Filter to a single model type (e.g. \"chat\", \"image\", \"video\"). */\n type?: string;\n /** Bypass the in-memory cache and fetch fresh. */\n refresh?: boolean;\n}\n\n/**\n * Live model catalog. The list is dynamic and per-app filtered server-side, so\n * it is always fetched (with a short in-memory cache), never hardcoded.\n */\nexport class Models {\n private cache?: { at: number; data: ModelsListResponse };\n\n constructor(\n private client: HttpClient,\n private cacheTtlMs = 60_000,\n ) {}\n\n private async load(options?: RequestOptions): Promise<ModelsListResponse> {\n return this.client.request<ModelsListResponse>({\n method: \"GET\",\n path: \"/models\",\n options,\n });\n }\n\n private async ensure(options?: ModelsListOptions): Promise<ModelsListResponse> {\n const stale = !this.cache || Date.now() - this.cache.at > this.cacheTtlMs;\n if (options?.refresh || stale) {\n this.cache = { at: Date.now(), data: await this.load(options) };\n }\n return this.cache!.data;\n }\n\n /** List available models, optionally filtered by `type`. */\n async list(options?: ModelsListOptions): Promise<ModelInfo[]> {\n const data = await this.ensure(options);\n const models = data.models ?? [];\n return options?.type ? models.filter((m) => m.type === options.type) : models;\n }\n\n /** Find a single model by id (or undefined). */\n async get(id: string, options?: ModelsListOptions): Promise<ModelInfo | undefined> {\n return (await this.list(options)).find((m) => m.id === id);\n }\n\n /** The app's rate limits as reported by GET /models. */\n async rateLimits(options?: ModelsListOptions): Promise<RateLimits | undefined> {\n return (await this.ensure(options)).rateLimits;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface BalanceInfo {\n walletBalance?: number;\n totalAvailableUSD: number;\n totalPoints?: number;\n breakdown?: {\n walletCredits?: number;\n totalCredits?: number;\n organizationLimit?: number;\n monthlyUsed?: number;\n isEnterprise?: boolean;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport class Balance {\n constructor(private client: HttpClient) {}\n\n /** Get the current credit balance for the app owner. */\n async get(options?: RequestOptions): Promise<BalanceInfo> {\n const body = await this.client.request<{ success: boolean; balance: BalanceInfo }>({\n method: \"GET\",\n path: \"/balance\",\n options,\n });\n return body.balance;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface AnalyticsParams extends RequestOptions {\n /** ISO 8601 start date. */\n startDate?: string;\n /** ISO 8601 end date. */\n endDate?: string;\n}\n\nexport interface AnalyticsResult {\n totalRequests?: number;\n totalCost?: number;\n requestsByModel?: Record<string, number>;\n requestsByCategory?: Record<string, number>;\n [key: string]: unknown;\n}\n\nexport class Analytics {\n constructor(private client: HttpClient) {}\n\n /** Usage analytics for the app, optionally bounded by a date range. */\n async get(params: AnalyticsParams = {}): Promise<AnalyticsResult> {\n const { startDate, endDate, ...options } = params;\n const body = await this.client.request<{ success: boolean; analytics: AnalyticsResult }>({\n method: \"GET\",\n path: \"/analytics\",\n query: { startDate, endDate },\n options,\n });\n return body.analytics;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface WorkflowRunParams {\n /** Input values for the workflow. */\n inputs?: Record<string, unknown>;\n /** Optional file inputs, keyed by the workflow's file field name. */\n files?: Record<string, Blob>;\n /** Include the full execution state in the response (default true server-side). */\n includeFullState?: boolean;\n}\n\nexport interface WorkflowRunResult {\n success: boolean;\n [key: string]: unknown;\n}\n\nexport class Workflows {\n constructor(private client: HttpClient) {}\n\n /**\n * Execute a visual-builder workflow by id. Sends JSON when there are no file\n * inputs, multipart/form-data when files are provided. Not auto-retried (a\n * workflow run executes and may consume credits).\n */\n async run(\n id: string,\n params: WorkflowRunParams = {},\n options?: RequestOptions,\n ): Promise<WorkflowRunResult> {\n const reqOptions: RequestOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };\n const hasFiles = params.files && Object.keys(params.files).length > 0;\n\n let body: unknown;\n if (hasFiles) {\n const form = new FormData();\n form.append(\"inputs\", JSON.stringify(params.inputs ?? {}));\n if (params.includeFullState !== undefined) {\n form.append(\"includeFullState\", String(params.includeFullState));\n }\n for (const [field, file] of Object.entries(params.files!)) {\n form.append(field, file);\n }\n body = form;\n } else {\n body = { inputs: params.inputs ?? {}, includeFullState: params.includeFullState };\n }\n\n return this.client.request<WorkflowRunResult>({\n method: \"POST\",\n path: `/workflows/${encodeURIComponent(id)}/run`,\n body,\n options: reqOptions,\n });\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface FoodItem {\n [key: string]: unknown;\n}\n\n/**\n * Indian Food Dataset API. Mounted as a sibling of the playground under\n * `/api/v1/food`, so it uses the v1-root HTTP client. Requires the app to have\n * Food API access enabled.\n */\nexport class Food {\n constructor(private client: HttpClient) {}\n\n /** List dishes (default limit 20). */\n async list(opts?: { limit?: number } & RequestOptions): Promise<FoodItem[]> {\n const { limit, ...options } = opts ?? {};\n const body = await this.client.request<{ success: boolean; data: FoodItem[]; count: number }>({\n method: \"GET\",\n path: \"/food\",\n query: { limit },\n options,\n });\n return body.data;\n }\n\n /** Full-text search for dishes. */\n async search(query: string, opts?: { limit?: number } & RequestOptions): Promise<FoodItem[]> {\n const { limit, ...options } = opts ?? {};\n const body = await this.client.request<{ success: boolean; data: FoodItem[] }>({\n method: \"GET\",\n path: \"/food/search\",\n query: { q: query, limit },\n options,\n });\n return body.data;\n }\n\n /** Natural-language dish recommendations. */\n async recommendations(prompt: string, options?: RequestOptions): Promise<FoodItem[]> {\n const body = await this.client.request<{ success: boolean; data: FoodItem[] }>({\n method: \"POST\",\n path: \"/food/recommendations\",\n body: { prompt },\n options,\n });\n return body.data;\n }\n}\n","import type { HttpClient } from \"../core/http\";\nimport type { RequestOptions } from \"../types/common\";\n\nexport interface SttParams {\n /** The audio to transcribe. */\n audio: Blob | Uint8Array | ArrayBuffer;\n /** File name for the upload (default \"audio\"). */\n filename?: string;\n provider?: \"elevenlabs\" | \"deepinfra\" | (string & {});\n /** ASR model id (provider-specific; optional). */\n model?: string;\n prompt?: string;\n /** ISO 639-1 language hint. */\n languageCode?: string;\n allowFallback?: boolean;\n}\n\nexport interface SttResult {\n success: boolean;\n text: string;\n languageCode?: string;\n segments?: Array<{ start: number; end: number; text: string }>;\n provider?: string;\n creditsCharged?: number;\n creditsRemaining?: number;\n [key: string]: unknown;\n}\n\n/**\n * Public speech-to-text. Mounted as a sibling of the playground under\n * `/api/v1/voice`, so it uses the v1-root HTTP client. Multipart upload; not\n * auto-retried (it consumes credits).\n */\nexport class Voice {\n constructor(private client: HttpClient) {}\n\n async stt(params: SttParams, options?: RequestOptions): Promise<SttResult> {\n const form = new FormData();\n form.append(\"audio\", toBlob(params.audio), params.filename ?? \"audio\");\n if (params.provider) form.append(\"provider\", params.provider);\n if (params.model) form.append(\"model\", params.model);\n if (params.prompt) form.append(\"prompt\", params.prompt);\n if (params.languageCode) form.append(\"languageCode\", params.languageCode);\n if (params.allowFallback !== undefined) {\n form.append(\"allowFallback\", String(params.allowFallback));\n }\n\n const reqOptions: RequestOptions = {\n ...options,\n timeout: options?.timeout ?? 120_000,\n maxRetries: options?.maxRetries ?? 0,\n };\n return this.client.request<SttResult>({\n method: \"POST\",\n path: \"/voice/stt/public\",\n body: form,\n options: reqOptions,\n });\n }\n}\n\nfunction toBlob(audio: Blob | Uint8Array | ArrayBuffer): Blob {\n if (typeof Blob !== \"undefined\" && audio instanceof Blob) return audio;\n return new Blob([audio] as ConstructorParameters<typeof Blob>[0]);\n}\n","import { HttpClient } from \"./core/http\";\nimport { CurvetError } from \"./core/errors\";\nimport type { FetchLike } from \"./types/common\";\nimport { Chat } from \"./resources/chat\";\nimport { Images } from \"./resources/image\";\nimport { Video } from \"./resources/video\";\nimport { Audio } from \"./resources/audio\";\nimport { ThreeD } from \"./resources/threeD\";\nimport { Jobs } from \"./resources/jobs\";\nimport { Models } from \"./resources/models\";\nimport { Balance } from \"./resources/balance\";\nimport { Analytics } from \"./resources/analytics\";\nimport { Workflows } from \"./resources/workflows\";\nimport { Food } from \"./resources/food\";\nimport { Voice } from \"./resources/voice\";\n\nexport const DEFAULT_BASE_URL = \"https://curvet.ai/api/v1/playground\";\n\nexport interface CurvetOptions {\n /** Your app key. Falls back to the CURVET_APP_KEY env var. */\n appKey?: string;\n /** Override the playground base URL (defaults to production). */\n baseURL?: string;\n /** Per-request timeout in ms (default 60000). */\n timeout?: number;\n /** Max automatic retries for 429/5xx and network errors (default 2). */\n maxRetries?: number;\n /** Inject a fetch implementation (defaults to global fetch on Node 18+). */\n fetch?: FetchLike;\n /** Default poll interval for async media jobs, in ms (default 2500). */\n defaultPollIntervalMs?: number;\n /** Default poll timeout for async media jobs, in ms (default 180000). */\n defaultPollTimeoutMs?: number;\n}\n\n/**\n * The Curvet client. One instance per app key.\n *\n * ```ts\n * const curvet = new Curvet({ appKey: process.env.CURVET_APP_KEY });\n * const { response } = await curvet.chat.create({\n * model: \"gpt-4o-mini\",\n * messages: [{ role: \"user\", content: \"hi\" }],\n * });\n * ```\n */\nexport class Curvet {\n readonly chat: Chat;\n readonly image: Images;\n readonly video: Video;\n readonly audio: Audio;\n readonly threeD: ThreeD;\n readonly jobs: Jobs;\n readonly models: Models;\n readonly balance: Balance;\n readonly analytics: Analytics;\n readonly workflows: Workflows;\n readonly food: Food;\n readonly voice: Voice;\n\n constructor(options: CurvetOptions = {}) {\n const appKey = options.appKey ?? envKey();\n if (!appKey) {\n throw new CurvetError(\n \"Missing Curvet app key. Pass { appKey } or set the CURVET_APP_KEY environment variable.\",\n );\n }\n const fetchImpl = options.fetch ?? defaultFetch();\n if (!fetchImpl) {\n throw new CurvetError(\n \"No fetch implementation available. Use Node 18+ or pass { fetch }.\",\n );\n }\n\n const playgroundBase = options.baseURL ?? DEFAULT_BASE_URL;\n // Sibling routes (food, voice) live one level up at /api/v1/*.\n const v1Base = playgroundBase.replace(/\\/playground\\/?$/, \"\");\n\n const shared = {\n appKey,\n timeout: options.timeout ?? 60_000,\n maxRetries: options.maxRetries ?? 2,\n fetch: fetchImpl,\n };\n const client = new HttpClient({ ...shared, baseURL: playgroundBase });\n const v1Client = new HttpClient({ ...shared, baseURL: v1Base });\n\n const jobDefaults = {\n pollIntervalMs: options.defaultPollIntervalMs ?? 2500,\n pollTimeoutMs: options.defaultPollTimeoutMs ?? 180_000,\n };\n\n this.chat = new Chat(client);\n this.image = new Images(client);\n this.jobs = new Jobs(client, jobDefaults);\n this.video = new Video(client, jobDefaults);\n this.audio = new Audio(client, jobDefaults);\n this.threeD = new ThreeD(client, jobDefaults);\n this.models = new Models(client);\n this.balance = new Balance(client);\n this.analytics = new Analytics(client);\n this.workflows = new Workflows(client);\n this.food = new Food(v1Client);\n this.voice = new Voice(v1Client);\n }\n}\n\nfunction envKey(): string | undefined {\n return typeof process !== \"undefined\" ? process.env?.CURVET_APP_KEY : undefined;\n}\n\nfunction defaultFetch(): FetchLike | undefined {\n const f = (globalThis as { fetch?: unknown }).fetch;\n return typeof f === \"function\" ? (f.bind(globalThis) as FetchLike) : undefined;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curvet/sdk",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Official TypeScript SDK for the Curvet Unified Playground API (chat, image, and video generation across providers, one API key).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Curvet <hello@curvet.in>",
|