@comfyorg/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +236 -0
  2. package/dist/index.d.ts +27 -0
  3. package/dist/index.js +27 -0
  4. package/dist/low/errors.d.ts +73 -0
  5. package/dist/low/errors.js +104 -0
  6. package/dist/low/generated/index.d.ts +1 -0
  7. package/dist/low/generated/index.js +2 -0
  8. package/dist/low/generated/types.gen.d.ts +528 -0
  9. package/dist/low/generated/types.gen.js +2 -0
  10. package/dist/low/generated/zod.gen.d.ts +455 -0
  11. package/dist/low/generated/zod.gen.js +204 -0
  12. package/dist/low/index.d.ts +21 -0
  13. package/dist/low/index.js +21 -0
  14. package/dist/low/models.d.ts +47 -0
  15. package/dist/low/models.js +16 -0
  16. package/dist/low/sse.d.ts +24 -0
  17. package/dist/low/sse.js +44 -0
  18. package/dist/low/transport.d.ts +128 -0
  19. package/dist/low/transport.js +285 -0
  20. package/dist/sdk/abortable-sleep.d.ts +13 -0
  21. package/dist/sdk/abortable-sleep.js +31 -0
  22. package/dist/sdk/assets.d.ts +74 -0
  23. package/dist/sdk/assets.js +200 -0
  24. package/dist/sdk/client.d.ts +70 -0
  25. package/dist/sdk/client.js +120 -0
  26. package/dist/sdk/core.d.ts +33 -0
  27. package/dist/sdk/core.js +89 -0
  28. package/dist/sdk/events.d.ts +60 -0
  29. package/dist/sdk/events.js +84 -0
  30. package/dist/sdk/exceptions.d.ts +79 -0
  31. package/dist/sdk/exceptions.js +114 -0
  32. package/dist/sdk/hashing.d.ts +14 -0
  33. package/dist/sdk/hashing.js +28 -0
  34. package/dist/sdk/index.d.ts +13 -0
  35. package/dist/sdk/index.js +12 -0
  36. package/dist/sdk/jobs.d.ts +47 -0
  37. package/dist/sdk/jobs.js +145 -0
  38. package/dist/sdk/outputs.d.ts +26 -0
  39. package/dist/sdk/outputs.js +48 -0
  40. package/dist/sdk/workflows.d.ts +32 -0
  41. package/dist/sdk/workflows.js +45 -0
  42. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # @comfyorg/sdk (TypeScript)
