wavespeed 0.2.1 → 0.2.3

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
@@ -18,6 +18,10 @@
18
18
 
19
19
  ---
20
20
 
21
+ ## Introduction
22
+
23
+ **WaveSpeedAI** JavaScript/TypeScript SDK — Official JS/TS SDK for **WaveSpeedAI** inference platform. This library offers a clean, unified, and high-performance API for your applications.
24
+
21
25
  ## Installation
22
26
 
23
27
  ```bash
@@ -109,6 +113,22 @@ const url = await wavespeed.upload("/path/to/image.png");
109
113
  console.log(url);
110
114
  ```
111
115
 
116
+ ### Getting Task ID and Debug Information
117
+
118
+ If you need access to the task ID for logging, tracking, or debugging, use `runNoThrow()` instead of `run()`. This method returns detailed information and does not throw exceptions:
119
+
120
+ ```javascript
121
+ const result = await client.runNoThrow(model, input);
122
+
123
+ if (result.outputs) {
124
+ console.log("Success:", result.outputs);
125
+ console.log("Task ID:", result.detail.taskId); // For tracking/debugging
126
+ } else {
127
+ console.log("Failed:", result.detail.error);
128
+ console.log("Task ID:", result.detail.taskId); // Still available on failure
129
+ }
130
+ ```
131
+
112
132
  ## Running Tests
113
133
 
