@curvet/sdk 0.2.1 → 0.3.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/CHANGELOG.md ADDED
@@ -0,0 +1,45 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@curvet/sdk` are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.3.0] - 2026-06-27
9
+
10
+ ### Added
11
+ - **Pollable workflow runs** for long workflows (video/audio/3D nodes) — no more
12
+ one long-lived HTTP call:
13
+ - `workflows.submit(id, params)` — start a run, returns a `runId` immediately.
14
+ - `workflows.runs.retrieve(runId)` — live status: `currentNode`, `progress`,
15
+ per-node history, and the final `result`.
16
+ - `workflows.runAndPoll(id, params, { onProgress })` — submit + auto-poll to
17
+ completion (mirrors `video.generate`).
18
+ - `WorkflowRunFailedError` and `WorkflowRunTimeoutError` (both carry `runId`).
19
+ - `examples/pollable-workflow.ts`.
20
+
21
+ ### Notes
22
+ - `workflows.run()` (synchronous) is unchanged.
23
+ - Requires the matching backend (media-node execution + pollable run endpoints).
24
+
25
+ ## [0.2.1] - 2026-06-20
26
+
27
+ ### Added
28
+ - Additional resources: `audio.generate`/`submit`, `threeD.generate`/`submit`,
29
+ `analytics.get`, `workflows.run` (JSON or multipart file inputs), `food.*`
30
+ (list/search/recommendations), and `voice.stt`.
31
+ - `FormData` (multipart) support in the HTTP layer for file uploads.
32
+
33
+ ## [0.1.0] - 2026-06-19
34
+
35
+ ### Added
36
+ - Initial release. One typed client over the Curvet Playground API:
37
+ `chat.create`, `image.generate`, `video.generate`/`submit` with **async
38
+ auto-polling**, `jobs.retrieve`, `models.list`, `balance.get`.
39
+ - Typed error taxonomy (`AuthError`, `InsufficientBalanceError`, `RateLimitError`,
40
+ `JobFailedError`, …) and automatic retry/backoff on 429/5xx.
41
+ - Live model catalog (never hardcoded). Ships ESM + CJS + type declarations.
42
+
43
+ [0.3.0]: https://github.com/Curvet-in/curvet-sdk/releases/tag/v0.3.0
44
+ [0.2.1]: https://github.com/Curvet-in/curvet-sdk/releases/tag/v0.2.1
45
+ [0.1.0]: https://github.com/Curvet-in/curvet-sdk/releases/tag/v0.1.0
package/README.md CHANGED
@@ -112,6 +112,22 @@ await curvet.workflows.run("workflowId", {
112
112
  });
113
113
  ```
114
114
 
115
+ For long workflows (video/audio/3D nodes), use the **pollable** API — submit
116
+ and auto-poll to completion with live progress, instead of one long HTTP call:
117
+
118
+ ```ts
119
+ const run = await curvet.workflows.runAndPoll(
120
+ "workflowId",
121
+ { inputs: { topic: "ai" } },
122
+ { onProgress: (r) => console.log(r.status, r.progress + "%", r.currentNode?.label) },
123
+ );
124
+ console.log(run.result);
125
+
126
+ // Or fire-and-forget + poll yourself:
127
+ const { runId } = await curvet.workflows.submit("workflowId", { inputs: {} });
128
+ const status = await curvet.workflows.runs.retrieve(runId);
129
+ ```
130
+
115
131
  ### Food & speech-to-text
116
132
 
