@picsart/ai-sdk 5.24.0 → 5.25.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/index.d.ts CHANGED
@@ -49,6 +49,10 @@ interface WorkflowStatusResult<TResult = unknown> {
49
49
  status: WorkflowStatus;
50
50
  result?: TResult;
51
51
  error?: string;
52
+ /** Platform error `reason` on a failed task, when the response carried one. */
53
+ reason?: string;
54
+ /** Numeric status on the error payload, when the response carried one. */
55
+ statusCode?: number;
52
56
  progress?: WorkflowProgress;
53
57
  /** Credit usage reported by the platform, when present on the response. */
54
58
  usage?: CreditUsage;
@@ -822,6 +826,18 @@ type ModelInputById = {
822
826
  bitrate?: 32000 | 64000 | 128000 | 256000;
823
827
  format?: "mp3" | "wav" | "pcm";
824
828
  };
829
+ "muse-image-1.0": {
830
+ prompt: string;
831
+ aspectRatio?: "1:1" | "3:2" | "2:3" | "16:9" | "9:16" | "4:3" | "3:4";
832
+ reasoningStrength?: "low" | "high";
833
+ moderation?: "auto" | "low" | "none";
834
+ enableImageSearch?: boolean;
835
+ enableWebSearch?: boolean;
836
+ enableShell?: boolean;
837
+ outputFormat?: "png" | "jpeg" | "webp";
838
+ count?: 1 | 2 | 4 | 6 | 8 | 10;
839
+ imageUrls?: string[];
840
+ };
825
841
  "ovi": {
826
842
  prompt: string;
827
843
  size?: "9:16" | "16:9" | "1:1" | "9:16+" | "16:9+" | "2:5" | "5:2";
@@ -2026,7 +2042,7 @@ interface ModelFilter$1 {
2026
2042
  release?: ReleaseTag[];
2027
2043
  }
2028
2044
 
2029
- type AppProvider = 'picsart' | 'google' | 'kling' | 'grok' | 'openai' | 'flux' | 'ideogram' | 'elevenlabs' | 'minimax' | 'wan' | 'seedance' | 'ltx' | 'seedream' | 'seedaudio' | 'hunyuan' | 'pika' | 'runway' | 'luma' | 'ovi' | 'creatify' | 'veed' | 'bytedance' | 'qwen' | 'reve' | 'recraft' | 'videography' | 'topaz' | 'heygen' | 'happyhorse' | 'pixverse' | 'anthropic' | 'async' | 'captionsai';
2045
+ type AppProvider = 'picsart' | 'google' | 'kling' | 'grok' | 'openai' | 'flux' | 'ideogram' | 'elevenlabs' | 'minimax' | 'wan' | 'seedance' | 'ltx' | 'seedream' | 'seedaudio' | 'hunyuan' | 'pika' | 'runway' | 'luma' | 'ovi' | 'creatify' | 'veed' | 'bytedance' | 'qwen' | 'reve' | 'recraft' | 'videography' | 'topaz' | 'heygen' | 'happyhorse' | 'pixverse' | 'anthropic' | 'async' | 'captionsai' | 'meta';
2030
2046
  /** Provider used by model definitions. */
2031
2047
  type Provider = AppProvider;
2032
2048
  /** App generation modes. */
@@ -2631,6 +2647,7 @@ declare const Models: {
2631
2647
  readonly MinimaxH3Max: "minimax-h3-max";
2632
2648
  readonly MinimaxMusicV2: "minimax-music-v2";
2633
2649
  readonly MinimaxMusicV3: "minimax-music-v3";
2650
+ readonly MuseImage10: "muse-image-1.0";
2634
2651
  readonly Ovi: "ovi";
2635
2652
  readonly PicsartChangeBg: "picsart-change-bg";
2636
2653
  readonly PicsartEnhance: "picsart-enhance";
@@ -2761,6 +2778,59 @@ declare function getVoiceById(id: string): VoiceOption | undefined;
2761
2778
  /** @deprecated Load the model's catalog instead (`ai.catalogs.voices(modelId)`) — loaded voices are searched automatically. */
2762
2779
  declare function getVoiceById(id: string, extra: VoiceOption[] | undefined): VoiceOption | undefined;
2763
2780
 
2781
+ /**
2782
+ * Failure codes the SDK synthesizes when the platform supplies no `reason`.
2783
+ * An API-supplied `reason` passes through unchanged, so the open `string`
2784
+ * member keeps arbitrary platform reasons assignable while preserving
2785
+ * autocomplete on the known set.
2786
+ */
2787
+ type ApiErrorCode = 'unknown_model' | 'wrong_model_mode' | 'validation_error' | 'unsupported_transport' | 'timeout' | 'aborted' | 'canceled' | 'generation_failed' | 'invalid_response' | 'bad_request' | 'unauthorized' | 'payment_required' | 'forbidden' | 'not_found' | 'rate_limited' | 'server_error' | (string & {});
2788
+ /** Everything but the message needed to build a {@link ApiError}. */
2789
+ interface ApiErrorInit {
2790
+ /**
2791
+ * HTTP status of the failing response. When no HTTP exchange took place the
2792
+ * SDK synthesizes the semantically matching code: 400 for input the SDK
2793
+ * itself rejects, 408 for a poll deadline, 499 for an abort or cancel, 502
2794
+ * for a response it cannot make sense of.
2795
+ */
2796
+ status: number;
2797
+ /** Platform `reason` when present, otherwise an SDK-synthesized code. */
2798
+ code: ApiErrorCode;
2799
+ }
2800
+ /**
2801
+ * The single error type thrown by the SDK's generation surface —
2802
+ * `generate()`, `generateText()`, `submit()`, and `result()`.
2803
+ *
2804
+ * Unrelated to the `Api*` types (`ApiResponse`, `ApiRunOptions`, …), which
2805
+ * describe the low-level `ai.apis` surface. `ai.apis.run()` throws the
2806
+ * workflows client's own errors, not this.
2807
+ *
2808
+ * ```ts
2809
+ * try {
2810
+ * await ai.generate(Models.Flux2Pro, { prompt: 'a cat' });
2811
+ * } catch (err) {
2812
+ * if (err instanceof ApiError) {
2813
+ * if (err.status === 402) return topUpCredits();
2814
+ * if (err.status === 429 || err.status >= 500) return retry();
2815
+ * if (err.code === 'validation_error') return showFormError(err.message);
2816
+ * }
2817
+ * throw err;
2818
+ * }
2819
+ * ```
2820
+ *
2821
+ * Aborts raised by `fetch` itself are never wrapped — a caller checking
2822
+ * `err.name === 'AbortError'` on a `DOMException` keeps working.
2823
+ */
2824
+ declare class ApiError extends Error {
2825
+ /** HTTP status, or the synthesized equivalent for non-HTTP failures. */
2826
+ readonly status: number;
2827
+ /** Platform `reason`, or an SDK-synthesized code. Always equal to {@link reason}. */
2828
+ readonly code: ApiErrorCode;
2829
+ /** Alias of {@link code}, named after the platform's own error field. */
2830
+ readonly reason: ApiErrorCode;
2831
+ constructor(message: string, init: ApiErrorInit);
2832
+ }
2833
+
2764
2834
  /**
2765
2835
  * Pricing internals — owns the ModelPricingClient, the per-model cache, and
2766
2836
  * the credit-range lookup. The Model accessor delegates to the helpers below
@@ -2889,4 +2959,4 @@ declare const findModel: (ref: string) => ModelDefinition | undefined;
2889
2959
  */
2890
2960
  declare const KLING_DUAL_IMAGE_EFFECTS: ReadonlySet<string>;
2891
2961
 
2892
- export { ALL_MODELS, type AiClient, type ApiResponse, type ApiRunOptions, type ApiSchemas, type ApisClient, type AppIdentity, type AppType, type AuthenticatedFetch, type AvatarOption, type BooleanDescriptor, type BooleanEntry, type CatalogDescriptor, type CatalogEntry, type CatalogItem, type CatalogKind, type CatalogPage, type CatalogPageOptions, type CatalogPreview, type CatalogQuery, type CatalogResult, type CatalogSource, type CatalogsClient, type CatalogsOptions, type ClientConfig, type CreditRange, type CreditRangeContext, type CreditTier, type CreditUsage, DEFAULT_VISIBLE_RELEASES, type DeepLinkResult, type DriveAttributes, type DriveClient, type DriveConfig, type DriveFile, type DriveFileDetails, type DriveFolder, type DriveMediaItem, type DriveSaveResult, type EntryMeta, type EnumDescriptor, type EnumEntry, type EnumOption, type FileDescriptor, type FileEntry, type FlatParamEntry, type GenerateOptions, type GenerateResult, type GenerateResultItem, type GenerateTextResult, type GenerationContext, type GenerationFile, type GenerationMode, KLING_DUAL_IMAGE_EFFECTS, type ListOptions, type MediaModelId, type MediaTypeFilter, Model, type ModelDefinition, type ModelDescriptor, type ModelFilter$1 as ModelFilter, type ModelInput, type ModelInputById, type ModelMeta, type ModelParams, type ModelParamsAccessor, Models, type ObjectDescriptor, type ObjectEntry, type ParamDescriptor, type ParamEntry, type ParamOption, type PayloadDriveFolderOptions, type PayloadDriveOptions, type PricingOptions, type ProviderInfo, type RangeDescriptor, type RangeEntry, type ReleaseTag, type SaveParams, type SdkPayload, type SdkTransport, type TextDescriptor, type TextEntry, type TextModelId, type TextModelInputById, type ToolUsage, type TypedModelId, type UserReaction, type ValidationResult$1 as ValidationResult, type VoiceOption, type WorkflowJobHandle, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, toAvatarOption, toVoiceOption };
2962
+ export { ALL_MODELS, type AiClient, ApiError, type ApiErrorCode, type ApiErrorInit, type ApiResponse, type ApiRunOptions, type ApiSchemas, type ApisClient, type AppIdentity, type AppType, type AuthenticatedFetch, type AvatarOption, type BooleanDescriptor, type BooleanEntry, type CatalogDescriptor, type CatalogEntry, type CatalogItem, type CatalogKind, type CatalogPage, type CatalogPageOptions, type CatalogPreview, type CatalogQuery, type CatalogResult, type CatalogSource, type CatalogsClient, type CatalogsOptions, type ClientConfig, type CreditRange, type CreditRangeContext, type CreditTier, type CreditUsage, DEFAULT_VISIBLE_RELEASES, type DeepLinkResult, type DriveAttributes, type DriveClient, type DriveConfig, type DriveFile, type DriveFileDetails, type DriveFolder, type DriveMediaItem, type DriveSaveResult, type EntryMeta, type EnumDescriptor, type EnumEntry, type EnumOption, type FileDescriptor, type FileEntry, type FlatParamEntry, type GenerateOptions, type GenerateResult, type GenerateResultItem, type GenerateTextResult, type GenerationContext, type GenerationFile, type GenerationMode, KLING_DUAL_IMAGE_EFFECTS, type ListOptions, type MediaModelId, type MediaTypeFilter, Model, type ModelDefinition, type ModelDescriptor, type ModelFilter$1 as ModelFilter, type ModelInput, type ModelInputById, type ModelMeta, type ModelParams, type ModelParamsAccessor, Models, type ObjectDescriptor, type ObjectEntry, type ParamDescriptor, type ParamEntry, type ParamOption, type PayloadDriveFolderOptions, type PayloadDriveOptions, type PricingOptions, type ProviderInfo, type RangeDescriptor, type RangeEntry, type ReleaseTag, type SaveParams, type SdkPayload, type SdkTransport, type TextDescriptor, type TextEntry, type TextModelId, type TextModelInputById, type ToolUsage, type TypedModelId, type UserReaction, type ValidationResult$1 as ValidationResult, type VoiceOption, type WorkflowJobHandle, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, toAvatarOption, toVoiceOption };
package/index.js CHANGED
@@ -441,6 +441,62 @@ var require_build = __commonJS({
441
441
  }
442
442
  });
443
443
 
444
+ // src/core/errors.ts
445
+ var ApiError = class extends Error {
446
+ /** HTTP status, or the synthesized equivalent for non-HTTP failures. */
447
+ status;
448
+ /** Platform `reason`, or an SDK-synthesized code. Always equal to {@link reason}. */
449
+ code;
450
+ /** Alias of {@link code}, named after the platform's own error field. */
451
+ reason;
452
+ constructor(message, init) {
453
+ super(message);
454
+ this.name = "ApiError";
455
+ this.status = init.status;
456
+ this.code = init.code;
457
+ this.reason = init.code;
458
+ }
459
+ };
460
+ var CODE_BY_STATUS = {
461
+ 400: "bad_request",
462
+ 401: "unauthorized",
463
+ 402: "payment_required",
464
+ 403: "forbidden",
465
+ 404: "not_found",
466
+ 408: "timeout",
467
+ 409: "conflict",
468
+ 413: "payload_too_large",
469
+ 422: "unprocessable_entity",
470
+ 429: "rate_limited",
471
+ 500: "server_error",
472
+ 502: "bad_gateway",
473
+ 503: "service_unavailable",
474
+ 504: "gateway_timeout"
475
+ };
476
+ function codeForStatus(status) {
477
+ return CODE_BY_STATUS[status] ?? (status >= 500 ? "server_error" : `http_${status}`);
478
+ }
479
+ async function readErrorBody(res) {
480
+ let text = "";
481
+ try {
482
+ text = await res.text();
483
+ } catch {
484
+ return { text: "" };
485
+ }
486
+ try {
487
+ const parsed = JSON.parse(text);
488
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
489
+ return { text, json: parsed };
490
+ }
491
+ } catch {
492
+ }
493
+ return { text };
494
+ }
495
+ function reasonFrom(json, status) {
496
+ const raw = json?.reason ?? json?.code;
497
+ return typeof raw === "string" && raw.length > 0 ? raw : codeForStatus(status);
498
+ }
499
+
444
500
  // src/core/workflow.ts
445
501
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
446
502
  var DEFAULT_MAX_ATTEMPTS = 300;
@@ -476,7 +532,9 @@ function parseWorkflowStatus(handle, raw) {
476
532
  const result = pickFirst(raw, [["response", "result"], ["result"]]);
477
533
  const usageRaw = pickFirst(raw, [["response", "usage"], ["usage"]]);
478
534
  const usage = usageRaw && typeof usageRaw === "object" && (typeof usageRaw.credits === "number" || Array.isArray(usageRaw.details)) ? usageRaw : void 0;
479
- const errorRaw = pickFirst(raw, [["response", "error"], ["error"], ["message"], ["reason"]]);
535
+ const errorRaw = pickFirst(raw, [["response", "error"], ["response", "message"], ["error"], ["message"], ["reason"]]);
536
+ const reasonRaw = pickFirst(raw, [["response", "reason"], ["reason"]]);
537
+ const statusCodeRaw = pickFirst(raw, [["response", "statusCode"], ["statusCode"]]);
480
538
  const progressRaw = pickFirst(raw, [["response", "progress"], ["progress"]]);
481
539
  const progress = progressRaw && typeof progressRaw === "object" ? {
482
540
  percent: typeof progressRaw.percent === "number" ? progressRaw.percent : void 0,
@@ -487,6 +545,8 @@ function parseWorkflowStatus(handle, raw) {
487
545
  status,
488
546
  result,
489
547
  error: typeof errorRaw === "string" ? errorRaw : void 0,
548
+ reason: typeof reasonRaw === "string" ? reasonRaw : void 0,
549
+ statusCode: typeof statusCodeRaw === "number" ? statusCodeRaw : void 0,
490
550
  progress,
491
551
  usage,
492
552
  raw
@@ -502,13 +562,19 @@ function createWorkflowClient(transport, options = {}) {
502
562
  const defaultMaxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
503
563
  const submit = async (request) => {
504
564
  if (!transport.submit) {
505
- throw new Error("Transport does not support submit (execute-only transport)");
565
+ throw new ApiError("Transport does not support submit (execute-only transport)", {
566
+ status: 400,
567
+ code: "unsupported_transport"
568
+ });
506
569
  }
507
570
  return transport.submit(request);
508
571
  };
509
572
  const status = async (handle, signal) => {
510
573
  if (!transport.status) {
511
- throw new Error("Transport does not support status (execute-only transport)");
574
+ throw new ApiError("Transport does not support status (execute-only transport)", {
575
+ status: 400,
576
+ code: "unsupported_transport"
577
+ });
512
578
  }
513
579
  const raw = await transport.status(handle, signal);
514
580
  return parseStatus(handle, raw);
@@ -518,13 +584,16 @@ function createWorkflowClient(transport, options = {}) {
518
584
  const maxAttempts = pollOptions.maxAttempts ?? defaultMaxAttempts;
519
585
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
520
586
  if (pollOptions.signal?.aborted) {
521
- throw new Error("Operation aborted");
587
+ throw new ApiError("Operation aborted", { status: 499, code: "aborted" });
522
588
  }
523
589
  const next = await status(handle, pollOptions.signal);
524
590
  if (isTerminal(next.status)) return next;
525
591
  await sleep2(intervalMs);
526
592
  }
527
- throw new Error(`Timed out waiting for workflow ${handle.workflow}:${handle.id}`);
593
+ throw new ApiError(
594
+ `Timed out waiting for workflow ${handle.workflow}:${handle.id}`,
595
+ { status: 408, code: "timeout" }
596
+ );
528
597
  };
529
598
  const run = async (request, runOptions = {}) => {
530
599
  const runMode = runOptions.mode;
@@ -543,14 +612,17 @@ function createWorkflowClient(transport, options = {}) {
543
612
  const maxAttempts = subscribeOptions.maxAttempts ?? defaultMaxAttempts;
544
613
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
545
614
  if (subscribeOptions.signal?.aborted) {
546
- throw new Error("Operation aborted");
615
+ throw new ApiError("Operation aborted", { status: 499, code: "aborted" });
547
616
  }
548
617
  const next = await status(handle, subscribeOptions.signal);
549
618
  yield next;
550
619
  if (isTerminal(next.status)) return next;
551
620
  await sleep2(intervalMs);
552
621
  }
553
- throw new Error(`Timed out waiting for workflow ${handle.workflow}:${handle.id}`);
622
+ throw new ApiError(
623
+ `Timed out waiting for workflow ${handle.workflow}:${handle.id}`,
624
+ { status: 408, code: "timeout" }
625
+ );
554
626
  };
555
627
  return { submit, status, result, run, subscribe };
556
628
  }
@@ -821,7 +893,8 @@ var providers = {
821
893
  pixverse: { color: "#7C3AED", label: "PV", name: "PixVerse" },
822
894
  anthropic: { color: "#D97757", label: "CL", name: "Anthropic" },
823
895
  async: { color: "#5E5CE6", label: "AA", name: "Async AI" },
824
- captionsai: { color: "#1D1F20", label: "MR", name: "Mirage" }
896
+ captionsai: { color: "#1D1F20", label: "MR", name: "Mirage" },
897
+ meta: { color: "#0081FB", label: "MT", name: "Meta" }
825
898
  };
826
899
 
827
900
  // src/core/descriptors/presets.ts
@@ -1177,7 +1250,7 @@ var passthroughPayload = (paramConfig) => (ctx) => {
1177
1250
  return payload;
1178
1251
  };
1179
1252
  function defineModels(provider, configs) {
1180
- const MODELS38 = [];
1253
+ const MODELS39 = [];
1181
1254
  for (const c of configs) {
1182
1255
  const prov = c.provider ?? provider;
1183
1256
  const resolvedPayload = c.buildPayload ?? passthroughPayload(c.paramConfig);
@@ -1213,19 +1286,19 @@ function defineModels(provider, configs) {
1213
1286
  if (c.constraints !== void 0) model.constraints = c.constraints;
1214
1287
  const contract = createModelContract(model);
1215
1288
  model.outputSchema = c.outputSchema ?? contract.output;
1216
- MODELS38.push(model);
1289
+ MODELS39.push(model);
1217
1290
  }
1218
- return { MODELS: MODELS38 };
1291
+ return { MODELS: MODELS39 };
1219
1292
  }
1220
- function registerPayloads(MODELS38, payloads) {
1293
+ function registerPayloads(MODELS39, payloads) {
1221
1294
  for (const [id, builder] of Object.entries(payloads)) {
1222
- const model = MODELS38.find((m) => m.id === id);
1295
+ const model = MODELS39.find((m) => m.id === id);
1223
1296
  if (model) model.buildPayload = builder;
1224
1297
  }
1225
1298
  }
1226
- function registerEditPayloads(MODELS38, payloads) {
1299
+ function registerEditPayloads(MODELS39, payloads) {
1227
1300
  for (const [id, builder] of Object.entries(payloads)) {
1228
- const model = MODELS38.find((m) => m.id === id);
1301
+ const model = MODELS39.find((m) => m.id === id);
1229
1302
  if (model) model.buildEditPayload = builder;
1230
1303
  }
1231
1304
  }
@@ -8561,6 +8634,74 @@ registerPayloads(MODELS37, {
8561
8634
  "captionsai-video-captions": buildCaptionsPayload
8562
8635
  });
8563
8636
 
8637
+ // src/vendors/catalog/meta.ts
8638
+ var { MODELS: MODELS38 } = defineModels("meta", [
8639
+ // ── Image ─────────────────────────────────────────
8640
+ {
8641
+ id: "muse-image-1.0",
8642
+ name: "Muse Image 1.0",
8643
+ addedAt: "2026-08-31",
8644
+ workflow: "meta/v1/images/generations",
8645
+ editWorkflow: "meta/v1/images/edits",
8646
+ estimatedTime: 60,
8647
+ mode: "image",
8648
+ inputType: "t2i",
8649
+ description: "Meta's agentic image model \u2014 plans with reasoning, web and image search before rendering.",
8650
+ features: [feat("Multi-Image Input", "input"), feat("Web Search", "characteristic"), feat("High Quality", "quality")],
8651
+ paramConfig: {
8652
+ ...params.prompt(),
8653
+ ...params.aspectRatio(["1:1", "3:2", "2:3", "16:9", "9:16", "4:3", "3:4"], "1:1"),
8654
+ // Vendor-side reasoning tier for the agentic planner; vendor default high.
8655
+ ...p.enum("reasoningStrength", ["low", "high"], "high", { label: "Reasoning" }),
8656
+ ...p.enum("moderation", ["auto", "low", "none"], "auto", { label: "Moderation" }),
8657
+ // Per-tool planner controls — all-true matches the vendor default
8658
+ // (omitting tool_enablement enables every tool).
8659
+ ...p.boolean("enableImageSearch", true, "Image Search"),
8660
+ ...p.boolean("enableWebSearch", true, "Web Search"),
8661
+ ...p.boolean("enableShell", true, "Layout & Chart Tools"),
8662
+ ...p.enum("outputFormat", ["png", "jpeg", "webp"], "png", { label: "Format" }),
8663
+ ...params.count(),
8664
+ ...params.imageInput(5, "Source Images")
8665
+ }
8666
+ }
8667
+ ]);
8668
+
8669
+ // src/vendors/catalog/meta.payloads.ts
8670
+ var MUSE_AR_TO_SIZE = {
8671
+ "1:1": "1024x1024",
8672
+ "3:2": "1536x1024",
8673
+ "2:3": "1024x1536",
8674
+ "16:9": "1820x1024",
8675
+ "9:16": "1024x1820",
8676
+ "4:3": "1365x1024",
8677
+ "3:4": "1024x1365"
8678
+ };
8679
+ var buildMuseCommonPayload = (input) => ({
8680
+ model: "muse-image-1.0",
8681
+ prompt: input.prompt,
8682
+ n: input.count ?? 1,
8683
+ size: MUSE_AR_TO_SIZE[input.aspectRatio ?? ""] ?? "1024x1024",
8684
+ ...input.outputFormat ? { output_format: input.outputFormat } : {},
8685
+ ...input.reasoningStrength ? { reasoning_strength: input.reasoningStrength } : {},
8686
+ ...input.moderation ? { moderation: input.moderation } : {},
8687
+ tool_enablement: {
8688
+ enable_image_search: input.enableImageSearch ?? true,
8689
+ enable_web_search: input.enableWebSearch ?? true,
8690
+ enable_shell: input.enableShell ?? true
8691
+ }
8692
+ });
8693
+ var buildMuseImagePayload = (input) => buildMuseCommonPayload(input);
8694
+ var buildMuseImageEditPayload = (input) => ({
8695
+ ...buildMuseCommonPayload(input),
8696
+ images: input.imageUrls ?? []
8697
+ });
8698
+ registerPayloads(MODELS38, {
8699
+ "muse-image-1.0": buildMuseImagePayload
8700
+ });
8701
+ registerEditPayloads(MODELS38, {
8702
+ "muse-image-1.0": buildMuseImageEditPayload
8703
+ });
8704
+
8564
8705
  // src/vendors/catalog/index.ts
8565
8706
  var ALL_MODELS = [
8566
8707
  ...MODELS,
@@ -8599,21 +8740,30 @@ var ALL_MODELS = [
8599
8740
  ...MODELS34,
8600
8741
  ...MODELS35,
8601
8742
  ...MODELS36,
8602
- ...MODELS37
8743
+ ...MODELS37,
8744
+ ...MODELS38
8603
8745
  ];
8604
8746
  var getModelsByMode = (mode, includeDisabled = false) => ALL_MODELS.filter((m) => m.mode === mode && (includeDisabled || isVisibleForReleases(m)));
8605
8747
 
8606
8748
  // src/core/contracts.ts
8607
8749
  function requireObject(value, message) {
8608
8750
  if (!value || typeof value !== "object" || Array.isArray(value)) {
8609
- throw new Error(message);
8751
+ throw new ApiError(message, { status: 400, code: "validation_error" });
8610
8752
  }
8611
8753
  }
8612
8754
  function buildInputSchema(model) {
8613
8755
  return {
8614
8756
  parse(input) {
8615
8757
  requireObject(input, `Invalid input for model "${model.id}"`);
8616
- validateAll(model.paramConfig, input);
8758
+ try {
8759
+ validateAll(model.paramConfig, input);
8760
+ } catch (err) {
8761
+ if (err instanceof ApiError) throw err;
8762
+ throw new ApiError(err instanceof Error ? err.message : String(err), {
8763
+ status: 400,
8764
+ code: "validation_error"
8765
+ });
8766
+ }
8617
8767
  return input;
8618
8768
  }
8619
8769
  };
@@ -8622,7 +8772,10 @@ function buildOutputSchema(model) {
8622
8772
  return {
8623
8773
  parse(output) {
8624
8774
  if (output == null) {
8625
- throw new Error(`Model "${model.id}" returned empty output`);
8775
+ throw new ApiError(`Model "${model.id}" returned empty output`, {
8776
+ status: 502,
8777
+ code: "invalid_response"
8778
+ });
8626
8779
  }
8627
8780
  return output;
8628
8781
  }
@@ -8665,7 +8818,12 @@ function throwIfErrorResult(result, modelName) {
8665
8818
  if (isError) {
8666
8819
  const code = typeof status === "number" ? ` (${status})` : "";
8667
8820
  const detail = message ? String(message) : "unknown error";
8668
- throw new Error(`${modelName} failed${code}: ${detail}`);
8821
+ const httpStatus = typeof status === "number" ? status : 502;
8822
+ const reason = obj.reason;
8823
+ throw new ApiError(`${modelName} failed${code}: ${detail}`, {
8824
+ status: httpStatus,
8825
+ code: typeof reason === "string" && reason.length > 0 ? reason : codeForStatus(httpStatus)
8826
+ });
8669
8827
  }
8670
8828
  }
8671
8829
  function extractSyncResult(raw) {
@@ -8867,7 +9025,9 @@ var findModel = (ref) => {
8867
9025
  // src/core/resolve.ts
8868
9026
  function resolveModel(id) {
8869
9027
  const found = findModel(id);
8870
- if (!found) throw new Error(`Unknown model: "${id}"`);
9028
+ if (!found) {
9029
+ throw new ApiError(`Unknown model: "${id}"`, { status: 400, code: "unknown_model" });
9030
+ }
8871
9031
  return found;
8872
9032
  }
8873
9033
 
@@ -8907,18 +9067,34 @@ function buildTransport(config) {
8907
9067
  { params: request.payload },
8908
9068
  request.signal
8909
9069
  );
8910
- const data = await res.json();
9070
+ const { text, json } = await readErrorBody(res);
8911
9071
  if (!res.ok) {
8912
- throw new Error(`Submit failed (${res.status}): ${data.message ?? JSON.stringify(data)}`);
9072
+ const detail = json ? json.message ?? JSON.stringify(json) : text;
9073
+ throw new ApiError(`Submit failed (${res.status}): ${detail}`, {
9074
+ status: res.status,
9075
+ code: reasonFrom(json, res.status)
9076
+ });
9077
+ }
9078
+ const response = json?.response;
9079
+ const id = response?.id ?? json?.id;
9080
+ if (!id) {
9081
+ throw new ApiError(`No task id in response: ${json ? JSON.stringify(json) : text}`, {
9082
+ status: 502,
9083
+ code: "invalid_response"
9084
+ });
8913
9085
  }
8914
- const response = data.response;
8915
- const id = response?.id ?? data.id;
8916
- if (!id) throw new Error(`No task id in response: ${JSON.stringify(data)}`);
8917
9086
  return { workflow: request.workflow, id: String(id) };
8918
9087
  },
8919
9088
  async status(handle, signal) {
8920
9089
  const res = await f(`${apiUrl}/workflows/${handle.workflow}/${handle.id}/result`, { signal });
8921
- if (!res.ok) throw new Error(`Status check failed (${res.status}): ${await res.text()}`);
9090
+ if (!res.ok) {
9091
+ const { text, json } = await readErrorBody(res);
9092
+ const detail = json ? json.message ?? text : text;
9093
+ throw new ApiError(`Status check failed (${res.status}): ${detail}`, {
9094
+ status: res.status,
9095
+ code: reasonFrom(json, res.status)
9096
+ });
9097
+ }
8922
9098
  return res.json();
8923
9099
  },
8924
9100
  async execute(request) {
@@ -8927,7 +9103,14 @@ function buildTransport(config) {
8927
9103
  { params: request.payload },
8928
9104
  request.signal
8929
9105
  );
8930
- if (!res.ok) throw new Error(`Execute failed (${res.status}): ${await res.text()}`);
9106
+ if (!res.ok) {
9107
+ const { text, json } = await readErrorBody(res);
9108
+ const detail = json ? json.message ?? text : text;
9109
+ throw new ApiError(`Execute failed (${res.status}): ${detail}`, {
9110
+ status: res.status,
9111
+ code: reasonFrom(json, res.status)
9112
+ });
9113
+ }
8931
9114
  return res.json();
8932
9115
  },
8933
9116
  async options(workflow, payload) {
@@ -8965,13 +9148,19 @@ function prepareRequest(model, params2) {
8965
9148
  const payload = resolved.buildPayload(validatedCtx);
8966
9149
  return { ctx, workflow: resolved.workflow, payload, contract };
8967
9150
  }
8968
- function parseResult(completed, model, contract) {
9151
+ function throwIfTerminalFailure(completed, model) {
8969
9152
  if (completed.status === "FAILED") {
8970
- throw new Error(`${model.name} failed: ${completed.error ?? "unknown error"}`);
9153
+ throw new ApiError(`${model.name} failed: ${completed.error ?? "unknown error"}`, {
9154
+ status: completed.statusCode ?? 502,
9155
+ code: completed.reason ?? "generation_failed"
9156
+ });
8971
9157
  }
8972
9158
  if (completed.status === "CANCELED") {
8973
- throw new Error(`${model.name} was canceled`);
9159
+ throw new ApiError(`${model.name} was canceled`, { status: 499, code: "canceled" });
8974
9160
  }
9161
+ }
9162
+ function parseResult(completed, model, contract) {
9163
+ throwIfTerminalFailure(completed, model);
8975
9164
  throwIfErrorResult(completed.result, model.name);
8976
9165
  const parsed = contract?.output ? contract.output.parse(completed.result) : completed.result;
8977
9166
  const multiItems = extractAllResults(parsed);
@@ -8984,22 +9173,23 @@ function parseResult(completed, model, contract) {
8984
9173
  }
8985
9174
  const url = extractUrl(parsed);
8986
9175
  if (!url) {
8987
- throw new Error(`${model.name}: unexpected response \u2014 no result URL`);
9176
+ throw new ApiError(`${model.name}: unexpected response \u2014 no result URL`, {
9177
+ status: 502,
9178
+ code: "invalid_response"
9179
+ });
8988
9180
  }
8989
9181
  return { url, results: [{ url }], model: model.id, handle: completed.handle, raw: parsed, usage: completed.usage };
8990
9182
  }
8991
9183
  function parseTextResult(completed, model) {
8992
- if (completed.status === "FAILED") {
8993
- throw new Error(`${model.name} failed: ${completed.error ?? "unknown error"}`);
8994
- }
8995
- if (completed.status === "CANCELED") {
8996
- throw new Error(`${model.name} was canceled`);
8997
- }
9184
+ throwIfTerminalFailure(completed, model);
8998
9185
  throwIfErrorResult(completed.result, model.name);
8999
9186
  throwIfErrorResult(completed.raw, model.name);
9000
9187
  const text = extractText(completed.result) ?? extractText(completed.raw);
9001
9188
  if (text == null) {
9002
- throw new Error(`${model.name}: unexpected response \u2014 no text`);
9189
+ throw new ApiError(`${model.name}: unexpected response \u2014 no text`, {
9190
+ status: 502,
9191
+ code: "invalid_response"
9192
+ });
9003
9193
  }
9004
9194
  return { text, model: model.id, handle: completed.handle, raw: completed.raw ?? completed.result, usage: completed.usage };
9005
9195
  }
@@ -10134,7 +10324,10 @@ function createClient(config) {
10134
10324
  async generate(model, params2, options) {
10135
10325
  const resolved = resolveModel(model);
10136
10326
  if (resolved.mode === "text") {
10137
- throw new Error(`${resolved.name} is a text model \u2014 use generateText() instead.`);
10327
+ throw new ApiError(`${resolved.name} is a text model \u2014 use generateText() instead.`, {
10328
+ status: 400,
10329
+ code: "wrong_model_mode"
10330
+ });
10138
10331
  }
10139
10332
  const { workflow, payload, contract } = prepareRequest(resolved, params2);
10140
10333
  const drive = buildDrivePayloadOptions(resolved, params2, options);
@@ -10153,7 +10346,10 @@ function createClient(config) {
10153
10346
  async generateText(model, params2, options) {
10154
10347
  const resolved = resolveModel(model);
10155
10348
  if (resolved.mode !== "text") {
10156
- throw new Error(`${resolved.name} is not a text model \u2014 use generate() instead.`);
10349
+ throw new ApiError(`${resolved.name} is not a text model \u2014 use generate() instead.`, {
10350
+ status: 400,
10351
+ code: "wrong_model_mode"
10352
+ });
10157
10353
  }
10158
10354
  const { workflow, payload } = prepareRequest(resolved, params2);
10159
10355
  const completed = await executeModel(resolved, workflow, payload, options);
@@ -10227,10 +10423,16 @@ function createClient(config) {
10227
10423
  options
10228
10424
  );
10229
10425
  if (done.status === "FAILED" || done.status === "CANCELED") {
10230
- throw new Error(done.error ?? `${workflow} failed with status ${done.status}`);
10426
+ throw new ApiError(done.error ?? `${workflow} failed with status ${done.status}`, {
10427
+ status: done.statusCode ?? (done.status === "CANCELED" ? 499 : 502),
10428
+ code: done.reason ?? (done.status === "CANCELED" ? "canceled" : "generation_failed")
10429
+ });
10231
10430
  }
10232
10431
  if (done.result === void 0) {
10233
- throw new Error(`${workflow} completed but returned no result`);
10432
+ throw new ApiError(`${workflow} completed but returned no result`, {
10433
+ status: 502,
10434
+ code: "invalid_response"
10435
+ });
10234
10436
  }
10235
10437
  return done.result;
10236
10438
  },
@@ -10795,6 +10997,7 @@ var MinimaxH3 = "minimax-h3";
10795
10997
  var MinimaxH3Max = "minimax-h3-max";
10796
10998
  var MinimaxMusicV2 = "minimax-music-v2";
10797
10999
  var MinimaxMusicV3 = "minimax-music-v3";
11000
+ var MuseImage10 = "muse-image-1.0";
10798
11001
  var Ovi = "ovi";
10799
11002
  var PicsartChangeBg = "picsart-change-bg";
10800
11003
  var PicsartEnhance = "picsart-enhance";
@@ -11007,6 +11210,7 @@ var Models = {
11007
11210
  MinimaxH3Max,
11008
11211
  MinimaxMusicV2,
11009
11212
  MinimaxMusicV3,
11213
+ MuseImage10,
11010
11214
  Ovi,
11011
11215
  PicsartChangeBg,
11012
11216
  PicsartEnhance,
@@ -11325,4 +11529,4 @@ function decodeDeepLinkPayload(encoded) {
11325
11529
  return deserializePayload(encoded);
11326
11530
  }
11327
11531
 
11328
- export { ALL_MODELS, ExecutionMode as ApiRunMode, DEFAULT_VISIBLE_RELEASES, KLING_DUAL_IMAGE_EFFECTS, Model, Models, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, toAvatarOption, toVoiceOption };
11532
+ export { ALL_MODELS, ApiError, ExecutionMode as ApiRunMode, DEFAULT_VISIBLE_RELEASES, KLING_DUAL_IMAGE_EFFECTS, Model, Models, buildFilename, buildGenerationAttributes, catalog, createClient, decodeDeepLinkPayload, encodeDeepLinkPayload, findModel, getModel, getModelsByMode, getVoiceById, inferResourceType, isVisibleForReleases, parseGeneration, releaseOf, toAvatarOption, toVoiceOption };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picsart/ai-sdk",
3
- "version": "5.24.0",
3
+ "version": "5.25.0",
4
4
  "type": "module",
5
5
  "description": "Type-safe SDK for 100+ AI models — image, video, audio, and text generation with Picsart",
6
6
  "license": "MIT",