114
134
  ```bash
@@ -10,6 +10,23 @@ export interface RunOptions {
10
10
  enableSyncMode?: boolean;
11
11
  maxRetries?: number;
12
12
  }
13
+ /**
14
+ * Detail information for runNoThrow result.
15
+ */
16
+ export interface RunDetail {
17
+ taskId: string;
18
+ status: 'completed' | 'failed';
19
+ model: string;
20
+ error?: string;
21
+ createdAt?: string;
22
+ }
23
+ /**
24
+ * Result interface for runNoThrow method.
25
+ */
26
+ export interface RunNoThrowResult {
27
+ outputs: any[] | null;
28
+ detail: RunDetail;
29
+ }
13
30
  /**
14
31
  * WaveSpeed API client.
15
32
  *
@@ -132,6 +149,38 @@ export declare class Client {
132
149
  * Error: If the prediction times out.
133
150
  */
134
151
  run(model: string, input?: Record<string, any>, options?: RunOptions): Promise<Record<string, any>>;
152
+ /**
153
+ * Run a model and wait for the output (no-throw version).
154
+ *
155
+ * This method is similar to run() but does not throw exceptions.
156
+ * Instead, it returns a result object with outputs (null on failure) and detail information.
157
+ * The detail object always contains the taskId, which is useful for debugging and tracking.
158
+ *
159
+ * Args:
160
+ * model: Model identifier (e.g., "wavespeed-ai/flux-dev").
161
+ * input: Input parameters for the model.
162
+ * options.timeout: Maximum time to wait for completion (undefined = no timeout).
163
+ * options.pollInterval: Interval between status checks in seconds.
164
+ * options.enableSyncMode: If true, use synchronous mode (single request).
165
+ * options.maxRetries: Maximum task-level retries (overrides client setting).
166
+ *
167
+ * Returns:
168
+ * Object containing:
169
+ * - outputs: Array of model outputs (null if failed)
170
+ * - detail: Object with taskId, status, error (if any), and other metadata
171
+ *
172
+ * Example:
173
+ * const result = await client.runNoThrow("wavespeed-ai/z-image/turbo", { prompt: "Cat" });
174
+ *
175
+ * if (result.outputs) {
176
+ * console.log("Success:", result.outputs);
177
+ * console.log("Task ID:", result.detail.taskId);
178
+ * } else {
179
+ * console.log("Failed:", result.detail.error);
180
+ * console.log("Task ID:", result.detail.taskId);
181
+ * }
182
+ */
183
+ runNoThrow(model: string, input?: Record<string, any>, options?: RunOptions): Promise<RunNoThrowResult>;
135
184
  /**
136
185
  * Upload a file to WaveSpeed.
137
186
  *
@@ -319,6 +319,131 @@ class Client {
319
319
  }
320
320
  throw new Error(`All ${taskRetries + 1} attempts failed`);
321
321
  }
322
+ /**
323
+ * Run a model and wait for the output (no-throw version).
324
+ *
325
+ * This method is similar to run() but does not throw exceptions.
326
+ * Instead, it returns a result object with outputs (null on failure) and detail information.
327
+ * The detail object always contains the taskId, which is useful for debugging and tracking.
328
+ *
329
+ * Args:
330
+ * model: Model identifier (e.g., "wavespeed-ai/flux-dev").
331
+ * input: Input parameters for the model.
332
+ * options.timeout: Maximum time to wait for completion (undefined = no timeout).
333
+ * options.pollInterval: Interval between status checks in seconds.
334
+ * options.enableSyncMode: If true, use synchronous mode (single request).
335
+ * options.maxRetries: Maximum task-level retries (overrides client setting).
336
+ *
337
+ * Returns:
338
+ * Object containing:
339
+ * - outputs: Array of model outputs (null if failed)
340
+ * - detail: Object with taskId, status, error (if any), and other metadata
341
+ *
342
+ * Example:
343
+ * const result = await client.runNoThrow("wavespeed-ai/z-image/turbo", { prompt: "Cat" });
344
+ *
345
+ * if (result.outputs) {
346
+ * console.log("Success:", result.outputs);
347
+ * console.log("Task ID:", result.detail.taskId);
348
+ * } else {
349
+ * console.log("Failed:", result.detail.error);
350
+ * console.log("Task ID:", result.detail.taskId);
351
+ * }
352
+ */
353
+ async runNoThrow(model, input, options) {
354
+ var _a, _b, _c, _d, _e;
355
+ const taskRetries = (_a = options === null || options === void 0 ? void 0 : options.maxRetries) !== null && _a !== void 0 ? _a : this.maxRetries;
356
+ const timeout = (_b = options === null || options === void 0 ? void 0 : options.timeout) !== null && _b !== void 0 ? _b : this.timeout;
357
+ const pollInterval = (_c = options === null || options === void 0 ? void 0 : options.pollInterval) !== null && _c !== void 0 ? _c : 1.0;
358
+ const enableSyncMode = (_d = options === null || options === void 0 ? void 0 : options.enableSyncMode) !== null && _d !== void 0 ? _d : false;
359
+ for (let attempt = 0; attempt <= taskRetries; attempt++) {
360
+ try {
361
+ const [requestId, syncResult] = await this._submit(model, input, enableSyncMode, timeout);
362
+ if (enableSyncMode) {
363
+ // In sync mode, extract outputs from the result
364
+ const data = (syncResult === null || syncResult === void 0 ? void 0 : syncResult.data) || {};
365
+ const status = data.status;
366
+ const taskId = data.id || 'unknown';
367
+ if (status !== 'completed') {
368
+ const error = data.error || 'Unknown error';
369
+ return {
370
+ outputs: null,
371
+ detail: {
372
+ taskId,
373
+ status: 'failed',
374
+ model,
375
+ error,
376
+ createdAt: data.created_at
377
+ }
378
+ };
379
+ }
380
+ return {
381
+ outputs: data.outputs || [],
382
+ detail: {
383
+ taskId,
384
+ status: 'completed',
385
+ model,
386
+ createdAt: data.created_at
387
+ }
388
+ };
389
+ }
390
+ if (requestId) {
391
+ const result = await this._wait(requestId, timeout, pollInterval);
392
+ return {
393
+ outputs: result.outputs,
394
+ detail: {
395
+ taskId: requestId,
396
+ status: 'completed',
397
+ model
398
+ }
399
+ };
400
+ }
401
+ // Should not reach here
402
+ return {
403
+ outputs: null,
404
+ detail: {
405
+ taskId: 'unknown',
406
+ status: 'failed',
407
+ model,
408
+ error: 'Invalid response from _submit'
409
+ }
410
+ };
411
+ }
412
+ catch (error) {
413
+ const isRetryable = this._isRetryableError(error);
414
+ // If not retryable or last attempt, return error result
415
+ if (!isRetryable || attempt >= taskRetries) {
416
+ // Try to extract taskId from error message
417
+ const taskIdMatch = (_e = error.message) === null || _e === void 0 ? void 0 : _e.match(/task_id: ([a-f0-9-]+)/);
418
+ const taskId = taskIdMatch ? taskIdMatch[1] : 'unknown';
419
+ return {
420
+ outputs: null,
421
+ detail: {
422
+ taskId,
423
+ status: 'failed',
424
+ model,
425
+ error: error.message || String(error)
426
+ }
427
+ };
428
+ }
429
+ // Retry
430
+ console.log(`Task attempt ${attempt + 1}/${taskRetries + 1} failed: ${error}`);
431
+ const delay = this.retryInterval * (attempt + 1) * 1000;
432
+ console.log(`Retrying in ${delay}ms...`);
433
+ await new Promise((resolve) => setTimeout(resolve, delay));
434
+ }
435
+ }
436
+ // Should not reach here, but just in case
437
+ return {
438
+ outputs: null,
439
+ detail: {
440
+ taskId: 'unknown',
441
+ status: 'failed',
442
+ model,
443
+ error: `All ${taskRetries + 1} attempts failed`
444
+ }
445
+ };
446
+ }
322
447
  /**
323
448
  * Upload a file to WaveSpeed.
324
449
  *
@@ -18,9 +18,9 @@
18
18
  * console.log(url);
19
19
  */
20
20
  import { Client } from './client';
21
- import type { RunOptions } from './client';
21
+ import type { RunOptions, RunDetail, RunNoThrowResult } from './client';
22
22
  export { Client };
23
- export type { RunOptions };
23
+ export type { RunOptions, RunDetail, RunNoThrowResult };
24
24
  /**
25
25
  * Run a model and wait for the output.
26
26
  *
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  import { version } from './version';
17
17
  import './config';
18
18
  import { Client, run, upload } from './api';
19
- import type { RunOptions } from './api/client';
19
+ import type { RunOptions, RunDetail, RunNoThrowResult } from './api/client';
20
20
  export { version, Client, run, upload };
21
- export type { RunOptions };
21
+ export type { RunOptions, RunDetail, RunNoThrowResult };
22
22
  export default Client;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wavespeed",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "WaveSpeed Client SDK for Wavespeed API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",