2
+
3
+ TypeScript SDK for running ComfyUI workflows via the **Comfy API v2**. The
4
+ same code runs against three surfaces — a self-hosted ComfyUI (through
5
+ [`comfy-api-proxy`](https://github.com/Comfy-Org/comfy-api-proxy)), Comfy
6
+ Cloud, or a serverless deployment — changing only the base URL and an
7
+ optional API key. It mirrors the behavior of the
8
+ [Python SDK](https://github.com/Comfy-Org/ComfyPythonSDK) (`comfy-sdk`):
9
+ upload/dedup inputs, submit a workflow, wait for it, download the outputs —
10
+ collapsed here to a single async client (no separate sync/async API;
11
+ JavaScript is async-native).
12
+
13
+ ```ts
14
+ import { Comfy } from "@comfyorg/sdk";
15
+
16
+ const client = new Comfy("http://127.0.0.1:8189"); // local proxy, no key needed
17
+ // const client = new Comfy("https://api.comfy.org", { apiKey: "..." }); // Comfy Cloud
18
+
19
+ const wf = await client.workflows.fromFile("workflow_api.json");
20
+ const asset = client.assets.fromFile("photo.png"); // lazy; hashed + uploaded on first use
21
+ wf.setInput("10", "image", asset);
22
+
23
+ const job = await client.run(wf); // submit, then poll to a terminal state
24
+ await job.getOutputs("13")[0].toFile("out.png");
25
+ ```
26
+
27
+ ## Requirements
28
+
29
+ - **Node >=22.** Node 20 reached end-of-life; browser support is out of
30
+ scope for v1.
31
+ - **Install:**
32
+
33
+ ```bash
34
+ npm i @comfyorg/sdk
35
+ pnpm add @comfyorg/sdk
36
+ yarn add @comfyorg/sdk
37
+ ```
38
+
39
+ Releases are published to npm from a GitHub Release (tag `vX.Y.Z`) by
40
+ [`.github/workflows/publish.yml`](.github/workflows/publish.yml). To build
41
+ from source instead (for local development, or to track an unreleased
42
+ commit), clone this repo, `pnpm install`, `pnpm build`, and reference the
43
+ built `dist/`.
44
+
45
+ ## Auth, per surface
46
+
47
+ | Surface | Auth |
48
+ | ------------------------------------------------------------------ | ------------------------------------------ |
49
+ | Self-hosted proxy (`comfy-api-proxy` in front of your own ComfyUI) | none — do **not** pass `apiKey` |
50
+ | Comfy Cloud | `new Comfy(baseUrl, { apiKey: "ck_..." })` |
51
+ | Serverless | `new Comfy(baseUrl, { apiKey: "ck_..." })` |
52
+
53
+ The client only attaches the `Authorization` header to requests aimed at its
54
+ own `baseUrl`'s origin. If the server hands back an absolute URL on a
55
+ different host (for example a job's `events`/`cancel` link, or a redirect on
56
+ an asset download), the key is not sent there — see "Typed errors" below for
57
+ the exception classes this surface can raise.
58
+
59
+ ## Quickstart
60
+
61
+ ```ts
62
+ import { Comfy } from "@comfyorg/sdk";
63
+
64
+ const client = new Comfy("http://127.0.0.1:8189");
65
+
66
+ const wf = await client.workflows.fromFile("workflow_api.json");
67
+ const job = await client.run(wf); // submit + poll to a terminal state; throws on failure
68
+ const outputs = job.getOutputs("13"); // outputs produced by node "13"
69
+ await outputs[0].toFile("out.png");
70
+ ```
71
+
72
+ `run()` submits and polls to completion in one call. If you want to act on
73
+ the job in between (read `job.status`, stream progress, cancel it), use
74
+ `submit()` and drive the job yourself:
75
+
76
+ ```ts
77
+ const job = await client.submit(wf);
78
+ await job.wait(); // poll to terminal (adaptive backoff); or call job.refresh() yourself
79
+ console.log(job.status, job.outputs);
80
+ ```
81
+
82
+ ## Assets and `core/ASSET`
83
+
84
+ `client.assets.fromFile(path)` / `client.assets.fromBytes(data, options)`
85
+ return a **lazy** asset handle: nothing is hashed or uploaded until the
86
+ handle is actually used. Embed the handle directly in a workflow input with
87
+ `wf.setInput(...)`:
88
+
89
+ ```ts
90
+ const asset = client.assets.fromFile("photo.png");
91
+ wf.setInput("10", "image", asset);
92
+ ```
93
+
94
+ On submit, the SDK walks the workflow graph, finds every embedded handle,
95
+ and for each one: hashes the bytes locally (blake3, via
96
+ [`hash-wasm`](https://www.npmjs.com/package/hash-wasm) — pure WebAssembly,
97
+ no native addon), probes the server's dedup fast path, and only streams a
98
+ full upload if the server does not already have those bytes. Each handle is
99
+ then substituted in place with a `core/ASSET` reference
100
+ (`{ __type: "core/ASSET", info: { id, hash, file_path } }`) before the
101
+ workflow is sent. Re-running a script against unchanged files re-uploads
102
+ nothing.
103
+
104
+ `client.assets` also has `fromStream`, `fromUrl`, and `get(assetId)` (to
105
+ rehydrate a handle for an asset that is already committed) for less common
106
+ cases — see the type definitions for details.
107
+
108
+ ## Live progress
109
+
110
+ `job.events()` is a typed, auto-reconnecting async iterator over the job's
111
+ live event stream:
112
+
113
+ ```ts
114
+ const job = await client.submit(wf);
115
+ for await (const event of job.events()) {
116
+ switch (event.kind) {
117
+ case "progress":
118
+ console.log(event.value);
119
+ break;
120
+ case "outputReady":
121
+ await event.output.toFile(`${event.output.name}`);
122
+ break;
123
+ case "statusChange":
124
+ if (event.status === "succeeded") break;
125
+ }
126
+ }
127
+ ```
128
+
129
+ The stream carries no replay cursor, so a dropped connection is reconnected
130
+ from "now," not replayed from the start. Polling stays the source of truth
131
+ for whether the job is actually done: if the stream is throttled, drops
132
+ permanently, or never even connects, `events()` falls back to polling
133
+ `GET /jobs/{id}` to detect the terminal state, so consumers never hang
134
+ waiting on a stream that isn't coming back. If you only care about the
135
+ final result, `run()`/`job.wait()` (poll-only, no SSE) is simpler.
136
+
137
+ ## Cancellation and timeouts
138
+
139
+ `submit`, `run`, `wait`, `events`, and `cancel` all accept an `AbortSignal`,
140
+ which stops both the in-flight request _and_ any internal wait (the queue-full
141
+ retry pause, the poll backoff, the SSE reconnect pause) — an abort takes
142
+ effect immediately rather than only after the current network call returns:
143
+
144
+ ```ts
145
+ const controller = new AbortController();
146
+ setTimeout(() => controller.abort(), 30_000); // give up after 30s
147
+
148
+ const job = await client.submit(wf, { signal: controller.signal });
149
+ await job.wait(undefined, controller.signal);
150
+ ```
151
+
152
+ `run()` also takes a plain `timeoutMs` if you just want a deadline without
153
+ managing an `AbortController` yourself:
154
+
155
+ ```ts
156
+ await client.run(wf, { timeoutMs: 60_000 });
157
+ ```
158
+
159
+ ## Typed errors
160
+
161
+ Protocol-level failures are raised as one exception class per error code, so
162
+ you can catch what you actually expect instead of string-matching messages:
163
+
164
+ - `Unauthorized`, `Forbidden`, `NotFound`
165
+ - `InvalidWorkflow` (and `WorkflowFormatUi`, for submitting a UI-export
166
+ instead of an API-format graph)
167
+ - `MissingAsset` — a `core/ASSET` reference the server couldn't resolve
168
+ - `HashMismatch` — uploaded bytes didn't match the declared hash
169
+ - `BlobNotFound`
170
+ - `IdempotencyKeyReuse` — the `Idempotency-Key` was reused. `submit()` (and
171
+ `run()`) attach a fresh key to every call, so an accidental exact resend never
172
+ runs the workflow twice. Keys are single-use (reject-on-duplicate, no replay),
173
+ so reusing your own explicit `idempotencyKey` throws this. After an ambiguous
174
+ failure, poll or list your jobs instead of resubmitting with the same key.
175
+ - `InsufficientCredits`
176
+ - `QueueFull` (carries `retryAfter`; `submit()` already retries this one
177
+ transparently)
178
+ - `JobFailed` — a job reached a non-`succeeded` terminal state (carries the
179
+ node-level `error` detail when the platform provided one)
180
+
181
+ All extend a shared `ComfyError` (`code`, `httpStatus`, `details`).
182
+
183
+ ```ts
184
+ import { JobFailed, MissingAsset } from "@comfyorg/sdk";
185
+
186
+ try {
187
+ await client.run(wf);
188
+ } catch (err) {
189
+ if (err instanceof JobFailed) {
190
+ console.error(err.error); // { code, message, node_id, class_type, traceback } | null
191
+ } else if (err instanceof MissingAsset) {
192
+ console.error("asset reference was not usable:", err.details);
193
+ } else {
194
+ throw err;
195
+ }
196
+ }
197
+ ```
198
+
199
+ ## Two layers
200
+
201
+ - **`@comfyorg/sdk`** — the idiomatic client above: asset dedup/upload,
202
+ `core/ASSET` substitution, idempotent submit with queue-full backoff,
203
+ poll-authoritative job completion, typed SSE events, range-aware
204
+ downloads, and typed errors.
205
+ - **`@comfyorg/sdk/low`** — generated types + [Zod](https://zod.dev) schemas
206
+ plus a hand-written `fetch` transport (`ComfyLow`) with one method per API
207
+ operation and the escape hatches the SDK layer is built on: raw `Response`
208
+ access, unbuffered streaming bodies (for SSE and range downloads), a
209
+ streaming multipart upload body, and per-request `AbortSignal`/timeout.
210
+ Use this directly if you need lower-level control.
211
+
212
+ The generated part of `low` (`src/low/generated/*`) is produced by
213
+ [`@hey-api/openapi-ts`](https://heyapi.dev) from `spec/openapi.yaml`, a
214
+ vendored, filtered copy of the canonical Comfy API v2 contract (see
215
+ `spec/README.md`). Regenerate it with `pnpm generate` after the spec
216
+ changes; CI fails if the generated code has drifted from the spec.
217
+
218
+ ## Development
219
+
220
+ ```bash
221
+ pnpm install --frozen-lockfile
222
+ pnpm lint # oxlint
223
+ pnpm format:check # oxfmt --check
224
+ pnpm typecheck # tsc --noEmit
225
+ pnpm test # vitest run
226
+ pnpm build # tsc -> dist/
227
+ ```
228
+
229
+ Other useful scripts:
230
+
231
+ ```bash
232
+ pnpm generate # regenerate src/low/generated/* from spec/openapi.yaml
233
+ pnpm format # oxfmt --write
234
+ pnpm test:coverage # vitest run --coverage
235
+ pnpm check:spec-drift # fails if src/low/generated/* is stale vs. the spec
236
+ ```
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Comfy SDK — the idiomatic TypeScript client for the Comfy API v2.
3
+ *
4
+ * Runs an API-format workflow against any Comfy API v2 surface (self-hosted
5
+ * ComfyUI through `comfy-api-proxy`, Comfy Cloud, or a serverless
6
+ * deployment) — the only per-surface difference is the base URL and an
7
+ * optional key. This is the `sdk` (idiomatic) layer; the generated
8
+ * types/validators + thin transport live under `@comfyorg/sdk/low` for
9
+ * advanced/escape-hatch use. Behaviorally mirrors the Python SDK
10
+ * (`Comfy-Org/ComfyPythonSDK`), collapsed to one async client (JS is
11
+ * async-native — no sync/async split).
12
+ *
13
+ * ```ts
14
+ * import { Comfy } from "@comfyorg/sdk";
15
+ *
16
+ * const client = new Comfy("http://127.0.0.1:8189"); // local proxy
17
+ * // const client = new Comfy("https://api.comfy.org", { apiKey: "..." }) // Comfy Cloud
18
+ *
19
+ * const wf = await client.workflows.fromFile("workflow_api.json");
20
+ * const asset = client.assets.fromFile("photo.png"); // lazy; uploaded on use
21
+ * wf.setInput("10", "image", asset);
22
+ *
23
+ * const job = await client.run(wf);
24
+ * await job.getOutputs("13")[0].toFile("out.png");
25
+ * ```
26
+ */
27
+ export * from "./sdk/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Comfy SDK — the idiomatic TypeScript client for the Comfy API v2.
3
+ *
4
+ * Runs an API-format workflow against any Comfy API v2 surface (self-hosted
5
+ * ComfyUI through `comfy-api-proxy`, Comfy Cloud, or a serverless
6
+ * deployment) — the only per-surface difference is the base URL and an
7
+ * optional key. This is the `sdk` (idiomatic) layer; the generated
8
+ * types/validators + thin transport live under `@comfyorg/sdk/low` for
9
+ * advanced/escape-hatch use. Behaviorally mirrors the Python SDK
10
+ * (`Comfy-Org/ComfyPythonSDK`), collapsed to one async client (JS is
11
+ * async-native — no sync/async split).
12
+ *
13
+ * ```ts
14
+ * import { Comfy } from "@comfyorg/sdk";
15
+ *
16
+ * const client = new Comfy("http://127.0.0.1:8189"); // local proxy
17
+ * // const client = new Comfy("https://api.comfy.org", { apiKey: "..." }) // Comfy Cloud
18
+ *
19
+ * const wf = await client.workflows.fromFile("workflow_api.json");
20
+ * const asset = client.assets.fromFile("photo.png"); // lazy; uploaded on use
21
+ * wf.setInput("10", "image", asset);
22
+ *
23
+ * const job = await client.run(wf);
24
+ * await job.getOutputs("13")[0].toFile("out.png");
25
+ * ```
26
+ */
27
+ export * from "./sdk/index.js";
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The shared error envelope mapped to a typed exception per `code`.
3
+ *
4
+ * This is the `low` (protocol) view of errors: one class per documented error
5
+ * `code`, plus a fallback. The `sdk` layer re-raises these as its own
6
+ * idiomatic exceptions where it adds value (e.g. `JobFailed` carrying node
7
+ * details), but the protocol codes are defined here so the generated layer
8
+ * has a stable, typed error surface. Mirrors `comfy_low.errors` in the
9
+ * Python SDK.
10
+ */
11
+ export interface ApiErrorOptions {
12
+ code?: string;
13
+ httpStatus: number;
14
+ details?: Record<string, unknown> | null;
15
+ retryAfter?: number | null;
16
+ }
17
+ export declare class ApiError extends Error {
18
+ static readonly code: string;
19
+ readonly code: string;
20
+ readonly httpStatus: number;
21
+ readonly details: Record<string, unknown> | null;
22
+ readonly retryAfter: number | null;
23
+ constructor(message: string, options: ApiErrorOptions);
24
+ }
25
+ export declare class InvalidWorkflow extends ApiError {
26
+ static readonly code = "invalid_workflow";
27
+ }
28
+ export declare class WorkflowFormatUi extends ApiError {
29
+ static readonly code = "workflow_format_ui";
30
+ }
31
+ export declare class MissingAsset extends ApiError {
32
+ static readonly code = "missing_asset";
33
+ }
34
+ export declare class HashMismatch extends ApiError {
35
+ static readonly code = "hash_mismatch";
36
+ }
37
+ export declare class BlobNotFound extends ApiError {
38
+ static readonly code = "blob_not_found";
39
+ }
40
+ export declare class IdempotencyKeyReuse extends ApiError {
41
+ static readonly code = "idempotency_key_reuse";
42
+ }
43
+ export declare class QueueFull extends ApiError {
44
+ static readonly code = "queue_full";
45
+ }
46
+ export declare class InsufficientCredits extends ApiError {
47
+ static readonly code = "insufficient_credits";
48
+ }
49
+ export declare class NotFound extends ApiError {
50
+ static readonly code = "not_found";
51
+ }
52
+ export declare class Unauthorized extends ApiError {
53
+ static readonly code = "unauthorized";
54
+ }
55
+ export declare class Forbidden extends ApiError {
56
+ static readonly code = "forbidden";
57
+ }
58
+ interface ErrorEnvelopeBody {
59
+ error?: {
60
+ code?: string;
61
+ message?: string;
62
+ details?: Record<string, unknown> | null;
63
+ };
64
+ }
65
+ /**
66
+ * Build the typed exception for an error response. Falls back to a
67
+ * status-derived code when the body is missing or not a well-formed
68
+ * envelope, so a bare 401 with no JSON still maps to `Unauthorized`.
69
+ */
70
+ export declare function errorFromEnvelope(httpStatus: number, body: ErrorEnvelopeBody | null | undefined, options?: {
71
+ retryAfter?: number | null;
72
+ }): ApiError;
73
+ export {};
@@ -0,0 +1,104 @@
1
+ /**
2
+ * The shared error envelope mapped to a typed exception per `code`.
3
+ *
4
+ * This is the `low` (protocol) view of errors: one class per documented error
5
+ * `code`, plus a fallback. The `sdk` layer re-raises these as its own
6
+ * idiomatic exceptions where it adds value (e.g. `JobFailed` carrying node
7
+ * details), but the protocol codes are defined here so the generated layer
8
+ * has a stable, typed error surface. Mirrors `comfy_low.errors` in the
9
+ * Python SDK.
10
+ */
11
+ export class ApiError extends Error {
12
+ static code = "error";
13
+ code;
14
+ httpStatus;
15
+ details;
16
+ retryAfter;
17
+ constructor(message, options) {
18
+ super(message);
19
+ this.name = new.target.name;
20
+ this.code = options.code ?? new.target.code;
21
+ this.httpStatus = options.httpStatus;
22
+ this.details = options.details ?? null;
23
+ this.retryAfter = options.retryAfter ?? null;
24
+ }
25
+ }
26
+ export class InvalidWorkflow extends ApiError {
27
+ static code = "invalid_workflow";
28
+ }
29
+ export class WorkflowFormatUi extends ApiError {
30
+ static code = "workflow_format_ui";
31
+ }
32
+ export class MissingAsset extends ApiError {
33
+ static code = "missing_asset";
34
+ }
35
+ export class HashMismatch extends ApiError {
36
+ static code = "hash_mismatch";
37
+ }
38
+ export class BlobNotFound extends ApiError {
39
+ static code = "blob_not_found";
40
+ }
41
+ export class IdempotencyKeyReuse extends ApiError {
42
+ static code = "idempotency_key_reuse";
43
+ }
44
+ export class QueueFull extends ApiError {
45
+ static code = "queue_full";
46
+ }
47
+ export class InsufficientCredits extends ApiError {
48
+ static code = "insufficient_credits";
49
+ }
50
+ export class NotFound extends ApiError {
51
+ static code = "not_found";
52
+ }
53
+ export class Unauthorized extends ApiError {
54
+ static code = "unauthorized";
55
+ }
56
+ export class Forbidden extends ApiError {
57
+ static code = "forbidden";
58
+ }
59
+ const BY_CODE = {
60
+ invalid_workflow: InvalidWorkflow,
61
+ workflow_format_ui: WorkflowFormatUi,
62
+ missing_asset: MissingAsset,
63
+ hash_mismatch: HashMismatch,
64
+ blob_not_found: BlobNotFound,
65
+ idempotency_key_reuse: IdempotencyKeyReuse,
66
+ queue_full: QueueFull,
67
+ insufficient_credits: InsufficientCredits,
68
+ not_found: NotFound,
69
+ unauthorized: Unauthorized,
70
+ forbidden: Forbidden,
71
+ };
72
+ const CODE_BY_STATUS = {
73
+ 401: "unauthorized",
74
+ 402: "insufficient_credits",
75
+ 403: "forbidden",
76
+ 404: "not_found",
77
+ 409: "hash_mismatch",
78
+ 422: "invalid_workflow",
79
+ 429: "queue_full",
80
+ };
81
+ /**
82
+ * Build the typed exception for an error response. Falls back to a
83
+ * status-derived code when the body is missing or not a well-formed
84
+ * envelope, so a bare 401 with no JSON still maps to `Unauthorized`.
85
+ */
86
+ export function errorFromEnvelope(httpStatus, body, options = {}) {
87
+ const err = body && typeof body === "object" ? body.error : undefined;
88
+ let code = err && typeof err === "object" ? err.code : undefined;
89
+ let message = err && typeof err === "object" ? err.message : undefined;
90
+ const details = err && typeof err === "object" ? err.details : undefined;
91
+ if (!code) {
92
+ code = CODE_BY_STATUS[httpStatus] ?? "error";
93
+ }
94
+ if (!message) {
95
+ message = `HTTP ${httpStatus}`;
96
+ }
97
+ const cls = BY_CODE[code] ?? ApiError;
98
+ return new cls(message, {
99
+ code,
100
+ httpStatus,
101
+ details: details && typeof details === "object" ? details : null,
102
+ retryAfter: options.retryAfter ?? null,
103
+ });
104
+ }
@@ -0,0 +1 @@
1
+ export type { Asset, AssetFromHashData, AssetFromHashError, AssetFromHashErrors, AssetFromHashResponse, AssetFromHashResponses, AssetId, BlakeHash, CancelJobData, CancelJobError, CancelJobErrors, CancelJobResponse, CancelJobResponses, ClientOptions, ErrorEnvelope, GetAssetContentData, GetAssetContentError, GetAssetContentErrors, GetAssetContentResponse, GetAssetContentResponses, GetAssetData, GetAssetError, GetAssetErrors, GetAssetResponse, GetAssetResponses, GetJobData, GetJobError, GetJobErrors, GetJobEventsData, GetJobEventsError, GetJobEventsErrors, GetJobEventsResponse, GetJobEventsResponses, GetJobResponse, GetJobResponses, HeadAssetByHashData, HeadAssetByHashError, HeadAssetByHashErrors, HeadAssetByHashResponses, IdempotencyKey, Job, JobError, JobId, JobStatus, JobUrls, Output, OutputType, PostAssetsData, PostAssetsError, PostAssetsErrors, PostAssetsResponse, PostAssetsResponses, PostJobsData, PostJobsError, PostJobsErrors, PostJobsResponse, PostJobsResponses, Progress } from './types.gen.js';
@@ -0,0 +1,2 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+ export {};