117
133
  ```ts
@@ -207,6 +223,10 @@ to finish.
207
223
  > at [`.github/workflows/publish.yml`](.github/workflows/publish.yml) for when
208
224
  > GitHub Actions is available.
209
225
 
226
+ ## Changelog
227
+
228
+ See [CHANGELOG.md](CHANGELOG.md) for release notes.
229
+
210
230
  ## License
211
231
 
212
232
  MIT
package/dist/index.cjs CHANGED
@@ -46,6 +46,9 @@ __export(index_exports, {
46
46
  ThreeD: () => ThreeD,
47
47
  Video: () => Video,
48
48
  Voice: () => Voice,
49
+ WorkflowRunFailedError: () => WorkflowRunFailedError,
50
+ WorkflowRunTimeoutError: () => WorkflowRunTimeoutError,
51
+ WorkflowRuns: () => WorkflowRuns,
49
52
  Workflows: () => Workflows
50
53
  });
51
54
  module.exports = __toCommonJS(index_exports);
@@ -89,6 +92,18 @@ var JobTimeoutError = class extends CurvetError {
89
92
  this.jobId = jobId;
90
93
  }
91
94
  };
95
+ var WorkflowRunFailedError = class extends CurvetError {
96
+ constructor(message, runId, opts = {}) {
97
+ super(message, opts);
98
+ this.runId = runId;
99
+ }
100
+ };
101
+ var WorkflowRunTimeoutError = class extends CurvetError {
102
+ constructor(message, runId, opts = {}) {
103
+ super(message, opts);
104
+ this.runId = runId;
105
+ }
106
+ };
92
107
  function errorFromResponse(status, body, requestId, headers) {
93
108
  const b = body ?? {};
94
109
  const message = typeof b.error === "string" ? b.error : `HTTP ${status}`;
@@ -555,38 +570,133 @@ var Analytics = class {
555
570
  };
556
571
 
557
572
  // src/resources/workflows.ts
573
+ function normalizeRun(body) {
574
+ const b = body ?? {};
575
+ return {
576
+ runId: b.runId,
577
+ status: b.status,
578
+ progress: b.progress,
579
+ totalNodes: b.totalNodes,
580
+ completedNodeCount: b.completedNodeCount,
581
+ currentNode: b.currentNode ?? null,
582
+ nodesExecuted: b.nodesExecuted,
583
+ result: b.result,
584
+ error: b.error ?? null,
585
+ startTime: b.startTime,
586
+ endTime: b.endTime,
587
+ raw: body
588
+ };
589
+ }
590
+ function buildBody(params, extra = {}) {
591
+ const hasFiles = params.files && Object.keys(params.files).length > 0;
592
+ if (hasFiles) {
593
+ const form = new FormData();
594
+ form.append("inputs", JSON.stringify(params.inputs ?? {}));
595
+ if (params.includeFullState !== void 0) {
596
+ form.append("includeFullState", String(params.includeFullState));
597
+ }
598
+ for (const [k, v] of Object.entries(extra)) form.append(k, String(v));
599
+ for (const [field, file] of Object.entries(params.files)) {
600
+ form.append(field, file);
601
+ }
602
+ return form;
603
+ }
604
+ return {
605
+ inputs: params.inputs ?? {},
606
+ includeFullState: params.includeFullState,
607
+ ...extra
608
+ };
609
+ }
610
+ var WorkflowRuns = class {
611
+ constructor(client) {
612
+ this.client = client;
613
+ }
614
+ /** Fetch the current status of an async run once (no polling). */
615
+ async retrieve(runId, options) {
616
+ const body = await this.client.request({
617
+ method: "GET",
618
+ path: `/workflows/runs/${encodeURIComponent(runId)}`,
619
+ options
620
+ });
621
+ return normalizeRun(body);
622
+ }
623
+ };
558
624
  var Workflows = class {
559
625
  constructor(client) {
560
626
  this.client = client;
627
+ this.runs = new WorkflowRuns(client);
561
628
  }
562
629
  /**
563
- * Execute a visual-builder workflow by id. Sends JSON when there are no file
564
- * inputs, multipart/form-data when files are provided. Not auto-retried (a
565
- * workflow run executes and may consume credits).
630
+ * Execute a workflow synchronously (blocks until it finishes). Best for short
631
+ * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.
632
+ * Sends JSON, or multipart/form-data when file inputs are provided.
566
633
  */
567
634
  async run(id, params = {}, options) {
568
635
  const reqOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };
569
- const hasFiles = params.files && Object.keys(params.files).length > 0;
570
- let body;
571
- if (hasFiles) {
572
- const form = new FormData();
573
- form.append("inputs", JSON.stringify(params.inputs ?? {}));
574
- if (params.includeFullState !== void 0) {
575
- form.append("includeFullState", String(params.includeFullState));
576
- }
577
- for (const [field, file] of Object.entries(params.files)) {
578
- form.append(field, file);
579
- }
580
- body = form;
581
- } else {
582
- body = { inputs: params.inputs ?? {}, includeFullState: params.includeFullState };
583
- }
584
636
  return this.client.request({
585
637
  method: "POST",
586
638
  path: `/workflows/${encodeURIComponent(id)}/run`,
587
- body,
639
+ body: buildBody(params),
640
+ options: reqOptions
641
+ });
642
+ }
643
+ /**
644
+ * Submit a workflow in async (pollable) mode — returns immediately with a
645
+ * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.
646
+ */
647
+ async submit(id, params = {}, options) {
648
+ const reqOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };
649
+ const res = await this.client.request({
650
+ method: "POST",
651
+ path: `/workflows/${encodeURIComponent(id)}/run`,
652
+ body: buildBody(params, { async: true }),
588
653
  options: reqOptions
589
654
  });
655
+ return { runId: res?.runId, status: res?.status ?? "running", raw: res };
656
+ }
657
+ /**
658
+ * Submit and poll to completion. Resolves with the completed run (including
659
+ * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError
660
+ * on failure, WorkflowRunTimeoutError on timeout.
661
+ */
662
+ async runAndPoll(id, params = {}, opts = {}) {
663
+ const submitted = await this.submit(id, params, opts);
664
+ if (!submitted.runId) {
665
+ throw new CurvetError("Workflow submit did not return a runId", {
666
+ raw: submitted.raw
667
+ });
668
+ }
669
+ const intervalMs = opts.pollIntervalMs ?? 2500;
670
+ const timeoutMs = opts.pollTimeoutMs ?? 3e5;
671
+ let run;
672
+ try {
673
+ run = await pollUntil(
674
+ () => this.runs.retrieve(submitted.runId, { signal: opts.signal }),
675
+ {
676
+ intervalMs,
677
+ timeoutMs,
678
+ signal: opts.signal,
679
+ isTerminal: (r) => r.status === "completed" || r.status === "failed" || r.status === "stopped",
680
+ onTick: (r) => opts.onProgress?.(r)
681
+ }
682
+ );
683
+ } catch (e) {
684
+ if (e instanceof PollTimeoutError) {
685
+ throw new WorkflowRunTimeoutError(
686
+ `Workflow run ${submitted.runId} did not finish within ${timeoutMs}ms`,
687
+ submitted.runId
688
+ );
689
+ }
690
+ throw e;
691
+ }
692
+ if (run.status === "failed" || run.status === "stopped") {
693
+ throw new WorkflowRunFailedError(
694
+ run.error || `Workflow run ${submitted.runId} ${run.status}`,
695
+ submitted.runId,
696
+ { raw: run.raw }
697
+ );
698
+ }
699
+ return run;
590
700
  }
591
701
  };
592
702
 
@@ -741,6 +851,9 @@ function defaultFetch() {
741
851
  ThreeD,
742
852
  Video,
743
853
  Voice,
854
+ WorkflowRunFailedError,
855
+ WorkflowRunTimeoutError,
856
+ WorkflowRuns,
744
857
  Workflows
745
858
  });
746
859
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../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 { Curvet, DEFAULT_BASE_URL } from \"./client\";\nexport type { CurvetOptions } from \"./client\";\n\n// Errors\nexport {\n CurvetError,\n AuthError,\n PermissionError,\n BadRequestError,\n NotFoundError,\n APIError,\n ConnectionError,\n InsufficientBalanceError,\n RateLimitError,\n JobFailedError,\n JobTimeoutError,\n} from \"./core/errors\";\nexport type { CurvetErrorOptions } from \"./core/errors\";\n\n// Resources\nexport { Chat } from \"./resources/chat\";\nexport { Images } from \"./resources/image\";\nexport { MediaResource } from \"./resources/media\";\nexport type { MediaParamsBase } from \"./resources/media\";\nexport { Video } from \"./resources/video\";\nexport { Audio } from \"./resources/audio\";\nexport { ThreeD } from \"./resources/threeD\";\nexport { Jobs, Job } from \"./resources/jobs\";\nexport type { JobDefaults } from \"./resources/jobs\";\nexport { Models } from \"./resources/models\";\nexport type { ModelsListOptions } from \"./resources/models\";\nexport { Balance } from \"./resources/balance\";\nexport type { BalanceInfo } from \"./resources/balance\";\nexport { Analytics } from \"./resources/analytics\";\nexport type { AnalyticsParams, AnalyticsResult } from \"./resources/analytics\";\nexport { Workflows } from \"./resources/workflows\";\nexport type { WorkflowRunParams, WorkflowRunResult } from \"./resources/workflows\";\nexport { Food } from \"./resources/food\";\nexport type { FoodItem } from \"./resources/food\";\nexport { Voice } from \"./resources/voice\";\nexport type { SttParams, SttResult } from \"./resources/voice\";\n\n// Types\nexport type { Usage, RequestOptions, FetchLike } from \"./types/common\";\nexport type { ChatRole, ChatMessage, ChatCreateParams, ChatResponse } from \"./types/chat\";\nexport type { ImageGenerateParams, ImageResponse } from \"./types/image\";\nexport type {\n JobStatus,\n MediaKind,\n MediaJob,\n VideoGenerateParams,\n AudioGenerateParams,\n ThreeDGenerateParams,\n PollOptions,\n} from \"./types/job\";\nexport type { ModelType, ModelInfo, RateLimits, KnownModelId, ModelId } from \"./types/models\";\n","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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../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 { Curvet, DEFAULT_BASE_URL } from \"./client\";\nexport type { CurvetOptions } from \"./client\";\n\n// Errors\nexport {\n CurvetError,\n AuthError,\n PermissionError,\n BadRequestError,\n NotFoundError,\n APIError,\n ConnectionError,\n InsufficientBalanceError,\n RateLimitError,\n JobFailedError,\n JobTimeoutError,\n WorkflowRunFailedError,\n WorkflowRunTimeoutError,\n} from \"./core/errors\";\nexport type { CurvetErrorOptions } from \"./core/errors\";\n\n// Resources\nexport { Chat } from \"./resources/chat\";\nexport { Images } from \"./resources/image\";\nexport { MediaResource } from \"./resources/media\";\nexport type { MediaParamsBase } from \"./resources/media\";\nexport { Video } from \"./resources/video\";\nexport { Audio } from \"./resources/audio\";\nexport { ThreeD } from \"./resources/threeD\";\nexport { Jobs, Job } from \"./resources/jobs\";\nexport type { JobDefaults } from \"./resources/jobs\";\nexport { Models } from \"./resources/models\";\nexport type { ModelsListOptions } from \"./resources/models\";\nexport { Balance } from \"./resources/balance\";\nexport type { BalanceInfo } from \"./resources/balance\";\nexport { Analytics } from \"./resources/analytics\";\nexport type { AnalyticsParams, AnalyticsResult } from \"./resources/analytics\";\nexport { Workflows, WorkflowRuns } from \"./resources/workflows\";\nexport type {\n WorkflowRunParams,\n WorkflowRunResult,\n WorkflowRunStatus,\n WorkflowRunNode,\n WorkflowRun,\n WorkflowSubmitResult,\n WorkflowPollOptions,\n} from \"./resources/workflows\";\nexport { Food } from \"./resources/food\";\nexport type { FoodItem } from \"./resources/food\";\nexport { Voice } from \"./resources/voice\";\nexport type { SttParams, SttResult } from \"./resources/voice\";\n\n// Types\nexport type { Usage, RequestOptions, FetchLike } from \"./types/common\";\nexport type { ChatRole, ChatMessage, ChatCreateParams, ChatResponse } from \"./types/chat\";\nexport type { ImageGenerateParams, ImageResponse } from \"./types/image\";\nexport type {\n JobStatus,\n MediaKind,\n MediaJob,\n VideoGenerateParams,\n AudioGenerateParams,\n ThreeDGenerateParams,\n PollOptions,\n} from \"./types/job\";\nexport type { ModelType, ModelInfo, RateLimits, KnownModelId, ModelId } from \"./types/models\";\n","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\n/** An async workflow run finished with status \"failed\" (or \"stopped\"). */\nexport class WorkflowRunFailedError extends CurvetError {\n readonly runId: string;\n constructor(message: string, runId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.runId = runId;\n }\n}\n\n/** An async workflow run did not finish within the poll timeout. */\nexport class WorkflowRunTimeoutError extends CurvetError {\n readonly runId: string;\n constructor(message: string, runId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.runId = runId;\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\";\nimport { pollUntil, PollTimeoutError } from \"../core/poll\";\nimport {\n CurvetError,\n WorkflowRunFailedError,\n WorkflowRunTimeoutError,\n} from \"../core/errors\";\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\n/** Result of a synchronous `run()` call. */\nexport interface WorkflowRunResult {\n success: boolean;\n [key: string]: unknown;\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"stopped\";\n\nexport interface WorkflowRunNode {\n nodeId: string;\n nodeLabel?: string;\n nodeType?: string;\n status?: string;\n executionTime?: number;\n}\n\n/** Normalized status of an async (pollable) workflow run. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n progress?: number;\n totalNodes?: number;\n completedNodeCount?: number;\n /** The node currently executing (null when finished/queued). */\n currentNode?: { id: string; label?: string; type?: string } | null;\n nodesExecuted?: WorkflowRunNode[];\n /** Final outputs (present once completed). */\n result?: unknown;\n error?: string | null;\n startTime?: string;\n endTime?: string;\n /** Raw, unnormalized response body. */\n raw: unknown;\n}\n\nexport interface WorkflowSubmitResult {\n runId: string;\n status: WorkflowRunStatus;\n raw: unknown;\n}\n\nexport interface WorkflowPollOptions {\n /** Poll interval in ms (default 2500). */\n pollIntervalMs?: number;\n /** Total poll timeout in ms before throwing WorkflowRunTimeoutError (default 300000). */\n pollTimeoutMs?: number;\n signal?: AbortSignal;\n /** Called on each poll tick with the latest run status (current node, progress). */\n onProgress?: (run: WorkflowRun) => void;\n}\n\nfunction normalizeRun(body: unknown): WorkflowRun {\n const b = (body ?? {}) as Record<string, any>;\n return {\n runId: b.runId,\n status: b.status,\n progress: b.progress,\n totalNodes: b.totalNodes,\n completedNodeCount: b.completedNodeCount,\n currentNode: b.currentNode ?? null,\n nodesExecuted: b.nodesExecuted,\n result: b.result,\n error: b.error ?? null,\n startTime: b.startTime,\n endTime: b.endTime,\n raw: body,\n };\n}\n\nfunction buildBody(params: WorkflowRunParams, extra: Record<string, unknown> = {}) {\n const hasFiles = params.files && Object.keys(params.files).length > 0;\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 [k, v] of Object.entries(extra)) form.append(k, String(v));\n for (const [field, file] of Object.entries(params.files!)) {\n form.append(field, file);\n }\n return form;\n }\n return {\n inputs: params.inputs ?? {},\n includeFullState: params.includeFullState,\n ...extra,\n };\n}\n\n/** Retrieve async workflow-run status. */\nexport class WorkflowRuns {\n constructor(private client: HttpClient) {}\n\n /** Fetch the current status of an async run once (no polling). */\n async retrieve(runId: string, options?: RequestOptions): Promise<WorkflowRun> {\n const body = await this.client.request({\n method: \"GET\",\n path: `/workflows/runs/${encodeURIComponent(runId)}`,\n options,\n });\n return normalizeRun(body);\n }\n}\n\nexport class Workflows {\n readonly runs: WorkflowRuns;\n\n constructor(private client: HttpClient) {\n this.runs = new WorkflowRuns(client);\n }\n\n /**\n * Execute a workflow synchronously (blocks until it finishes). Best for short\n * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.\n * Sends JSON, or multipart/form-data when file inputs are provided.\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 return this.client.request<WorkflowRunResult>({\n method: \"POST\",\n path: `/workflows/${encodeURIComponent(id)}/run`,\n body: buildBody(params),\n options: reqOptions,\n });\n }\n\n /**\n * Submit a workflow in async (pollable) mode — returns immediately with a\n * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.\n */\n async submit(\n id: string,\n params: WorkflowRunParams = {},\n options?: RequestOptions,\n ): Promise<WorkflowSubmitResult> {\n const reqOptions: RequestOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };\n const res = await this.client.request<Record<string, any>>({\n method: \"POST\",\n path: `/workflows/${encodeURIComponent(id)}/run`,\n body: buildBody(params, { async: true }),\n options: reqOptions,\n });\n return { runId: res?.runId, status: res?.status ?? \"running\", raw: res };\n }\n\n /**\n * Submit and poll to completion. Resolves with the completed run (including\n * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError\n * on failure, WorkflowRunTimeoutError on timeout.\n */\n async runAndPoll(\n id: string,\n params: WorkflowRunParams = {},\n opts: RequestOptions & WorkflowPollOptions = {},\n ): Promise<WorkflowRun> {\n const submitted = await this.submit(id, params, opts);\n if (!submitted.runId) {\n throw new CurvetError(\"Workflow submit did not return a runId\", {\n raw: submitted.raw,\n });\n }\n\n const intervalMs = opts.pollIntervalMs ?? 2500;\n const timeoutMs = opts.pollTimeoutMs ?? 300_000;\n\n let run: WorkflowRun;\n try {\n run = await pollUntil(\n () => this.runs.retrieve(submitted.runId, { signal: opts.signal }),\n {\n intervalMs,\n timeoutMs,\n signal: opts.signal,\n isTerminal: (r) =>\n r.status === \"completed\" || r.status === \"failed\" || r.status === \"stopped\",\n onTick: (r) => opts.onProgress?.(r),\n },\n );\n } catch (e) {\n if (e instanceof PollTimeoutError) {\n throw new WorkflowRunTimeoutError(\n `Workflow run ${submitted.runId} did not finish within ${timeoutMs}ms`,\n submitted.runId,\n );\n }\n throw e;\n }\n\n if (run.status === \"failed\" || run.status === \"stopped\") {\n throw new WorkflowRunFailedError(\n run.error || `Workflow run ${submitted.runId} ${run.status}`,\n submitted.runId,\n { raw: run.raw },\n );\n }\n return run;\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/dist/index.d.cts CHANGED
@@ -338,19 +338,83 @@ interface WorkflowRunParams {
338
338
  /** Include the full execution state in the response (default true server-side). */
339
339
  includeFullState?: boolean;
340
340
  }
341
+ /** Result of a synchronous `run()` call. */
341
342
  interface WorkflowRunResult {
342
343
  success: boolean;
343
344
  [key: string]: unknown;
344
345
  }
346
+ type WorkflowRunStatus = "queued" | "running" | "completed" | "failed" | "stopped";
347
+ interface WorkflowRunNode {
348
+ nodeId: string;
349
+ nodeLabel?: string;
350
+ nodeType?: string;
351
+ status?: string;
352
+ executionTime?: number;
353
+ }
354
+ /** Normalized status of an async (pollable) workflow run. */
355
+ interface WorkflowRun {
356
+ runId: string;
357
+ status: WorkflowRunStatus;
358
+ progress?: number;
359
+ totalNodes?: number;
360
+ completedNodeCount?: number;
361
+ /** The node currently executing (null when finished/queued). */
362
+ currentNode?: {
363
+ id: string;
364
+ label?: string;
365
+ type?: string;
366
+ } | null;
367
+ nodesExecuted?: WorkflowRunNode[];
368
+ /** Final outputs (present once completed). */
369
+ result?: unknown;
370
+ error?: string | null;
371
+ startTime?: string;
372
+ endTime?: string;
373
+ /** Raw, unnormalized response body. */
374
+ raw: unknown;
375
+ }
376
+ interface WorkflowSubmitResult {
377
+ runId: string;
378
+ status: WorkflowRunStatus;
379
+ raw: unknown;
380
+ }
381
+ interface WorkflowPollOptions {
382
+ /** Poll interval in ms (default 2500). */
383
+ pollIntervalMs?: number;
384
+ /** Total poll timeout in ms before throwing WorkflowRunTimeoutError (default 300000). */
385
+ pollTimeoutMs?: number;
386
+ signal?: AbortSignal;
387
+ /** Called on each poll tick with the latest run status (current node, progress). */
388
+ onProgress?: (run: WorkflowRun) => void;
389
+ }
390
+ /** Retrieve async workflow-run status. */
391
+ declare class WorkflowRuns {
392
+ private client;
393
+ constructor(client: HttpClient);
394
+ /** Fetch the current status of an async run once (no polling). */
395
+ retrieve(runId: string, options?: RequestOptions): Promise<WorkflowRun>;
396
+ }
345
397
  declare class Workflows {
346
398
  private client;
399
+ readonly runs: WorkflowRuns;
347
400
  constructor(client: HttpClient);
348
401
  /**
349
- * Execute a visual-builder workflow by id. Sends JSON when there are no file
350
- * inputs, multipart/form-data when files are provided. Not auto-retried (a
351
- * workflow run executes and may consume credits).
402
+ * Execute a workflow synchronously (blocks until it finishes). Best for short
403
+ * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.
404
+ * Sends JSON, or multipart/form-data when file inputs are provided.
352
405
  */
353
406
  run(id: string, params?: WorkflowRunParams, options?: RequestOptions): Promise<WorkflowRunResult>;
407
+ /**
408
+ * Submit a workflow in async (pollable) mode — returns immediately with a
409
+ * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.
410
+ */
411
+ submit(id: string, params?: WorkflowRunParams, options?: RequestOptions): Promise<WorkflowSubmitResult>;
412
+ /**
413
+ * Submit and poll to completion. Resolves with the completed run (including
414
+ * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError
415
+ * on failure, WorkflowRunTimeoutError on timeout.
416
+ */
417
+ runAndPoll(id: string, params?: WorkflowRunParams, opts?: RequestOptions & WorkflowPollOptions): Promise<WorkflowRun>;
354
418
  }
355
419
 
356
420
  interface FoodItem {
@@ -511,5 +575,15 @@ declare class JobTimeoutError extends CurvetError {
511
575
  readonly jobId: string;
512
576
  constructor(message: string, jobId: string, opts?: CurvetErrorOptions);
513
577
  }
578
+ /** An async workflow run finished with status "failed" (or "stopped"). */
579
+ declare class WorkflowRunFailedError extends CurvetError {
580
+ readonly runId: string;
581
+ constructor(message: string, runId: string, opts?: CurvetErrorOptions);
582
+ }
583
+ /** An async workflow run did not finish within the poll timeout. */
584
+ declare class WorkflowRunTimeoutError extends CurvetError {
585
+ readonly runId: string;
586
+ constructor(message: string, runId: string, opts?: CurvetErrorOptions);
587
+ }
514
588
 
515
- export { APIError, Analytics, type AnalyticsParams, type AnalyticsResult, Audio, type AudioGenerateParams, AuthError, BadRequestError, Balance, type BalanceInfo, Chat, type ChatCreateParams, type ChatMessage, type ChatResponse, type ChatRole, ConnectionError, Curvet, CurvetError, type CurvetErrorOptions, type CurvetOptions, DEFAULT_BASE_URL, type FetchLike, Food, type FoodItem, type ImageGenerateParams, type ImageResponse, Images, InsufficientBalanceError, Job, type JobDefaults, JobFailedError, type JobStatus, JobTimeoutError, Jobs, type KnownModelId, type MediaJob, type MediaKind, type MediaParamsBase, MediaResource, type ModelId, type ModelInfo, type ModelType, Models, type ModelsListOptions, NotFoundError, PermissionError, type PollOptions, RateLimitError, type RateLimits, type RequestOptions, type SttParams, type SttResult, ThreeD, type ThreeDGenerateParams, type Usage, Video, type VideoGenerateParams, Voice, type WorkflowRunParams, type WorkflowRunResult, Workflows };
589
+ export { APIError, Analytics, type AnalyticsParams, type AnalyticsResult, Audio, type AudioGenerateParams, AuthError, BadRequestError, Balance, type BalanceInfo, Chat, type ChatCreateParams, type ChatMessage, type ChatResponse, type ChatRole, ConnectionError, Curvet, CurvetError, type CurvetErrorOptions, type CurvetOptions, DEFAULT_BASE_URL, type FetchLike, Food, type FoodItem, type ImageGenerateParams, type ImageResponse, Images, InsufficientBalanceError, Job, type JobDefaults, JobFailedError, type JobStatus, JobTimeoutError, Jobs, type KnownModelId, type MediaJob, type MediaKind, type MediaParamsBase, MediaResource, type ModelId, type ModelInfo, type ModelType, Models, type ModelsListOptions, NotFoundError, PermissionError, type PollOptions, RateLimitError, type RateLimits, type RequestOptions, type SttParams, type SttResult, ThreeD, type ThreeDGenerateParams, type Usage, Video, type VideoGenerateParams, Voice, type WorkflowPollOptions, type WorkflowRun, WorkflowRunFailedError, type WorkflowRunNode, type WorkflowRunParams, type WorkflowRunResult, type WorkflowRunStatus, WorkflowRunTimeoutError, WorkflowRuns, type WorkflowSubmitResult, Workflows };
package/dist/index.d.ts CHANGED
@@ -338,19 +338,83 @@ interface WorkflowRunParams {
338
338
  /** Include the full execution state in the response (default true server-side). */
339
339
  includeFullState?: boolean;
340
340
  }
341
+ /** Result of a synchronous `run()` call. */
341
342
  interface WorkflowRunResult {
342
343
  success: boolean;
343
344
  [key: string]: unknown;
344
345
  }
346
+ type WorkflowRunStatus = "queued" | "running" | "completed" | "failed" | "stopped";
347
+ interface WorkflowRunNode {
348
+ nodeId: string;
349
+ nodeLabel?: string;
350
+ nodeType?: string;
351
+ status?: string;
352
+ executionTime?: number;
353
+ }
354
+ /** Normalized status of an async (pollable) workflow run. */
355
+ interface WorkflowRun {
356
+ runId: string;
357
+ status: WorkflowRunStatus;
358
+ progress?: number;
359
+ totalNodes?: number;
360
+ completedNodeCount?: number;
361
+ /** The node currently executing (null when finished/queued). */
362
+ currentNode?: {
363
+ id: string;
364
+ label?: string;
365
+ type?: string;
366
+ } | null;
367
+ nodesExecuted?: WorkflowRunNode[];
368
+ /** Final outputs (present once completed). */
369
+ result?: unknown;
370
+ error?: string | null;
371
+ startTime?: string;
372
+ endTime?: string;
373
+ /** Raw, unnormalized response body. */
374
+ raw: unknown;
375
+ }
376
+ interface WorkflowSubmitResult {
377
+ runId: string;
378
+ status: WorkflowRunStatus;
379
+ raw: unknown;
380
+ }
381
+ interface WorkflowPollOptions {
382
+ /** Poll interval in ms (default 2500). */
383
+ pollIntervalMs?: number;
384
+ /** Total poll timeout in ms before throwing WorkflowRunTimeoutError (default 300000). */
385
+ pollTimeoutMs?: number;
386
+ signal?: AbortSignal;
387
+ /** Called on each poll tick with the latest run status (current node, progress). */
388
+ onProgress?: (run: WorkflowRun) => void;
389
+ }
390
+ /** Retrieve async workflow-run status. */
391
+ declare class WorkflowRuns {
392
+ private client;
393
+ constructor(client: HttpClient);
394
+ /** Fetch the current status of an async run once (no polling). */
395
+ retrieve(runId: string, options?: RequestOptions): Promise<WorkflowRun>;
396
+ }
345
397
  declare class Workflows {
346
398
  private client;
399
+ readonly runs: WorkflowRuns;
347
400
  constructor(client: HttpClient);
348
401
  /**
349
- * Execute a visual-builder workflow by id. Sends JSON when there are no file
350
- * inputs, multipart/form-data when files are provided. Not auto-retried (a
351
- * workflow run executes and may consume credits).
402
+ * Execute a workflow synchronously (blocks until it finishes). Best for short
403
+ * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.
404
+ * Sends JSON, or multipart/form-data when file inputs are provided.
352
405
  */
353
406
  run(id: string, params?: WorkflowRunParams, options?: RequestOptions): Promise<WorkflowRunResult>;
407
+ /**
408
+ * Submit a workflow in async (pollable) mode — returns immediately with a
409
+ * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.
410
+ */
411
+ submit(id: string, params?: WorkflowRunParams, options?: RequestOptions): Promise<WorkflowSubmitResult>;
412
+ /**
413
+ * Submit and poll to completion. Resolves with the completed run (including
414
+ * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError
415
+ * on failure, WorkflowRunTimeoutError on timeout.
416
+ */
417
+ runAndPoll(id: string, params?: WorkflowRunParams, opts?: RequestOptions & WorkflowPollOptions): Promise<WorkflowRun>;
354
418
  }
355
419
 
356
420
  interface FoodItem {
@@ -511,5 +575,15 @@ declare class JobTimeoutError extends CurvetError {
511
575
  readonly jobId: string;
512
576
  constructor(message: string, jobId: string, opts?: CurvetErrorOptions);
513
577
  }
578
+ /** An async workflow run finished with status "failed" (or "stopped"). */
579
+ declare class WorkflowRunFailedError extends CurvetError {
580
+ readonly runId: string;
581
+ constructor(message: string, runId: string, opts?: CurvetErrorOptions);
582
+ }
583
+ /** An async workflow run did not finish within the poll timeout. */
584
+ declare class WorkflowRunTimeoutError extends CurvetError {
585
+ readonly runId: string;
586
+ constructor(message: string, runId: string, opts?: CurvetErrorOptions);
587
+ }
514
588
 
515
- export { APIError, Analytics, type AnalyticsParams, type AnalyticsResult, Audio, type AudioGenerateParams, AuthError, BadRequestError, Balance, type BalanceInfo, Chat, type ChatCreateParams, type ChatMessage, type ChatResponse, type ChatRole, ConnectionError, Curvet, CurvetError, type CurvetErrorOptions, type CurvetOptions, DEFAULT_BASE_URL, type FetchLike, Food, type FoodItem, type ImageGenerateParams, type ImageResponse, Images, InsufficientBalanceError, Job, type JobDefaults, JobFailedError, type JobStatus, JobTimeoutError, Jobs, type KnownModelId, type MediaJob, type MediaKind, type MediaParamsBase, MediaResource, type ModelId, type ModelInfo, type ModelType, Models, type ModelsListOptions, NotFoundError, PermissionError, type PollOptions, RateLimitError, type RateLimits, type RequestOptions, type SttParams, type SttResult, ThreeD, type ThreeDGenerateParams, type Usage, Video, type VideoGenerateParams, Voice, type WorkflowRunParams, type WorkflowRunResult, Workflows };
589
+ export { APIError, Analytics, type AnalyticsParams, type AnalyticsResult, Audio, type AudioGenerateParams, AuthError, BadRequestError, Balance, type BalanceInfo, Chat, type ChatCreateParams, type ChatMessage, type ChatResponse, type ChatRole, ConnectionError, Curvet, CurvetError, type CurvetErrorOptions, type CurvetOptions, DEFAULT_BASE_URL, type FetchLike, Food, type FoodItem, type ImageGenerateParams, type ImageResponse, Images, InsufficientBalanceError, Job, type JobDefaults, JobFailedError, type JobStatus, JobTimeoutError, Jobs, type KnownModelId, type MediaJob, type MediaKind, type MediaParamsBase, MediaResource, type ModelId, type ModelInfo, type ModelType, Models, type ModelsListOptions, NotFoundError, PermissionError, type PollOptions, RateLimitError, type RateLimits, type RequestOptions, type SttParams, type SttResult, ThreeD, type ThreeDGenerateParams, type Usage, Video, type VideoGenerateParams, Voice, type WorkflowPollOptions, type WorkflowRun, WorkflowRunFailedError, type WorkflowRunNode, type WorkflowRunParams, type WorkflowRunResult, type WorkflowRunStatus, WorkflowRunTimeoutError, WorkflowRuns, type WorkflowSubmitResult, Workflows };
package/dist/index.js CHANGED
@@ -37,6 +37,18 @@ var JobTimeoutError = class extends CurvetError {
37
37
  this.jobId = jobId;
38
38
  }
39
39
  };
40
+ var WorkflowRunFailedError = class extends CurvetError {
41
+ constructor(message, runId, opts = {}) {
42
+ super(message, opts);
43
+ this.runId = runId;
44
+ }
45
+ };
46
+ var WorkflowRunTimeoutError = class extends CurvetError {
47
+ constructor(message, runId, opts = {}) {
48
+ super(message, opts);
49
+ this.runId = runId;
50
+ }
51
+ };
40
52
  function errorFromResponse(status, body, requestId, headers) {
41
53
  const b = body ?? {};
42
54
  const message = typeof b.error === "string" ? b.error : `HTTP ${status}`;
@@ -503,38 +515,133 @@ var Analytics = class {
503
515
  };
504
516
 
505
517
  // src/resources/workflows.ts
518
+ function normalizeRun(body) {
519
+ const b = body ?? {};
520
+ return {
521
+ runId: b.runId,
522
+ status: b.status,
523
+ progress: b.progress,
524
+ totalNodes: b.totalNodes,
525
+ completedNodeCount: b.completedNodeCount,
526
+ currentNode: b.currentNode ?? null,
527
+ nodesExecuted: b.nodesExecuted,
528
+ result: b.result,
529
+ error: b.error ?? null,
530
+ startTime: b.startTime,
531
+ endTime: b.endTime,
532
+ raw: body
533
+ };
534
+ }
535
+ function buildBody(params, extra = {}) {
536
+ const hasFiles = params.files && Object.keys(params.files).length > 0;
537
+ if (hasFiles) {
538
+ const form = new FormData();
539
+ form.append("inputs", JSON.stringify(params.inputs ?? {}));
540
+ if (params.includeFullState !== void 0) {
541
+ form.append("includeFullState", String(params.includeFullState));
542
+ }
543
+ for (const [k, v] of Object.entries(extra)) form.append(k, String(v));
544
+ for (const [field, file] of Object.entries(params.files)) {
545
+ form.append(field, file);
546
+ }
547
+ return form;
548
+ }
549
+ return {
550
+ inputs: params.inputs ?? {},
551
+ includeFullState: params.includeFullState,
552
+ ...extra
553
+ };
554
+ }
555
+ var WorkflowRuns = class {
556
+ constructor(client) {
557
+ this.client = client;
558
+ }
559
+ /** Fetch the current status of an async run once (no polling). */
560
+ async retrieve(runId, options) {
561
+ const body = await this.client.request({
562
+ method: "GET",
563
+ path: `/workflows/runs/${encodeURIComponent(runId)}`,
564
+ options
565
+ });
566
+ return normalizeRun(body);
567
+ }
568
+ };
506
569
  var Workflows = class {
507
570
  constructor(client) {
508
571
  this.client = client;
572
+ this.runs = new WorkflowRuns(client);
509
573
  }
510
574
  /**
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).
575
+ * Execute a workflow synchronously (blocks until it finishes). Best for short
576
+ * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.
577
+ * Sends JSON, or multipart/form-data when file inputs are provided.
514
578
  */
515
579
  async run(id, params = {}, options) {
516
580
  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
581
  return this.client.request({
533
582
  method: "POST",
534
583
  path: `/workflows/${encodeURIComponent(id)}/run`,
535
- body,
584
+ body: buildBody(params),
585
+ options: reqOptions
586
+ });
587
+ }
588
+ /**
589
+ * Submit a workflow in async (pollable) mode — returns immediately with a
590
+ * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.
591
+ */
592
+ async submit(id, params = {}, options) {
593
+ const reqOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };
594
+ const res = await this.client.request({
595
+ method: "POST",
596
+ path: `/workflows/${encodeURIComponent(id)}/run`,
597
+ body: buildBody(params, { async: true }),
536
598
  options: reqOptions
537
599
  });
600
+ return { runId: res?.runId, status: res?.status ?? "running", raw: res };
601
+ }
602
+ /**
603
+ * Submit and poll to completion. Resolves with the completed run (including
604
+ * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError
605
+ * on failure, WorkflowRunTimeoutError on timeout.
606
+ */
607
+ async runAndPoll(id, params = {}, opts = {}) {
608
+ const submitted = await this.submit(id, params, opts);
609
+ if (!submitted.runId) {
610
+ throw new CurvetError("Workflow submit did not return a runId", {
611
+ raw: submitted.raw
612
+ });
613
+ }
614
+ const intervalMs = opts.pollIntervalMs ?? 2500;
615
+ const timeoutMs = opts.pollTimeoutMs ?? 3e5;
616
+ let run;
617
+ try {
618
+ run = await pollUntil(
619
+ () => this.runs.retrieve(submitted.runId, { signal: opts.signal }),
620
+ {
621
+ intervalMs,
622
+ timeoutMs,
623
+ signal: opts.signal,
624
+ isTerminal: (r) => r.status === "completed" || r.status === "failed" || r.status === "stopped",
625
+ onTick: (r) => opts.onProgress?.(r)
626
+ }
627
+ );
628
+ } catch (e) {
629
+ if (e instanceof PollTimeoutError) {
630
+ throw new WorkflowRunTimeoutError(
631
+ `Workflow run ${submitted.runId} did not finish within ${timeoutMs}ms`,
632
+ submitted.runId
633
+ );
634
+ }
635
+ throw e;
636
+ }
637
+ if (run.status === "failed" || run.status === "stopped") {
638
+ throw new WorkflowRunFailedError(
639
+ run.error || `Workflow run ${submitted.runId} ${run.status}`,
640
+ submitted.runId,
641
+ { raw: run.raw }
642
+ );
643
+ }
644
+ return run;
538
645
  }
539
646
  };
540
647
 
@@ -688,6 +795,9 @@ export {
688
795
  ThreeD,
689
796
  Video,
690
797
  Voice,
798
+ WorkflowRunFailedError,
799
+ WorkflowRunTimeoutError,
800
+ WorkflowRuns,
691
801
  Workflows
692
802
  };
693
803
  //# 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/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":[]}
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\n/** An async workflow run finished with status \"failed\" (or \"stopped\"). */\nexport class WorkflowRunFailedError extends CurvetError {\n readonly runId: string;\n constructor(message: string, runId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.runId = runId;\n }\n}\n\n/** An async workflow run did not finish within the poll timeout. */\nexport class WorkflowRunTimeoutError extends CurvetError {\n readonly runId: string;\n constructor(message: string, runId: string, opts: CurvetErrorOptions = {}) {\n super(message, opts);\n this.runId = runId;\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\";\nimport { pollUntil, PollTimeoutError } from \"../core/poll\";\nimport {\n CurvetError,\n WorkflowRunFailedError,\n WorkflowRunTimeoutError,\n} from \"../core/errors\";\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\n/** Result of a synchronous `run()` call. */\nexport interface WorkflowRunResult {\n success: boolean;\n [key: string]: unknown;\n}\n\nexport type WorkflowRunStatus =\n | \"queued\"\n | \"running\"\n | \"completed\"\n | \"failed\"\n | \"stopped\";\n\nexport interface WorkflowRunNode {\n nodeId: string;\n nodeLabel?: string;\n nodeType?: string;\n status?: string;\n executionTime?: number;\n}\n\n/** Normalized status of an async (pollable) workflow run. */\nexport interface WorkflowRun {\n runId: string;\n status: WorkflowRunStatus;\n progress?: number;\n totalNodes?: number;\n completedNodeCount?: number;\n /** The node currently executing (null when finished/queued). */\n currentNode?: { id: string; label?: string; type?: string } | null;\n nodesExecuted?: WorkflowRunNode[];\n /** Final outputs (present once completed). */\n result?: unknown;\n error?: string | null;\n startTime?: string;\n endTime?: string;\n /** Raw, unnormalized response body. */\n raw: unknown;\n}\n\nexport interface WorkflowSubmitResult {\n runId: string;\n status: WorkflowRunStatus;\n raw: unknown;\n}\n\nexport interface WorkflowPollOptions {\n /** Poll interval in ms (default 2500). */\n pollIntervalMs?: number;\n /** Total poll timeout in ms before throwing WorkflowRunTimeoutError (default 300000). */\n pollTimeoutMs?: number;\n signal?: AbortSignal;\n /** Called on each poll tick with the latest run status (current node, progress). */\n onProgress?: (run: WorkflowRun) => void;\n}\n\nfunction normalizeRun(body: unknown): WorkflowRun {\n const b = (body ?? {}) as Record<string, any>;\n return {\n runId: b.runId,\n status: b.status,\n progress: b.progress,\n totalNodes: b.totalNodes,\n completedNodeCount: b.completedNodeCount,\n currentNode: b.currentNode ?? null,\n nodesExecuted: b.nodesExecuted,\n result: b.result,\n error: b.error ?? null,\n startTime: b.startTime,\n endTime: b.endTime,\n raw: body,\n };\n}\n\nfunction buildBody(params: WorkflowRunParams, extra: Record<string, unknown> = {}) {\n const hasFiles = params.files && Object.keys(params.files).length > 0;\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 [k, v] of Object.entries(extra)) form.append(k, String(v));\n for (const [field, file] of Object.entries(params.files!)) {\n form.append(field, file);\n }\n return form;\n }\n return {\n inputs: params.inputs ?? {},\n includeFullState: params.includeFullState,\n ...extra,\n };\n}\n\n/** Retrieve async workflow-run status. */\nexport class WorkflowRuns {\n constructor(private client: HttpClient) {}\n\n /** Fetch the current status of an async run once (no polling). */\n async retrieve(runId: string, options?: RequestOptions): Promise<WorkflowRun> {\n const body = await this.client.request({\n method: \"GET\",\n path: `/workflows/runs/${encodeURIComponent(runId)}`,\n options,\n });\n return normalizeRun(body);\n }\n}\n\nexport class Workflows {\n readonly runs: WorkflowRuns;\n\n constructor(private client: HttpClient) {\n this.runs = new WorkflowRuns(client);\n }\n\n /**\n * Execute a workflow synchronously (blocks until it finishes). Best for short\n * workflows; for long ones (video/audio/3D nodes) prefer `runAndPoll`.\n * Sends JSON, or multipart/form-data when file inputs are provided.\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 return this.client.request<WorkflowRunResult>({\n method: \"POST\",\n path: `/workflows/${encodeURIComponent(id)}/run`,\n body: buildBody(params),\n options: reqOptions,\n });\n }\n\n /**\n * Submit a workflow in async (pollable) mode — returns immediately with a\n * runId. Poll `runs.retrieve(runId)` for status, or use `runAndPoll`.\n */\n async submit(\n id: string,\n params: WorkflowRunParams = {},\n options?: RequestOptions,\n ): Promise<WorkflowSubmitResult> {\n const reqOptions: RequestOptions = { ...options, maxRetries: options?.maxRetries ?? 0 };\n const res = await this.client.request<Record<string, any>>({\n method: \"POST\",\n path: `/workflows/${encodeURIComponent(id)}/run`,\n body: buildBody(params, { async: true }),\n options: reqOptions,\n });\n return { runId: res?.runId, status: res?.status ?? \"running\", raw: res };\n }\n\n /**\n * Submit and poll to completion. Resolves with the completed run (including\n * `result`), reporting progress via `onProgress`. Throws WorkflowRunFailedError\n * on failure, WorkflowRunTimeoutError on timeout.\n */\n async runAndPoll(\n id: string,\n params: WorkflowRunParams = {},\n opts: RequestOptions & WorkflowPollOptions = {},\n ): Promise<WorkflowRun> {\n const submitted = await this.submit(id, params, opts);\n if (!submitted.runId) {\n throw new CurvetError(\"Workflow submit did not return a runId\", {\n raw: submitted.raw,\n });\n }\n\n const intervalMs = opts.pollIntervalMs ?? 2500;\n const timeoutMs = opts.pollTimeoutMs ?? 300_000;\n\n let run: WorkflowRun;\n try {\n run = await pollUntil(\n () => this.runs.retrieve(submitted.runId, { signal: opts.signal }),\n {\n intervalMs,\n timeoutMs,\n signal: opts.signal,\n isTerminal: (r) =>\n r.status === \"completed\" || r.status === \"failed\" || r.status === \"stopped\",\n onTick: (r) => opts.onProgress?.(r),\n },\n );\n } catch (e) {\n if (e instanceof PollTimeoutError) {\n throw new WorkflowRunTimeoutError(\n `Workflow run ${submitted.runId} did not finish within ${timeoutMs}ms`,\n submitted.runId,\n );\n }\n throw e;\n }\n\n if (run.status === \"failed\" || run.status === \"stopped\") {\n throw new WorkflowRunFailedError(\n run.error || `Workflow run ${submitted.runId} ${run.status}`,\n submitted.runId,\n { raw: run.raw },\n );\n }\n return run;\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.2.1",
3
+ "version": "0.3.0",
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>",
@@ -18,6 +18,7 @@
18
18
  "files": [
19
19
  "dist",
20
20
  "README.md",
21
+ "CHANGELOG.md",
21
22
  "LICENSE"
22
23
  ],
23
24
  "engines": {