chutes-js 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,310 +1,555 @@
1
- # chutes-js
2
-
3
- A lightweight, functional JavaScript SDK for consuming [Chutes.ai](https://chutes.ai) APIs.
4
-
5
- - **Zero dependencies** – Built on native `fetch` and `AsyncGenerator`
6
- - **Streaming support** – First-class SSE parsing for chat/LLM responses
7
- - **Universal** – Works in Node.js 18+, Cloudflare Workers, and browsers
8
-
9
- ## Installation
10
-
11
- ```bash
12
- npm install chutes-js
13
- ```
14
-
15
- ## Quick Start
16
-
17
- ```javascript
18
- import { createClient, saveBlob } from 'chutes-js';
19
-
20
- const client = createClient({ apiKey: process.env.CHUTES_API_KEY });
21
-
22
- // 1. Chat Completion (uses llm.chutes.ai)
23
- const response = await client.chat({
24
- model: 'zai-org/GLM-4.7-TEE',
25
- messages: [{ role: 'user', content: 'Hello!' }]
26
- });
27
- console.log(response.choices[0].message.content);
28
-
29
- // 2. Image Generation (uses image.chutes.ai)
30
- const blob = await client.image({
31
- model: 'qwen-image',
32
- prompt: 'A beautiful sunset'
33
- });
34
-
35
- // 3. Video Generation (Hybrid: supports both Sync and Async)
36
- const result = await client.video({
37
- model: 'wan-2-2-i2v-14b-fast',
38
- prompt: 'A cat playing piano',
39
- image: 'base64_data_here...'
40
- });
41
-
42
- // Check if we got a Blob (sync) or a Job ID (async)
43
- if (result instanceof Blob) {
44
- await saveBlob(result, './video.mp4');
45
- } else {
46
- // We got a Job ID, poll for status
47
- const status = await client.getJobStatus(result.job_id);
48
- console.log('Job Status:', status.state);
49
- }
50
- ```
51
-
52
- ## API Reference
53
-
54
- ### `createClient(config)`
55
-
56
- Creates a new Chutes client.
57
-
58
- | Option | Type | Default | Description |
59
- |--------|------|---------|-------------|
60
- | `apiKey` | `string` | *required* | Your Chutes API key |
61
- | `timeout` | `number` | `60000` | Default timeout in ms (Note: Video/Audio have higher defaults) |
62
-
63
- > [!TIP]
64
- > You can access `client.endpoints` to see the base URLs being used by the client.
65
-
66
- ---
67
-
68
- ### LLM Methods (via `llm.chutes.ai`)
69
-
70
- #### `client.chat(options)`
71
-
72
- OpenAI-compatible chat completion.
73
-
74
- ```javascript
75
- const response = await client.chat({
76
- model: 'zai-org/GLM-4.7-TEE',
77
- messages: [{ role: 'user', content: 'Hello!' }]
78
- });
79
- ```
80
-
81
- #### `client.chatStream(options)`
82
-
83
- Streaming chat completion. Returns an async generator.
84
-
85
- ```javascript
86
- for await (const chunk of client.chatStream({ model, messages })) {
87
- console.log(chunk.choices[0]?.delta?.content);
88
- }
89
- ```
90
-
91
- ### Image Methods (via `image.chutes.ai`)
92
-
93
- #### `client.image(options)`
94
-
95
- Generate an image.
96
-
97
- ```javascript
98
- const blob = await client.image({
99
- model: 'qwen-image',
100
- prompt: 'A beautiful sunset over mountains'
101
- });
102
-
103
- // Save to file (Node.js)
104
- import { saveBlob } from 'chutes-js';
105
- await saveBlob(blob, './output.png');
106
- ```
107
-
108
- > [!IMPORTANT]
109
- > `saveBlob` is a Node.js utility. When using the SDK in browsers or Cloudflare Workers, handle the `Blob` response using native platform APIs.
110
-
111
- | Option | Type | Default | Description |
112
- |--------|------|---------|-------------|
113
- | `model` | `string` | *required* | Model ID (e.g., `qwen-image`) |
114
- | `prompt` | `string` | *required* | Image generation prompt |
115
- | `width` | `number` | `1024` | Image width |
116
- | `height` | `number` | `1024` | Image height |
117
- | `guidance_scale` | `number` | `7.5` | Guidance scale |
118
- | `num_inference_steps` | `number` | `50` | Inference steps |
119
-
120
- ---
121
-
122
- ### Video Methods (via `chutes-{model}.chutes.ai`)
123
-
124
- #### `client.video(options)`
125
-
126
- Generate a video. I2V (Image-to-Video) models require a base64 image input.
127
-
128
- ```javascript
129
- import { readFileSync } from 'fs';
130
-
131
- // For I2V models, provide a base64 image
132
- const imageBase64 = readFileSync('./input.png').toString('base64');
133
-
134
- const result = await client.video({
135
- model: 'wan-2-2-i2v-14b-fast',
136
- prompt: 'A cat playing piano',
137
- image: imageBase64,
138
- resolution: '480p',
139
- fps: 16,
140
- frames: 81
141
- });
142
-
143
- if (result instanceof Blob) {
144
- // 1. Synchronous: Video returned directly
145
- await saveBlob(result, './output.mp4');
146
- } else {
147
- // 2. Asynchronous: Job ID returned
148
- console.log('Job started:', result.job_id);
149
- }
150
- ```
151
-
152
- | Option | Type | Default | Description |
153
- |--------|------|---------|-------------|
154
- | `model` | `string` | *required* | Model slug (e.g., `wan-2-2-i2v-14b-fast`) |
155
- | `prompt` | `string` | *required* | Video generation prompt |
156
- | `image` | `string` | - | Base64 image (required for I2V models) |
157
- | `resolution` | `string` | `'480p'` | Video resolution |
158
- | `fps` | `number` | `16` | Frames per second |
159
- | `frames` | `number` | `81` | Number of frames |
160
- | `seed` | `number` | - | Random seed for reproducibility |
161
- | `fast` | `boolean` | `true` | Use fast generation mode |
162
- | `guidance_scale` | `number` | `1` | Guidance scale |
163
- | `guidance_scale_2` | `number` | `1` | Secondary guidance scale |
164
- | `negative_prompt` | `string` | - | Negative prompt |
165
-
166
- > [!NOTE]
167
- > Video generation has a default timeout of **5 minutes** (300,000ms).
168
-
169
- > **Note**: All methods accept additional parameters via spread (`...extra`) for model-specific options.
170
-
171
- ---
172
-
173
- ### Audio Methods (via `chutes-{model}.chutes.ai/speak`)
174
-
175
- #### `client.audio(options)`
176
-
177
- Generate audio (Text-to-Speech). Supported parameters vary by model.
178
-
179
- ```javascript
180
- // Example for CSM-1B model
181
- const audio1 = await client.audio({
182
- model: 'csm-1b',
183
- text: 'Hello world!',
184
- speaker: 1,
185
- max_duration_ms: 10000
186
- });
187
-
188
- // Example for Kokoro model
189
- const audio2 = await client.audio({
190
- model: 'kokoro',
191
- text: 'Hello world!',
192
- voice: 'af_heart',
193
- speed: 1.0
194
- });
195
-
196
- await saveBlob(audio2, './output.wav');
197
- ```
198
-
199
- | Option | Type | Default | Description |
200
- |--------|------|---------|-------------|
201
- | `model` | `string` | *required* | Model slug (e.g., `kokoro`, `csm-1b`) |
202
- | `text` | `string` | *required* | Text to speak |
203
- | `speaker` | `number` | - | Speaker ID (CSM models) |
204
- | `max_duration_ms` | `number` | - | Max duration in ms (CSM models) |
205
- | `voice` | `string` | - | Voice ID (Kokoro models) |
206
- | `speed` | `number` | `1.0` | Speaking speed (Kokoro models) |
207
-
208
- > [!NOTE]
209
- > Audio generation has a default timeout of **2 minutes** (120,000ms).
210
-
211
- ---
212
-
213
- ### Invoke Methods (subdomain-based chutes)
214
-
215
- For models using subdomain URLs (`chutes-{model}.chutes.ai`) not covered by built-in methods.
216
-
217
- > **Note**: Some image models use subdomain URLs instead of `image.chutes.ai`. Use `invoke()` for these.
218
- >
219
- > `invoke()` returns a `Blob` if the `Content-Type` is an image, `JSON` if it's `application/json`, or `string` otherwise.
220
-
221
- #### `client.invoke(target, path, payload)`
222
-
223
- ```javascript
224
- // Pattern: https://{name}-{username}.chutes.ai/{path}
225
-
226
- // Example 1: Subdomain image model (Hunyuan)
227
- const image = await client.invoke(
228
- { name: 'hunyuan-image-3', username: 'chutes' },
229
- '/generate',
230
- { prompt: 'A dog running on grass', size: '1024x1024' }
231
- );
232
-
233
- // Example 2: Subdomain image model (HiDream)
234
- const image2 = await client.invoke(
235
- { name: 'hidream', username: 'chutes' },
236
- '/generate',
237
- { prompt: 'Cyberpunk city', resolution: '1024x1024', guidance_scale: 5 }
238
- );
239
-
240
- // Example 3: Text-to-Video (Wan 2.1)
241
- const video = await client.invoke(
242
- { name: 'wan2-1-14b', username: 'chutes' },
243
- '/text2video',
244
- { prompt: 'Ocean waves crashing', fps: 24, frames: 81 }
245
- );
246
- ```
247
-
248
- #### `client.invokeStream(target, path, payload)`
249
-
250
- For streaming responses from custom chutes. Returns an `AsyncGenerator`.
251
-
252
- #### `parseSSE(stream)`
253
-
254
- The internal SSE parser is exported for custom streaming implementations.
255
-
256
- ---
257
-
258
- ### Job Methods (via `api.chutes.ai`)
259
-
260
- #### `client.getJobStatus(jobId)`
261
-
262
- Check status of a long-running job.
263
-
264
- ```javascript
265
- const status = await client.getJobStatus('job_abc123');
266
- // { state: 'completed', result: {...} }
267
- ```
268
-
269
- #### `client.deleteJob(jobId)`
270
-
271
- Cancel/delete a job.
272
-
273
- ---
274
-
275
- ## Available Models
276
-
277
- This SDK supports **all models** available on Chutes.ai. Below are some examples:
278
-
279
- | Type | Example Model | Method | Notes |
280
- |------|---------------|--------|-------|
281
- | LLM | `zai-org/GLM-4.7-TEE` | `chat()` / `chatStream()` | OpenAI-compatible |
282
- | Image | `qwen-image`, `FLUX.1-dev` | `image()` | Text-to-image |
283
- | Image | `hunyuan-image-3`, `hidream` | `invoke()` | Subdomain models |
284
- | Video | `wan-2-2-i2v-14b-fast` | `video()` | Image-to-video |
285
- | Video | `wan2.1-14b` | `invoke()` | Text-to-video |
286
- | Audio | `kokoro`, `csm-1b` | `audio()` | Text-to-speech |
287
-
288
- > **Tip**: Use `image()`, `video()`, and `audio()` for common models. Use `invoke()` for any model with a subdomain URL pattern.
289
-
290
- Browse all models at [chutes.ai/app](https://chutes.ai/app)
291
-
292
-
293
- ## Error Handling
294
-
295
- ```javascript
296
- import { createClient, ChutesError } from 'chutes-js';
297
-
298
- try {
299
- await client.chat({ ... });
300
- } catch (e) {
301
- if (e instanceof ChutesError) {
302
- console.log('Status:', e.status); // 429 = rate limited
303
- console.log('Body:', e.body); // Raw error response
304
- }
305
- }
306
- ```
307
-
308
- ## License
309
-
310
- MIT
1
+ # chutes-js
2
+
3
+ A lightweight, functional JavaScript SDK for consuming [Chutes.ai](https://chutes.ai) APIs.
4
+
5
+ - **Zero dependencies** – Built on native `fetch` and `AsyncGenerator`
6
+ - **Streaming support** – First-class SSE parsing for chat/LLM responses
7
+ - **Universal** – Works in Node.js 18+, Cloudflare Workers, and browsers
8
+ - **Unified API** – Normalized parameters across all models with auto-translation
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install chutes-js
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```javascript
19
+ import { createClient, saveBlob } from 'chutes-js';
20
+
21
+ const client = createClient({ apiKey: process.env.CHUTES_API_KEY });
22
+
23
+ // 1. Chat Completion (OpenAI-compatible)
24
+ const response = await client.chat({
25
+ model: 'deepseek-ai/DeepSeek-V3-0324',
26
+ messages: [{ role: 'user', content: 'Hello!' }]
27
+ });
28
+ console.log(response.choices[0].message.content);
29
+
30
+ // 2. Image Generation (unified params)
31
+ const image = await client.image({
32
+ model: 'flux', // alias for FLUX.1-schnell
33
+ prompt: 'A beautiful sunset over mountains',
34
+ aspectRatio: '16:9', // auto-converted to width/height
35
+ steps: 25,
36
+ cfgScale: 7
37
+ });
38
+ await saveBlob(image, './sunset.png');
39
+
40
+ // 3. Video Generation (I2V with URL auto-fetch)
41
+ const video = await client.video({
42
+ model: 'wan', // alias for wan-2-2-i2v-14b-fast
43
+ prompt: 'A cat playing piano smoothly',
44
+ image: 'https://example.com/cat.jpg', // URL auto-fetched to base64
45
+ duration: 5, // seconds → frames via fps
46
+ aspectRatio: '16:9'
47
+ });
48
+ await saveBlob(video, './cat-piano.mp4');
49
+
50
+ // 4. Audio Generation (Text-to-Speech)
51
+ const audio = await client.audio({
52
+ model: 'tts', // alias for kokoro
53
+ text: 'Hello, welcome to Chutes!',
54
+ voice: 'af_heart',
55
+ speed: 1.0
56
+ });
57
+ await saveBlob(audio, './welcome.wav');
58
+ ```
59
+
60
+ ## API Reference
61
+
62
+ ### `createClient(config)`
63
+
64
+ Creates a new Chutes client.
65
+
66
+ | Option | Type | Default | Description |
67
+ |--------|------|---------|-------------|
68
+ | `apiKey` | `string` | *required* | Your Chutes API key |
69
+ | `timeout` | `number` | `60000` | Default timeout in ms (Video: 5min, Audio: 2min) |
70
+
71
+ > [!TIP]
72
+ > You can access `client.endpoints` to see the base URLs being used by the client.
73
+
74
+ ---
75
+
76
+ ### LLM Methods (via `llm.chutes.ai`)
77
+
78
+ #### `client.chat(options)`
79
+
80
+ OpenAI-compatible chat completion.
81
+
82
+ ```javascript
83
+ const response = await client.chat({
84
+ model: 'deepseek-ai/DeepSeek-V3-0324',
85
+ messages: [{ role: 'user', content: 'Explain quantum computing' }]
86
+ });
87
+ ```
88
+
89
+ #### `client.chatStream(options)`
90
+
91
+ Streaming chat completion. Returns an async generator.
92
+
93
+ ```javascript
94
+ for await (const chunk of client.chatStream({ model, messages })) {
95
+ process.stdout.write(chunk.choices[0]?.delta?.content || '');
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ### Image Methods
102
+
103
+ The SDK provides a **unified API** for image generation. Parameters are automatically translated to each model's native format.
104
+
105
+ #### `client.image(options)`
106
+
107
+ Generate an image using unified parameters.
108
+
109
+ ```javascript
110
+ import { saveBlob } from 'chutes-js';
111
+
112
+ // Basic usage
113
+ const blob = await client.image({
114
+ model: 'flux',
115
+ prompt: 'A cyberpunk city at night'
116
+ });
117
+ await saveBlob(blob, './cyberpunk.png');
118
+
119
+ // With all options
120
+ const blob2 = await client.image({
121
+ model: 'qwen-image',
122
+ prompt: 'A serene Japanese garden',
123
+ aspectRatio: '16:9', // or use width/height directly
124
+ steps: 50,
125
+ cfgScale: 7.5,
126
+ negativePrompt: 'blurry, low quality',
127
+ seed: 42
128
+ });
129
+
130
+ // Image editing (requires reference images)
131
+ const edited = await client.image({
132
+ model: 'qwen-edit',
133
+ prompt: 'Add a rainbow to the sky',
134
+ images: ['https://example.com/photo.jpg'], // URLs auto-fetched
135
+ aspectRatio: '1:1'
136
+ });
137
+ ```
138
+
139
+ > [!IMPORTANT]
140
+ > `saveBlob` is a Node.js utility. In browsers or Cloudflare Workers, handle the `Blob` using platform APIs.
141
+
142
+ #### Parameters
143
+
144
+ | Parameter | Type | Description |
145
+ |-----------|------|-------------|
146
+ | `model` | `string` | **Required.** Model ID or alias (e.g., `'flux'`, `'qwen-image'`, `'hidream'`) |
147
+ | `prompt` | `string` | **Required.** Image generation prompt |
148
+ | `aspectRatio` | `string` | Aspect ratio (e.g., `'16:9'`, `'1:1'`, `'9:16'`). Auto-converts to width/height. Conflicts with `width`/`height`. |
149
+ | `width` | `number` | Image width in pixels (default: 1024) |
150
+ | `height` | `number` | Image height in pixels (default: 1024) |
151
+ | `steps` | `number` | Number of inference steps (default varies by model: 25-50) |
152
+ | `cfgScale` | `number` | Guidance scale (default varies by model: 4-7.5) |
153
+ | `negativePrompt` | `string` | Negative prompt for content to avoid |
154
+ | `seed` | `number\|null` | Random seed for reproducibility |
155
+ | `images` | `string\|string[]` | Reference images for editing models (base64 or URL). URLs are auto-fetched. |
156
+
157
+ #### Alternative: Using `invoke()` for Raw API Access
158
+
159
+ For direct API access without parameter normalization:
160
+
161
+ ```javascript
162
+ // Subdomain model (HiDream)
163
+ const image = await client.invoke(
164
+ { name: 'hidream', username: 'chutes' },
165
+ '/generate',
166
+ { prompt: 'Cyberpunk city', resolution: '1024x1024', guidance_scale: 5 }
167
+ );
168
+
169
+ // Centralized model (requires model in payload)
170
+ const image2 = await client.invoke(
171
+ 'image.chutes.ai',
172
+ '/generate',
173
+ { model: 'qwen-image', prompt: 'A sunset', width: 1024, height: 1024 }
174
+ );
175
+ ```
176
+
177
+ <details>
178
+ <summary><strong>Supported Image Models (18 models)</strong></summary>
179
+
180
+ #### Centralized API Models (`image.chutes.ai`)
181
+
182
+ | Model | Aliases | Notes |
183
+ |-------|---------|-------|
184
+ | `qwen-image` | `qwen` | Qwen image generation |
185
+ | `Qwen-Image-2512` | `qwen-2512` | Qwen 2512 variant |
186
+ | `FLUX.1-schnell` | `flux`, `flux-schnell` | Fast FLUX model |
187
+ | `JuggernautXL` | `juggernaut` | Juggernaut XL |
188
+ | `JuggernautXL-Ragnarok` | `juggernaut-ragnarok` | Ragnarok variant |
189
+ | `iLustMix` | - | Illustration style |
190
+ | `chroma` | - | Chroma model |
191
+ | `Illustrij` | - | Illustration focused |
192
+ | `Animij` | - | Anime style |
193
+ | `HassakuXL` | - | Hassaku XL |
194
+ | `NovaFurryXL` | - | Furry art style |
195
+ | `stabilityai/stable-diffusion-xl-base-1.0` | `sdxl` | Stable Diffusion XL |
196
+ | `Lykon/dreamshaper-xl-1-0` | `dreamshaper` | DreamShaper XL |
197
+ | `diagonalge/Booba` | - | Community model |
198
+ | `diagonalge/ConstShaper` | - | Community model |
199
+
200
+ #### Subdomain API Models
201
+
202
+ | Model | Aliases | Notes |
203
+ |-------|---------|-------|
204
+ | `hidream` | - | HiDream (uses resolution enum) |
205
+ | `hunyuan-image-3` | `hunyuan` | Hunyuan Image 3 (uses size string) |
206
+ | `z-image-turbo` | `z-turbo` | Z-Image Turbo (fast generation) |
207
+
208
+ #### Image Editing Models (require `images` parameter)
209
+
210
+ | Model | Aliases | Notes |
211
+ |-------|---------|-------|
212
+ | `Qwen-Image-Edit-2511` | `qwen-edit-2511` | Qwen image editing (latest) |
213
+ | `qwen-image-edit-2509` | `qwen-edit` | Qwen image editing |
214
+
215
+ </details>
216
+
217
+ ---
218
+
219
+ ### Video Methods
220
+
221
+ Generate videos with unified parameters. The SDK handles image URL fetching and frame calculation automatically.
222
+
223
+ #### `client.video(options)`
224
+
225
+ Generate a video using unified parameters.
226
+
227
+ ```javascript
228
+ import { readFileSync } from 'fs';
229
+ import { saveBlob } from 'chutes-js';
230
+
231
+ // Using image URL (auto-fetched to base64)
232
+ const video = await client.video({
233
+ model: 'wan', // alias for wan-2-2-i2v-14b-fast
234
+ prompt: 'A cat playing piano elegantly',
235
+ image: 'https://example.com/cat.jpg', // URL auto-fetched
236
+ duration: 5, // 5 seconds
237
+ aspectRatio: '16:9'
238
+ });
239
+ await saveBlob(video, './output.mp4');
240
+
241
+ // Using local file (base64)
242
+ const imageBase64 = readFileSync('./input.png').toString('base64');
243
+ const video2 = await client.video({
244
+ model: 'i2v',
245
+ prompt: 'Ocean waves crashing on rocks',
246
+ image: imageBase64,
247
+ frames: 81, // or use duration in seconds
248
+ fps: 16,
249
+ cfgScale: 1,
250
+ cfgScale2: 1,
251
+ negativePrompt: 'blurry, static',
252
+ seed: 12345
253
+ });
254
+
255
+ // Check for async job (some models return job ID)
256
+ if (video2 instanceof Blob) {
257
+ await saveBlob(video2, './ocean.mp4');
258
+ } else {
259
+ console.log('Job started:', video2.job_id);
260
+ // Poll with client.getJobStatus(video2.job_id)
261
+ }
262
+ ```
263
+
264
+ #### Parameters
265
+
266
+ | Parameter | Type | Description |
267
+ |-----------|------|-------------|
268
+ | `model` | `string` | **Required.** Model ID or alias (e.g., `'wan'`, `'i2v'`) |
269
+ | `prompt` | `string` | **Required.** Video generation prompt |
270
+ | `image` | `string` | **Required.** Reference image (base64 or URL). URLs are auto-fetched. |
271
+ | `aspectRatio` | `string` | Aspect ratio, converts to resolution (e.g., `'16:9'` → `'480p'`) |
272
+ | `resolution` | `string` | Video resolution (`'480p'`, `'720p'`) |
273
+ | `duration` | `number` | Duration in seconds. Converted to frames via fps. Conflicts with `frames`. |
274
+ | `frames` | `number` | Number of frames (default: 81, range: 21-140) |
275
+ | `fps` | `number` | Frames per second (default: 16, range: 16-24) |
276
+ | `cfgScale` | `number` | Primary guidance scale (default: 1) |
277
+ | `cfgScale2` | `number` | Secondary guidance scale (default: 1) |
278
+ | `negativePrompt` | `string` | Negative prompt (has sensible default) |
279
+ | `seed` | `number\|null` | Random seed for reproducibility |
280
+ | `fast` | `boolean` | Use fast generation mode (default: true) |
281
+
282
+ > [!NOTE]
283
+ > Video generation has a default timeout of **5 minutes** (300,000ms).
284
+
285
+ #### Alternative: Using `invoke()` for Raw API Access
286
+
287
+ ```javascript
288
+ const video = await client.invoke(
289
+ { name: 'wan-2-2-i2v-14b-fast', username: 'chutes' },
290
+ '/generate',
291
+ {
292
+ prompt: 'A dog running',
293
+ image: imageBase64,
294
+ resolution: '480p',
295
+ fps: 16,
296
+ frames: 81,
297
+ guidance_scale: 1,
298
+ guidance_scale_2: 1
299
+ }
300
+ );
301
+ ```
302
+
303
+ <details>
304
+ <summary><strong>Supported Video Models (1 model)</strong></summary>
305
+
306
+ | Model | Aliases | Type | Notes |
307
+ |-------|---------|------|-------|
308
+ | `wan-2-2-i2v-14b-fast` | `wan`, `i2v`, `wan-i2v` | Image-to-Video | Requires reference image |
309
+
310
+ </details>
311
+
312
+ ---
313
+
314
+ ### Audio Methods
315
+
316
+ Generate audio (Text-to-Speech) with unified parameters.
317
+
318
+ #### `client.audio(options)`
319
+
320
+ Generate audio using unified parameters.
321
+
322
+ ```javascript
323
+ import { saveBlob } from 'chutes-js';
324
+
325
+ // Kokoro TTS (50+ voices)
326
+ const audio = await client.audio({
327
+ model: 'tts', // alias for kokoro
328
+ text: 'Hello, welcome to Chutes AI!',
329
+ voice: 'af_heart', // American female
330
+ speed: 1.0
331
+ });
332
+ await saveBlob(audio, './welcome.wav');
333
+
334
+ // CSM-1B (conversational)
335
+ const audio2 = await client.audio({
336
+ model: 'csm',
337
+ text: 'This is a test of the CSM model.',
338
+ speaker: 0,
339
+ maxDuration: 15 // 15 seconds (auto-converted to ms)
340
+ });
341
+ await saveBlob(audio2, './csm-test.wav');
342
+ ```
343
+
344
+ #### Parameters
345
+
346
+ **Common:**
347
+
348
+ | Parameter | Type | Description |
349
+ |-----------|------|-------------|
350
+ | `model` | `string` | **Required.** Model ID or alias (e.g., `'tts'`, `'kokoro'`, `'csm'`) |
351
+ | `text` | `string` | **Required.** Text to speak |
352
+
353
+ **Kokoro-specific:**
354
+
355
+ | Parameter | Type | Description |
356
+ |-----------|------|-------------|
357
+ | `voice` | `string` | Voice ID (default: `'af_heart'`). See voice list below. |
358
+ | `speed` | `number` | Playback speed (default: 1.0, range: 0.1-3.0) |
359
+
360
+ **CSM-specific:**
361
+
362
+ | Parameter | Type | Description |
363
+ |-----------|------|-------------|
364
+ | `speaker` | `number` | Speaker ID (0 or 1) |
365
+ | `maxDuration` | `number` | Max duration in **seconds** (auto-converted to ms) |
366
+ | `maxDurationMs` | `number` | Max duration in milliseconds directly |
367
+ | `context` | `array` | Conversation context for multi-turn |
368
+
369
+ > [!NOTE]
370
+ > Audio generation has a default timeout of **2 minutes** (120,000ms).
371
+
372
+ #### Alternative: Using `invoke()` for Raw API Access
373
+
374
+ ```javascript
375
+ // Kokoro via invoke
376
+ const audio = await client.invoke(
377
+ { name: 'kokoro', username: 'chutes' },
378
+ '/speak',
379
+ { text: 'Hello world', voice: 'af_heart', speed: 1.0 }
380
+ );
381
+
382
+ // CSM via invoke
383
+ const audio2 = await client.invoke(
384
+ { name: 'csm-1b', username: 'chutes' },
385
+ '/speak',
386
+ { text: 'Hello', speaker: 0, max_duration_ms: 10000 }
387
+ );
388
+ ```
389
+
390
+ <details>
391
+ <summary><strong>Supported Audio Models (2 models)</strong></summary>
392
+
393
+ | Model | Aliases | Notes |
394
+ |-------|---------|-------|
395
+ | `kokoro` | `tts` | 50+ voices, fast TTS |
396
+ | `csm-1b` | `csm` | Conversational speech model |
397
+
398
+ </details>
399
+
400
+ <details>
401
+ <summary><strong>Kokoro Voice List (50+ voices)</strong></summary>
402
+
403
+ **American English - Female (`af_*`)**
404
+ - `af_heart` (default), `af_alloy`, `af_aoede`, `af_bella`, `af_jessica`, `af_kore`, `af_nicole`, `af_nova`, `af_river`, `af_sarah`, `af_sky`
405
+
406
+ **American English - Male (`am_*`)**
407
+ - `am_adam`, `am_echo`, `am_eric`, `am_fenrir`, `am_liam`, `am_michael`, `am_onyx`, `am_puck`, `am_santa`
408
+
409
+ **British English - Female (`bf_*`)**
410
+ - `bf_alice`, `bf_emma`, `bf_isabella`, `bf_lily`
411
+
412
+ **British English - Male (`bm_*`)**
413
+ - `bm_daniel`, `bm_fable`, `bm_george`, `bm_lewis`
414
+
415
+ **Spanish (`ef_*`, `em_*`)**
416
+ - `ef_dora`, `em_alex`, `em_santa`
417
+
418
+ **French (`ff_*`)**
419
+ - `ff_siwis`
420
+
421
+ **Hindi (`hf_*`, `hm_*`)**
422
+ - `hf_alpha`, `hf_beta`, `hm_omega`, `hm_psi`
423
+
424
+ **Italian (`if_*`, `im_*`)**
425
+ - `if_sara`, `im_nicola`
426
+
427
+ **Japanese (`jf_*`, `jm_*`)**
428
+ - `jf_alpha`, `jf_gongitsune`, `jf_nezumi`, `jf_tebukuro`, `jm_kumo`
429
+
430
+ **Portuguese (`pf_*`, `pm_*`)**
431
+ - `pf_dora`, `pm_alex`, `pm_santa`
432
+
433
+ **Chinese (`zf_*`, `zm_*`)**
434
+ - `zf_xiaobei`, `zf_xiaoni`, `zf_xiaoxiao`, `zf_xiaoyi`, `zm_yunjian`, `zm_yunxi`, `zm_yunxia`, `zm_yunyang`
435
+
436
+ </details>
437
+
438
+ ---
439
+
440
+ ### Invoke Methods (Advanced)
441
+
442
+ For models not covered by built-in methods, or when you need raw API access.
443
+
444
+ #### `client.invoke(target, path, payload)`
445
+
446
+ ```javascript
447
+ // Pattern: https://{name}-{username}.chutes.ai/{path}
448
+
449
+ // Subdomain model
450
+ const result = await client.invoke(
451
+ { name: 'custom-model', username: 'myuser' },
452
+ '/generate',
453
+ { prompt: 'Hello', ...otherParams }
454
+ );
455
+
456
+ // Direct URL
457
+ const result2 = await client.invoke(
458
+ 'https://custom-endpoint.chutes.ai',
459
+ '/api/v1/generate',
460
+ { prompt: 'Hello' }
461
+ );
462
+ ```
463
+
464
+ Returns: `Blob` (if image/video/audio), `Object` (if JSON), or `string` otherwise.
465
+
466
+ #### `client.invokeStream(target, path, payload)`
467
+
468
+ For streaming responses. Returns an `AsyncGenerator`.
469
+
470
+ #### `parseSSE(stream)`
471
+
472
+ The internal SSE parser is exported for custom streaming implementations.
473
+
474
+ ---
475
+
476
+ ### Job Methods (via `api.chutes.ai`)
477
+
478
+ For long-running async jobs.
479
+
480
+ #### `client.getJobStatus(jobId)`
481
+
482
+ ```javascript
483
+ const status = await client.getJobStatus('job_abc123');
484
+ // { state: 'completed', result: {...} }
485
+ ```
486
+
487
+ #### `client.deleteJob(jobId)`
488
+
489
+ Cancel or delete a job.
490
+
491
+ ---
492
+
493
+ ## Error Handling
494
+
495
+ ```javascript
496
+ import { createClient, ChutesError, ValidationError } from 'chutes-js';
497
+
498
+ try {
499
+ await client.image({
500
+ model: 'flux',
501
+ prompt: 'A sunset',
502
+ steps: 500 // exceeds max
503
+ });
504
+ } catch (e) {
505
+ if (e instanceof ValidationError) {
506
+ // Parameter validation failed
507
+ console.log('Validation error:', e.message);
508
+ // e.g., "steps exceeds maximum value of 100"
509
+ } else if (e instanceof ChutesError) {
510
+ // API error
511
+ console.log('Status:', e.status); // 429 = rate limited
512
+ console.log('Body:', e.body); // Raw error response
513
+ }
514
+ }
515
+ ```
516
+
517
+ | Error Class | When |
518
+ |-------------|------|
519
+ | `ValidationError` | Invalid parameters (missing required, out of range, conflicts) |
520
+ | `ChutesError` | API returned an error (auth, rate limit, server error) |
521
+
522
+ ---
523
+
524
+ ## Exports
525
+
526
+ ```javascript
527
+ import {
528
+ // Client
529
+ createClient,
530
+
531
+ // Errors
532
+ ChutesError,
533
+ ValidationError,
534
+
535
+ // Utilities
536
+ parseSSE,
537
+ saveBlob,
538
+
539
+ // Model configs (advanced)
540
+ IMAGE_MODELS,
541
+ IMAGE_MODEL_ALIASES,
542
+ VIDEO_MODELS,
543
+ VIDEO_MODEL_ALIASES,
544
+ AUDIO_MODELS,
545
+ AUDIO_MODEL_ALIASES,
546
+ ALL_MODELS,
547
+ ALL_ALIASES
548
+ } from 'chutes-js';
549
+ ```
550
+
551
+ ---
552
+
553
+ ## License
554
+
555
+ MIT