@picsart/ai-sdk 5.24.1 → 5.26.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/README.md CHANGED
@@ -188,9 +188,61 @@ for await (const update of ai.subscribe(handle)) {
188
188
  const status = await ai.status(handle)
189
189
  ```
190
190
 
191
+ ## Error Handling
192
+
193
+ Every failure thrown by `generate()`, `generateText()`, `submit()`, and `result()`
194
+ is an `ApiError` with the same four fields, so you can branch on the error
195
+ instead of pattern-matching its message:
196
+
197
+ ```typescript
198
+ import { createClient, Models, ApiError } from '@picsart/ai-sdk'
199
+
200
+ try {
201
+ const result = await ai.generate(Models.Flux2Pro, { prompt: 'a cat on mars' })
202
+ } catch (err) {
203
+ if (err instanceof ApiError) {
204
+ err.status // 402 — HTTP status, or its synthesized equivalent
205
+ err.code // 'payment_required' — platform `reason`, else an SDK code
206
+ err.reason // same value as `code`, named after the platform's own field
207
+ err.message // 'Submit failed (402): Not enough credits'
208
+
209
+ if (err.status === 402) return topUpCredits()
210
+ if (err.status === 429 || err.status >= 500) return retry()
211
+ if (err.code === 'validation_error') return showFormError(err.message)
212
+ }
213
+ throw err
214
+ }
215
+ ```
216
+
217
+ `code` carries the platform's `reason` verbatim whenever the API supplies one
218
+ (`content_moderation`, `unauthorized`, …). When it doesn't, the SDK fills in a
219
+ conventional slug for the status — `payment_required` for 402, `rate_limited`
220
+ for 429, and so on.
221
+
222
+ Failures that never reach the network get the status they semantically deserve,
223
+ so one retry predicate covers every case:
224
+
225
+ | Failure | `status` | `code` |
226
+ |---------|----------|--------|
227
+ | Unknown model id | 400 | `unknown_model` |
228
+ | `generate()` on a text model (or the reverse) | 400 | `wrong_model_mode` |
229
+ | Parameter validation | 400 | `validation_error` |
230
+ | Async lifecycle on an execute-only transport | 400 | `unsupported_transport` |
231
+ | HTTP error from the API | the response's status | platform `reason`, else the status slug |
232
+ | Poll deadline exceeded | 408 | `timeout` |
233
+ | Aborted via `options.signal`, or a canceled job | 499 | `aborted` / `canceled` |
234
+ | Job finished `FAILED` | the task's `statusCode`, else 502 | platform `reason`, else `generation_failed` |
235
+ | Response the SDK can't parse | 502 | `invalid_response` |
236
+
237
+ Aborts raised by `fetch` itself are deliberately **not** wrapped, so
238
+ `err.name === 'AbortError'` keeps working on the `DOMException`.
239
+
240
+ `message` is human-readable and may change between versions — branch on `status`
241
+ and `code`, not on the message text.
242
+
191
243
  ## Public API
192
244
 
193
- The SDK exports 7 symbols:
245
+ The SDK exports 8 symbols:
194
246
 
195
247
  | Export | Type | Description |
196
248
  |--------|------|-------------|
@@ -201,6 +253,7 @@ The SDK exports 7 symbols:
201
253
  | `AuthenticatedFetch` | type | `(url, init?) => Promise<Response>` — for the custom-`fetch` path |
202
254
  | `SdkTransport` | type | Advanced: custom transport interface |
203
255
  | `WorkflowJobHandle` | type | Job handle for submit/status/cancel |
256
+ | `ApiError` | class | Unified error: `{ status, code, reason, message }` — see [Error Handling](#error-handling) |
204
257
 
205
258
  ## Package Structure
206
259