@picsart/ai-sdk 3.32.0 → 3.35.5

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.
@@ -2,5 +2,5 @@ import { ModelPricingClient } from './lib/ModelPricingClient';
2
2
  import { ModelPricingClientError } from './lib/errors/ModelPricingClientError';
3
3
  import { ModelPricingServerError } from './lib/errors/ModelPricingServerError';
4
4
  import { ModelPricingUnknownError } from './lib/errors/ModelPricingUnknownError';
5
- import { UseCase, PricingUnit, ModelPricingFilters, ModelPricingMetadata, SkuEntry, VendorCostEntry, ModelPricing, ModelPricingListResponse, ModelPricingClientOptions } from './lib/types';
6
- export { ModelPricingClient, ModelPricingClientError, ModelPricingServerError, ModelPricingUnknownError, UseCase, PricingUnit, ModelPricingFilters, ModelPricingMetadata, SkuEntry, VendorCostEntry, ModelPricing, ModelPricingListResponse, ModelPricingClientOptions, };
5
+ import { UseCase, PricingUnit, ModelPricingFilters, ModelPricingMetadata, SkuEntry, VendorCostEntry, CreditOverride, MinTier, ModelPricing, ModelPricingListResponse, ModelPricingClientOptions, UserDiscount, UserDiscountListResponse } from './lib/types';
6
+ export { ModelPricingClient, ModelPricingClientError, ModelPricingServerError, ModelPricingUnknownError, UseCase, PricingUnit, ModelPricingFilters, ModelPricingMetadata, SkuEntry, VendorCostEntry, CreditOverride, MinTier, ModelPricing, ModelPricingListResponse, ModelPricingClientOptions, UserDiscount, UserDiscountListResponse, };
@@ -3,7 +3,9 @@ export declare class ModelPricingClient {
3
3
  private readonly options;
4
4
  private readonly modelPricingApiBaseUrl;
5
5
  private pricing;
6
+ private userDiscounts;
6
7
  private refreshTimer;
8
+ private userDiscountsRefreshTimer;
7
9
  private readonly defaultHeaders;
8
10
  constructor(options: ModelPricingClientOptions);
9
11
  /**
@@ -21,7 +23,12 @@ export declare class ModelPricingClient {
21
23
  */
22
24
  getModelPricing(filters?: ModelPricingFilters): ModelPricing[];
23
25
  private loadAll;
26
+ private loadPricing;
27
+ private loadUserDiscounts;
28
+ private indexUserDiscounts;
29
+ private applyUserDiscounts;
24
30
  private applyFilters;
31
+ private applyCreditOverrides;
25
32
  private toSuccessResponse;
26
33
  private throwIfError;
27
34
  private wrapError;
@@ -4,6 +4,7 @@ export declare enum UseCase {
4
4
  TextToVideo = "text-to-video",
5
5
  ImageToVideo = "image-to-video",
6
6
  VideoToVideo = "video-to-video",
7
+ VideoToImage = "video-to-image",
7
8
  TextToSpeech = "text-to-speech",
8
9
  TextToAudio = "text-to-audio",
9
10
  SpeechToText = "speech-to-text",
@@ -24,16 +25,29 @@ export declare enum PricingUnit {
24
25
  InputTokens = "input_tokens",
25
26
  InputTextTokens = "input_text_tokens",
26
27
  InputCachedTokens = "input_cached_tokens",
28
+ CacheWrite5mTokens = "cache_write_5m_tokens",
29
+ CacheWrite1hTokens = "cache_write_1h_tokens",
30
+ InputImageTokens = "input_image_tokens",
27
31
  OutputImageTokens = "output_image_tokens",
28
32
  OutputAudioTokens = "output_audio_tokens",
29
- OutputTextTokens = "output_text_tokens"
33
+ OutputTextTokens = "output_text_tokens",
34
+ InputMegapixel = "input_megapixel",
35
+ OutputMegapixel = "output_megapixel",
36
+ OutputMegapixelAdditional = "output_megapixel_additional",
37
+ ThousandOutputVideoTokens = "1k_output_video_tokens"
30
38
  }
31
39
  export interface ModelPricingFilters {
32
40
  vendor?: string;
33
41
  modelId?: string;
42
+ operationId?: string;
34
43
  useCase?: UseCase;
35
44
  quality?: string;
36
45
  audio?: boolean;
46
+ countryCode?: string;
47
+ touchpoint?: string;
48
+ platform?: string;
49
+ packageId?: string;
50
+ userId?: string;
37
51
  }
38
52
  export interface ModelPricingMetadata {
39
53
  vendor: string;
@@ -51,15 +65,41 @@ export interface VendorCostEntry {
51
65
  unit: PricingUnit;
52
66
  skus: SkuEntry[];
53
67
  }
68
+ export interface CreditOverride {
69
+ countries: string[];
70
+ touchpoints: string[];
71
+ /** Optional: older overrides created before platform targeting have no platforms. */
72
+ platforms?: string[];
73
+ /** Optional: older overrides created before package targeting have no packageIds. */
74
+ packageIds?: string[];
75
+ credits: number;
76
+ startDate: string;
77
+ endDate: string;
78
+ }
79
+ export interface MinTier {
80
+ name: string;
81
+ accessLevel: number;
82
+ }
54
83
  export interface ModelPricing {
55
84
  id: string;
56
85
  operationId: string;
57
86
  metadata: ModelPricingMetadata;
58
87
  vendorCosts: VendorCostEntry[];
59
88
  unit: PricingUnit;
89
+ /** Credits the user pays — already discounted when a user discount applies. */
60
90
  credits: number;
91
+ /**
92
+ * The original (pre-discount) credits, present only when a discount was
93
+ * applied. On the frontend the service fills both fields (userId travels via
94
+ * the access token in headers); on the backend the SDK fills them when
95
+ * getModelPricing is called with a userId.
96
+ */
97
+ originalCredits?: number;
61
98
  costPerUnit: number;
62
99
  legacy: boolean;
100
+ /** Minimum subscription tier required to use this model, when one is set. */
101
+ minTier?: MinTier;
102
+ creditOverrides: CreditOverride[];
63
103
  created: string;
64
104
  updated: string;
65
105
  }
@@ -67,6 +107,19 @@ export interface ModelPricingListResponse {
67
107
  status: string;
68
108
  response: ModelPricing[];
69
109
  }
110
+ export interface UserDiscount {
111
+ id: string;
112
+ userId: string;
113
+ modelId: string;
114
+ expirationDate: string;
115
+ discountPercent: number;
116
+ created: string;
117
+ updated: string;
118
+ }
119
+ export interface UserDiscountListResponse {
120
+ status: string;
121
+ response: UserDiscount[];
122
+ }
70
123
  export interface ModelPricingClientOptions {
71
124
  /** Base URL of the model pricing service. */
72
125
  baseUrl: string;
package/index.d.ts CHANGED
@@ -171,19 +171,14 @@ type ModelInputById = {
171
171
  };
172
172
  "flux-3-video": {
173
173
  prompt: string;
174
- model?: "flux-3-preview-high" | "flux-3-preview-optimized";
175
- aspectRatio?: "auto" | "21:9" | "16:9" | "4:3" | "1:1" | "3:4" | "9:16" | "9:21";
176
- resolution?: "480p" | "720p";
174
+ aspectRatio?: "auto" | "21:9" | "2:1" | "16:9" | "4:3" | "1:1" | "3:4" | "9:16";
175
+ resolution?: "hd" | "fhd";
177
176
  duration?: "auto" | "5" | "10" | "15" | "20";
178
- startFrame?: string;
179
- endFrame?: string;
180
177
  imageUrls?: string[];
181
178
  videoUrl?: string;
182
- videoUrls?: string[];
183
179
  generateAudio?: boolean;
184
- grounding?: boolean;
185
- seed?: number;
186
- version?: string;
180
+ safetyTolerance?: number;
181
+ draft?: boolean;
187
182
  };
188
183
  "flux-kontext-max": {
189
184
  prompt: string;
@@ -1256,6 +1251,39 @@ type ModelInputById = {
1256
1251
  generateAudio?: boolean;
1257
1252
  videoUrls: [string, ...string[]];
1258
1253
  };
1254
+ "seedance-2.5": {
1255
+ prompt: string;
1256
+ aspectRatio?: "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | "adaptive";
1257
+ resolution?: "480p" | "720p";
1258
+ duration?: 4 | 5 | 6 | 8 | 10 | 12 | 15 | 20 | 25 | 30;
1259
+ generateAudio?: boolean;
1260
+ returnLastFrame?: boolean;
1261
+ outputFormat?: "mp4" | "mov";
1262
+ imageUrls?: string[];
1263
+ videoUrls?: string[];
1264
+ audioUrls?: string[];
1265
+ startFrame?: string;
1266
+ endFrame?: string;
1267
+ };
1268
+ "seedance-2.5-video-edit": {
1269
+ prompt: string;
1270
+ aspectRatio?: "adaptive";
1271
+ resolution?: "480p" | "720p";
1272
+ generateAudio?: boolean;
1273
+ returnLastFrame?: boolean;
1274
+ outputFormat?: "mp4" | "mov";
1275
+ videoUrl: string;
1276
+ imageUrls?: string[];
1277
+ };
1278
+ "seedance-2.5-video-extend": {
1279
+ prompt: string;
1280
+ aspectRatio?: "adaptive";
1281
+ resolution?: "480p" | "720p";
1282
+ duration?: 4 | 5 | 6 | 8 | 10 | 12 | 15 | 20 | 25 | 30;
1283
+ generateAudio?: boolean;
1284
+ outputFormat?: "mp4" | "mov";
1285
+ videoUrls: [string, ...string[]];
1286
+ };
1259
1287
  "seedance-i2v": {
1260
1288
  prompt: string;
1261
1289
  aspectRatio?: "16:9" | "9:16" | "1:1" | "4:3" | "3:4" | "21:9" | "adaptive";
@@ -1279,6 +1307,14 @@ type ModelInputById = {
1279
1307
  imageUrls?: string[];
1280
1308
  negativePrompt?: string;
1281
1309
  };
1310
+ "seedream-4.7": {
1311
+ resolution?: "1K" | "2K" | "4K";
1312
+ prompt: string;
1313
+ aspectRatio?: "1:1" | "4:3" | "3:4" | "16:9" | "9:16" | "3:2" | "2:3" | "21:9";
1314
+ count?: 1 | 2 | 4 | 6 | 8 | 10;
1315
+ imageUrls?: string[];
1316
+ negativePrompt?: string;
1317
+ };
1282
1318
  "seedream-5.0-lite": {
1283
1319
  resolution?: "2K" | "3K";
1284
1320
  prompt: string;
@@ -2348,9 +2384,13 @@ declare const Models: {
2348
2384
  readonly Seedance20MiniVideoExtend: "seedance-2.0-mini-video-extend";
2349
2385
  readonly Seedance20VideoEdit: "seedance-2.0-video-edit";
2350
2386
  readonly Seedance20VideoExtend: "seedance-2.0-video-extend";
2387
+ readonly Seedance25: "seedance-2.5";
2388
+ readonly Seedance25VideoEdit: "seedance-2.5-video-edit";
2389
+ readonly Seedance25VideoExtend: "seedance-2.5-video-extend";
2351
2390
  readonly SeedanceI2v: "seedance-i2v";
2352
2391
  readonly Seedream40: "seedream-4.0";
2353
2392
  readonly Seedream45: "seedream-4.5";
2393
+ readonly Seedream47: "seedream-4.7";
2354
2394
  readonly Seedream50Lite: "seedream-5.0-lite";
2355
2395
  readonly Seedream50Pro: "seedream-5.0-pro";
2356
2396
  readonly Sora2: "sora-2";
package/index.js CHANGED
@@ -110,12 +110,15 @@ var require_ModelPricingClient = __commonJS({
110
110
  var ModelPricingServerError_1 = require_ModelPricingServerError();
111
111
  var ModelPricingUnknownError_1 = require_ModelPricingUnknownError();
112
112
  var DEFAULT_REFRESH_INTERVAL_MS = 6e5;
113
+ var USER_DISCOUNTS_REFRESH_INTERVAL_MS = 3e4;
113
114
  var DEFAULT_TIMEOUT_MS = 5e3;
114
115
  var ModelPricingClient2 = class {
115
116
  constructor(options) {
116
117
  var _a;
117
118
  this.pricing = null;
119
+ this.userDiscounts = null;
118
120
  this.refreshTimer = null;
121
+ this.userDiscountsRefreshTimer = null;
119
122
  this.defaultHeaders = {
120
123
  Accept: "application/json"
121
124
  };
@@ -134,13 +137,22 @@ var require_ModelPricingClient = __commonJS({
134
137
  const refreshIntervalMs = (_a = this.options.refreshIntervalMs) !== null && _a !== void 0 ? _a : DEFAULT_REFRESH_INTERVAL_MS;
135
138
  if (refreshIntervalMs > 0 && this.refreshTimer == null) {
136
139
  this.refreshTimer = setInterval(() => {
137
- this.loadAll().catch(() => {
140
+ this.loadPricing().catch(() => {
138
141
  });
139
142
  }, refreshIntervalMs);
140
143
  if (typeof this.refreshTimer.unref === "function") {
141
144
  this.refreshTimer.unref();
142
145
  }
143
146
  }
147
+ if (this.userDiscountsRefreshTimer == null) {
148
+ this.userDiscountsRefreshTimer = setInterval(() => {
149
+ this.loadUserDiscounts().catch(() => {
150
+ });
151
+ }, USER_DISCOUNTS_REFRESH_INTERVAL_MS);
152
+ if (typeof this.userDiscountsRefreshTimer.unref === "function") {
153
+ this.userDiscountsRefreshTimer.unref();
154
+ }
155
+ }
144
156
  });
145
157
  }
146
158
  /**
@@ -151,18 +163,34 @@ var require_ModelPricingClient = __commonJS({
151
163
  clearInterval(this.refreshTimer);
152
164
  this.refreshTimer = null;
153
165
  }
166
+ if (this.userDiscountsRefreshTimer != null) {
167
+ clearInterval(this.userDiscountsRefreshTimer);
168
+ this.userDiscountsRefreshTimer = null;
169
+ }
154
170
  }
155
171
  /**
156
172
  * Returns model pricings matching the given filters from the in-memory cache.
157
173
  * Throws if pricing has not been loaded yet — call and await init() first.
158
174
  */
159
175
  getModelPricing(filters = {}) {
176
+ var _a, _b, _c, _d, _e;
160
177
  if (this.pricing == null) {
161
178
  throw new Error("ModelPricingClient: pricing not loaded. Call and await init() before getModelPricing().");
162
179
  }
163
- return this.applyFilters(this.pricing, filters);
180
+ const filtered = this.applyFilters(this.pricing, filters);
181
+ const countryCode = ((_a = filters.countryCode) === null || _a === void 0 ? void 0 : _a.trim()) || void 0;
182
+ const touchpoint = ((_b = filters.touchpoint) === null || _b === void 0 ? void 0 : _b.trim()) || void 0;
183
+ const platform = ((_c = filters.platform) === null || _c === void 0 ? void 0 : _c.trim()) || void 0;
184
+ const packageId = ((_d = filters.packageId) === null || _d === void 0 ? void 0 : _d.trim()) || void 0;
185
+ const withOverrides = this.applyCreditOverrides(filtered, countryCode, touchpoint, platform, packageId);
186
+ return this.applyUserDiscounts(withOverrides, ((_e = filters.userId) === null || _e === void 0 ? void 0 : _e.trim()) || void 0);
164
187
  }
165
188
  loadAll() {
189
+ return __awaiter(this, void 0, void 0, function* () {
190
+ yield Promise.all([this.loadPricing(), this.loadUserDiscounts()]);
191
+ });
192
+ }
193
+ loadPricing() {
166
194
  return __awaiter(this, void 0, void 0, function* () {
167
195
  try {
168
196
  const url = `${this.modelPricingApiBaseUrl}/pricing-management/model-pricing`;
@@ -177,12 +205,75 @@ var require_ModelPricingClient = __commonJS({
177
205
  }
178
206
  });
179
207
  }
208
+ loadUserDiscounts() {
209
+ return __awaiter(this, void 0, void 0, function* () {
210
+ try {
211
+ const url = `${this.modelPricingApiBaseUrl}/pricing-management/user-discounts/public`;
212
+ const response = yield this._fetch(url, {
213
+ method: "GET",
214
+ signal: AbortSignal.timeout(this.options.timeoutMs)
215
+ });
216
+ const data = yield this.toSuccessResponse(response, "getUserDiscounts");
217
+ this.userDiscounts = this.indexUserDiscounts(data.response);
218
+ } catch (error) {
219
+ console.error(`ModelPricingClient: failed to load user discounts - ${error.message}`);
220
+ if (this.userDiscounts == null) {
221
+ this.userDiscounts = /* @__PURE__ */ new Map();
222
+ }
223
+ }
224
+ });
225
+ }
226
+ indexUserDiscounts(discounts) {
227
+ const index = /* @__PURE__ */ new Map();
228
+ for (const discount of discounts) {
229
+ let byModel = index.get(discount.userId);
230
+ if (byModel == null) {
231
+ byModel = /* @__PURE__ */ new Map();
232
+ index.set(discount.userId, byModel);
233
+ }
234
+ const list = byModel.get(discount.modelId);
235
+ if (list == null)
236
+ byModel.set(discount.modelId, [discount]);
237
+ else
238
+ list.push(discount);
239
+ }
240
+ return index;
241
+ }
242
+ applyUserDiscounts(items, userId) {
243
+ var _a;
244
+ if (userId == null)
245
+ return items;
246
+ const byModel = (_a = this.userDiscounts) === null || _a === void 0 ? void 0 : _a.get(userId);
247
+ if (byModel == null || byModel.size === 0)
248
+ return items;
249
+ const now = Date.now();
250
+ return items.map((item) => {
251
+ const discounts = byModel.get(item.metadata.modelId);
252
+ if (discounts == null || discounts.length === 0)
253
+ return item;
254
+ let bestPercent = 0;
255
+ for (const discount of discounts) {
256
+ const expiresAt = Date.parse(discount.expirationDate);
257
+ const active = Number.isNaN(expiresAt) || expiresAt >= now;
258
+ if (active && discount.discountPercent > bestPercent) {
259
+ bestPercent = discount.discountPercent;
260
+ }
261
+ }
262
+ if (bestPercent <= 0)
263
+ return item;
264
+ const pct = Math.min(bestPercent, 100);
265
+ const discounted = Math.round(item.credits * (1 - pct / 100));
266
+ return Object.assign(Object.assign({}, item), { credits: discounted, originalCredits: item.credits });
267
+ });
268
+ }
180
269
  applyFilters(items, filters) {
181
270
  return items.filter((item) => {
182
271
  if (filters.vendor != null && item.metadata.vendor !== filters.vendor)
183
272
  return false;
184
273
  if (filters.modelId != null && item.metadata.modelId !== filters.modelId)
185
274
  return false;
275
+ if (filters.operationId != null && item.operationId !== filters.operationId)
276
+ return false;
186
277
  if (filters.useCase != null && item.metadata.useCase !== filters.useCase)
187
278
  return false;
188
279
  if (filters.quality != null && item.metadata.quality !== filters.quality)
@@ -192,6 +283,31 @@ var require_ModelPricingClient = __commonJS({
192
283
  return true;
193
284
  });
194
285
  }
286
+ applyCreditOverrides(items, countryCode, touchpoint, platform, packageId) {
287
+ if (countryCode == null && touchpoint == null && platform == null && packageId == null)
288
+ return items;
289
+ console.log(`Applying credit overrides for countryCode: ${countryCode}, touchpoint: ${touchpoint}, platform: ${platform} and packageId: ${packageId}`);
290
+ return items.map((item) => {
291
+ var _a, _b, _c;
292
+ if (!((_a = item.creditOverrides) === null || _a === void 0 ? void 0 : _a.length))
293
+ return item;
294
+ let matchedCredits;
295
+ for (const co of item.creditOverrides) {
296
+ const countryMatch = co.countries.length === 0 || countryCode != null && co.countries.some((c) => c.toLowerCase() === countryCode.toLowerCase());
297
+ const touchpointMatch = co.touchpoints.length === 0 || touchpoint != null && co.touchpoints.some((t) => t.toLowerCase() === touchpoint.toLowerCase());
298
+ const platforms = (_b = co.platforms) !== null && _b !== void 0 ? _b : [];
299
+ const platformMatch = platforms.length === 0 || platform != null && platforms.some((p2) => p2.toLowerCase() === platform.toLowerCase());
300
+ const packageIds = (_c = co.packageIds) !== null && _c !== void 0 ? _c : [];
301
+ const packageMatch = packageIds.length === 0 || packageId != null && packageIds.some((p2) => p2.toLowerCase() === packageId.toLowerCase());
302
+ if (countryMatch && touchpointMatch && platformMatch && packageMatch) {
303
+ matchedCredits = co.credits;
304
+ }
305
+ }
306
+ if (matchedCredits == null)
307
+ return item;
308
+ return Object.assign(Object.assign({}, item), { credits: matchedCredits });
309
+ });
310
+ }
195
311
  toSuccessResponse(response, actionName) {
196
312
  return __awaiter(this, void 0, void 0, function* () {
197
313
  yield this.throwIfError(response, actionName);
@@ -258,6 +374,7 @@ var require_types = __commonJS({
258
374
  UseCase2["TextToVideo"] = "text-to-video";
259
375
  UseCase2["ImageToVideo"] = "image-to-video";
260
376
  UseCase2["VideoToVideo"] = "video-to-video";
377
+ UseCase2["VideoToImage"] = "video-to-image";
261
378
  UseCase2["TextToSpeech"] = "text-to-speech";
262
379
  UseCase2["TextToAudio"] = "text-to-audio";
263
380
  UseCase2["SpeechToText"] = "speech-to-text";
@@ -279,9 +396,16 @@ var require_types = __commonJS({
279
396
  PricingUnit2["InputTokens"] = "input_tokens";
280
397
  PricingUnit2["InputTextTokens"] = "input_text_tokens";
281
398
  PricingUnit2["InputCachedTokens"] = "input_cached_tokens";
399
+ PricingUnit2["CacheWrite5mTokens"] = "cache_write_5m_tokens";
400
+ PricingUnit2["CacheWrite1hTokens"] = "cache_write_1h_tokens";
401
+ PricingUnit2["InputImageTokens"] = "input_image_tokens";
282
402
  PricingUnit2["OutputImageTokens"] = "output_image_tokens";
283
403
  PricingUnit2["OutputAudioTokens"] = "output_audio_tokens";
284
404
  PricingUnit2["OutputTextTokens"] = "output_text_tokens";
405
+ PricingUnit2["InputMegapixel"] = "input_megapixel";
406
+ PricingUnit2["OutputMegapixel"] = "output_megapixel";
407
+ PricingUnit2["OutputMegapixelAdditional"] = "output_megapixel_additional";
408
+ PricingUnit2["ThousandOutputVideoTokens"] = "1k_output_video_tokens";
285
409
  })(PricingUnit || (exports.PricingUnit = PricingUnit = {}));
286
410
  }
287
411
  });
@@ -3844,9 +3968,186 @@ var buildSeedance20VideoExtendPayloadFor = (modelAlias) => (ctx) => ({
3844
3968
  resolution: ctx.resolution ?? "720p",
3845
3969
  generate_audio: ctx.generateAudio ?? false
3846
3970
  });
3971
+ var SEEDANCE_25_FRAME_ADAPTIVE_REASON = "First/Last Frame mode requires an adaptive aspect ratio \u2014 the vendor rejects any fixed ratio.";
3972
+ var seedance25Constraints = [
3973
+ ...seedance20Constraints.slice(1),
3974
+ {
3975
+ when: { startFrame: { exists: false } },
3976
+ then: {
3977
+ endFrame: {
3978
+ disabled: true,
3979
+ reason: "End frame needs a start frame \u2014 a last frame on its own is rejected."
3980
+ }
3981
+ }
3982
+ },
3983
+ // First/Last Frame mode: aspect ratio is locked to 'adaptive' (vendor errors
3984
+ // on any fixed ratio when a first_frame/last_frame is supplied).
3985
+ {
3986
+ when: { startFrame: { exists: true } },
3987
+ then: { aspectRatio: { allowed: ["adaptive"], reason: SEEDANCE_25_FRAME_ADAPTIVE_REASON } }
3988
+ },
3989
+ {
3990
+ when: { endFrame: { exists: true } },
3991
+ then: { aspectRatio: { allowed: ["adaptive"], reason: SEEDANCE_25_FRAME_ADAPTIVE_REASON } }
3992
+ }
3993
+ ];
3994
+ var buildSeedance25Payload = (ctx) => {
3995
+ const refImages = ctx.imageUrls ?? [];
3996
+ const refVideos = ctx.videoUrls ?? [];
3997
+ const refAudios = ctx.audioUrls ?? [];
3998
+ const usesFrame = Boolean(ctx.startFrame || ctx.endFrame);
3999
+ return {
4000
+ model: "seedance_2_5",
4001
+ content: [
4002
+ ...ctx.startFrame ? [{ type: "image_url", image_url: { url: ctx.startFrame }, role: "first_frame" }] : [],
4003
+ ...refImages.slice(0, 30).map((url) => ({
4004
+ type: "image_url",
4005
+ image_url: { url },
4006
+ role: "reference_image"
4007
+ })),
4008
+ ...refVideos.slice(0, 10).map((url) => ({
4009
+ type: "video_url",
4010
+ video_url: { url },
4011
+ role: "reference_video"
4012
+ })),
4013
+ ...refAudios.slice(0, 10).map((url) => ({
4014
+ type: "audio_url",
4015
+ audio_url: { url },
4016
+ role: "reference_audio"
4017
+ })),
4018
+ ...ctx.endFrame ? [{ type: "image_url", image_url: { url: ctx.endFrame }, role: "last_frame" }] : [],
4019
+ { type: "text", text: ctx.prompt }
4020
+ ],
4021
+ ratio: usesFrame ? "adaptive" : ctx.aspectRatio ?? "16:9",
4022
+ duration: ctx.duration ?? 5,
4023
+ resolution: ctx.resolution ?? "720p",
4024
+ generate_audio: ctx.generateAudio ?? false,
4025
+ output_format: ctx.outputFormat ?? "mp4",
4026
+ ...ctx.returnLastFrame ? { return_last_frame: true } : {}
4027
+ };
4028
+ };
4029
+ var buildSeedance25VideoEditPayload = (ctx) => ({
4030
+ model: "seedance_2_5",
4031
+ content: [
4032
+ { type: "text", text: ctx.prompt },
4033
+ { type: "video_url", video_url: { url: ctx.videoUrl }, role: "reference_video" },
4034
+ ...(ctx.imageUrls ?? []).slice(0, 30).map((url) => ({
4035
+ type: "image_url",
4036
+ image_url: { url },
4037
+ role: "reference_image"
4038
+ }))
4039
+ ],
4040
+ ratio: "adaptive",
4041
+ duration: -1,
4042
+ resolution: ctx.resolution ?? "720p",
4043
+ generate_audio: ctx.generateAudio ?? false,
4044
+ output_format: ctx.outputFormat ?? "mp4",
4045
+ ...ctx.returnLastFrame ? { return_last_frame: true } : {}
4046
+ });
4047
+ var buildSeedance25VideoExtendPayload = (ctx) => ({
4048
+ model: "seedance_2_5",
4049
+ content: [
4050
+ { type: "text", text: ctx.prompt },
4051
+ ...(ctx.videoUrls ?? []).slice(0, 10).map((url) => ({
4052
+ type: "video_url",
4053
+ video_url: { url },
4054
+ role: "reference_video"
4055
+ }))
4056
+ ],
4057
+ ratio: "adaptive",
4058
+ duration: ctx.duration ?? 15,
4059
+ resolution: ctx.resolution ?? "720p",
4060
+ generate_audio: ctx.generateAudio ?? false,
4061
+ output_format: ctx.outputFormat ?? "mp4"
4062
+ });
3847
4063
  var SEEDANCE_AR = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "adaptive"];
3848
4064
  var SEEDANCE_V2_DURATIONS = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
4065
+ var SEEDANCE_25_DURATIONS = [4, 5, 6, 8, 10, 12, 15, 20, 25, 30];
3849
4066
  var { MODELS: MODELS12 } = defineModels("seedance", [
4067
+ {
4068
+ id: "seedance-2.5",
4069
+ name: "Seedance 2.5",
4070
+ modelId: "seedance-2.5",
4071
+ addedAt: "2026-08-06",
4072
+ workflow: "seedance",
4073
+ buildPayload: buildSeedance25Payload,
4074
+ constraints: seedance25Constraints,
4075
+ estimatedTime: 20,
4076
+ mode: "video",
4077
+ inputType: "t2v",
4078
+ release: "preview",
4079
+ badge: ["new", "premium", "hot"],
4080
+ description: "Latest cinematic video with audio, multi-reference input, and mp4/mov output. Up to 30s.",
4081
+ features: [feat("Reference Image", "frame"), feat("Start/End Frame", "frame"), feat("Audio", "audio"), feat("720p", "resolution"), feat("4-30 sec", "duration")],
4082
+ paramConfig: {
4083
+ ...params.prompt(),
4084
+ ...params.aspectRatio(SEEDANCE_AR),
4085
+ ...params.resolution(["480p", "720p"], "720p"),
4086
+ ...params.duration(SEEDANCE_25_DURATIONS, 5),
4087
+ ...params.generateAudio(false),
4088
+ ...params.returnLastFrame(),
4089
+ ...p.enum("outputFormat", ["mp4", "mov"], "mp4", { label: "Format" }),
4090
+ // 2.5 lifts the reference caps to 30 images / 10 videos / 10 audios.
4091
+ ...params.imageInput(30, "Reference Images", false, "reference", SEEDANCE_MIN_PIXELS),
4092
+ ...params.videoInputs(10, "Reference Videos", false, SEEDANCE_MIN_PIXELS),
4093
+ ...params.audioInputs(10, "Reference Audios"),
4094
+ ...params.startFrame(),
4095
+ ...params.endFrame()
4096
+ }
4097
+ },
4098
+ {
4099
+ id: "seedance-2.5-video-edit",
4100
+ name: "Seedance 2.5 Video Edit",
4101
+ modelId: "seedance-2.5",
4102
+ addedAt: "2026-08-06",
4103
+ workflow: "seedance",
4104
+ buildPayload: buildSeedance25VideoEditPayload,
4105
+ estimatedTime: 60,
4106
+ mode: "video",
4107
+ inputType: "v2v",
4108
+ release: "preview",
4109
+ badge: ["new", "premium", "hot"],
4110
+ description: "Edit video \u2014 replace subjects, add or remove objects, restyle scenes with reference images.",
4111
+ features: [feat("Video Input", "input"), feat("Multi-Image Input", "input"), feat("Audio", "audio"), feat("720p", "resolution"), feat("Source length", "duration")],
4112
+ paramConfig: {
4113
+ ...params.prompt(),
4114
+ // Editing mode: aspect ratio is fixed to 'adaptive' and duration is
4115
+ // source-driven ('-1'), so neither is user-selectable (vendor rule).
4116
+ ...params.aspectRatio(["adaptive"]),
4117
+ ...params.resolution(["480p", "720p"], "720p"),
4118
+ ...params.generateAudio(false),
4119
+ ...params.returnLastFrame(),
4120
+ ...p.enum("outputFormat", ["mp4", "mov"], "mp4", { label: "Format" }),
4121
+ ...params.videoInput("Source Video"),
4122
+ ...params.imageInput(30, "Reference Images")
4123
+ }
4124
+ },
4125
+ {
4126
+ id: "seedance-2.5-video-extend",
4127
+ name: "Seedance 2.5 Video Extend",
4128
+ modelId: "seedance-2.5",
4129
+ addedAt: "2026-08-06",
4130
+ workflow: "seedance",
4131
+ buildPayload: buildSeedance25VideoExtendPayload,
4132
+ estimatedTime: 200,
4133
+ mode: "video",
4134
+ inputType: "v2v",
4135
+ release: "preview",
4136
+ badge: ["new", "premium", "hot"],
4137
+ description: "Stitch up to 10 clips into one continuous, extended video.",
4138
+ features: [feat("Multi-Video Input", "input"), feat("Audio", "audio"), feat("720p", "resolution"), feat("4-30 sec", "duration")],
4139
+ paramConfig: {
4140
+ ...params.prompt(),
4141
+ // Extension mode: aspect ratio is locked to 'adaptive' (vendor rule);
4142
+ // duration stays user-selectable.
4143
+ ...params.aspectRatio(["adaptive"]),
4144
+ ...params.resolution(["480p", "720p"], "720p"),
4145
+ ...params.duration(SEEDANCE_25_DURATIONS, 15),
4146
+ ...params.generateAudio(false),
4147
+ ...p.enum("outputFormat", ["mp4", "mov"], "mp4", { label: "Format" }),
4148
+ ...params.videoInputs(10, "Source Videos", true)
4149
+ }
4150
+ },
3850
4151
  {
3851
4152
  id: "seedance-2.0",
3852
4153
  name: "Seedance 2.0",
@@ -4230,6 +4531,7 @@ function buildSeedreamV2(modelId) {
4230
4531
  }
4231
4532
  var buildSeedream40Payload = buildSeedreamV2("seedream_4_0");
4232
4533
  var buildSeedream45Payload = buildSeedreamV2("seedream_4_5");
4534
+ var buildSeedream47Payload = buildSeedreamV2("seedream_4_7");
4233
4535
  var buildSeedream50LitePayload = buildSeedreamV2("seedream_5_0_lite");
4234
4536
  var buildSeedream50ProPayload = buildSeedreamV2("seedream_5_0_pro");
4235
4537
  var seedreamV2Params = {
@@ -4286,6 +4588,23 @@ var { MODELS: MODELS14 } = defineModels("seedream", [
4286
4588
  ...seedreamV2Params
4287
4589
  }
4288
4590
  },
4591
+ {
4592
+ id: "seedream-4.7",
4593
+ name: "Seedream 4.7",
4594
+ modelId: "seedream_4_7",
4595
+ addedAt: "2026-08-06",
4596
+ workflow: "seedream",
4597
+ buildPayload: buildSeedream47Payload,
4598
+ estimatedTime: { "1K": 12, "2K": 21, "4K": 58 },
4599
+ mode: "image",
4600
+ inputType: "t2i",
4601
+ description: "Reliable all-purpose generation with readable text overlay.",
4602
+ features: [feat("Multi-Image Input", "input"), feat("4K", "resolution")],
4603
+ paramConfig: {
4604
+ ...params.resolution(["1K", "2K", "4K"]),
4605
+ ...seedreamV2Params
4606
+ }
4607
+ },
4289
4608
  {
4290
4609
  id: "seedream-4.5",
4291
4610
  name: "Seedream 4.5",
@@ -5042,6 +5361,7 @@ var buildGrokTTSPayload = (ctx) => ({
5042
5361
  language: ctx.language ?? "auto",
5043
5362
  voice_id: ctx.voiceId ?? DEFAULT_GROK_VOICE_ID
5044
5363
  });
5364
+ var GROK_VIDEO_PROMPT_MAX = 4096;
5045
5365
  var GROK_VIDEO_AR = ["16:9", "9:16", "1:1", "4:3", "3:4", "3:2", "2:3"];
5046
5366
  var GROK_IMAGE_AR = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "2:1", "1:2", "19.5:9", "9:19.5", "20:9", "9:20"];
5047
5367
  var GROK_DURATIONS = [3, 5, 6, 8, 10, 12, 15];
@@ -5065,7 +5385,7 @@ var { MODELS: MODELS17 } = defineModels("grok", [
5065
5385
  description: "Fastest generation pipeline \u2014 720p with audio in seconds, up to 15s.",
5066
5386
  features: [feat("Image Input", "input"), feat("Start Frame", "frame"), feat("Audio", "audio"), feat("720p", "resolution"), feat("15 sec", "duration")],
5067
5387
  paramConfig: {
5068
- ...params.prompt(),
5388
+ ...params.prompt({ maxLength: GROK_VIDEO_PROMPT_MAX }),
5069
5389
  ...params.aspectRatio(GROK_VIDEO_AR),
5070
5390
  ...params.resolution(GROK_VIDEO_RESOLUTIONS, "720p"),
5071
5391
  ...params.duration(GROK_DURATIONS, 6),
@@ -5087,7 +5407,7 @@ var { MODELS: MODELS17 } = defineModels("grok", [
5087
5407
  description: "Next-gen Grok video \u2014 faster, higher fidelity, up to 15s with audio.",
5088
5408
  features: [feat("Image Input", "input"), feat("Audio", "audio"), feat("1080p", "resolution"), feat("15 sec", "duration")],
5089
5409
  paramConfig: {
5090
- ...params.prompt(),
5410
+ ...params.prompt({ maxLength: GROK_VIDEO_PROMPT_MAX }),
5091
5411
  ...params.aspectRatio(GROK_VIDEO_AR),
5092
5412
  ...params.resolution(GROK_VIDEO_RESOLUTIONS_15, "720p"),
5093
5413
  ...params.duration(GROK_DURATIONS, 8),
@@ -5107,7 +5427,7 @@ var { MODELS: MODELS17 } = defineModels("grok", [
5107
5427
  description: "Restyle or remix an existing video with a new prompt direction.",
5108
5428
  features: [feat("Video Input", "input"), feat("Up to 8s", "duration")],
5109
5429
  paramConfig: {
5110
- ...params.prompt(),
5430
+ ...params.prompt({ maxLength: GROK_VIDEO_PROMPT_MAX }),
5111
5431
  ...params.videoInput("Source Video", "reference", true, 8)
5112
5432
  }
5113
5433
  },
@@ -5124,7 +5444,7 @@ var { MODELS: MODELS17 } = defineModels("grok", [
5124
5444
  description: "Extend an existing video forward with a new prompt \u2014 up to 10 seconds.",
5125
5445
  features: [feat("Video Input", "input"), feat("Up to 10s", "duration")],
5126
5446
  paramConfig: {
5127
- ...params.prompt(),
5447
+ ...params.prompt({ maxLength: GROK_VIDEO_PROMPT_MAX }),
5128
5448
  ...params.duration([3, 5, 6, 8, 10], 6),
5129
5449
  ...params.videoInput("Source Video")
5130
5450
  }
@@ -5699,6 +6019,11 @@ var fluxKontextBase = {
5699
6019
  mode: "image",
5700
6020
  inputType: "t2i"
5701
6021
  };
6022
+ var flux3VideoConstraints = [
6023
+ { when: { draft: { is: true } }, then: {
6024
+ resolution: { allowed: ["hd"], reason: "Draft mode only supports HD resolution." }
6025
+ } }
6026
+ ];
5702
6027
  var { MODELS: MODELS21 } = defineModels("flux", [
5703
6028
  {
5704
6029
  ...fluxV2Base,
@@ -5787,52 +6112,39 @@ var { MODELS: MODELS21 } = defineModels("flux", [
5787
6112
  }
5788
6113
  },
5789
6114
  {
5790
- // Single workflow `flux/v1/video` handles t2v plus every conditioning
5791
- // mode (i2v via start frame, morph via start/end frame, reference images,
5792
- // reference video, video continuation) through optional inputs — no
6115
+ // Single workflow `flux/v1/video` derives its mode from the input it's
6116
+ // given: none t2v, keyframe images i2v, a start video → v2v. No
5793
6117
  // editWorkflow needed. Payload assembly lives in flux.payloads.ts.
5794
6118
  id: "flux-3-video",
5795
6119
  name: "Flux 3 Video",
5796
6120
  workflow: "flux/v1/video",
5797
6121
  mode: "video",
5798
6122
  inputType: "t2v",
5799
- release: "preview",
5800
6123
  addedAt: "2026-07-27",
5801
6124
  estimatedTime: 120,
5802
- description: "Text-to-video with synchronized audio, plus image and video conditioning (continuation, references, first/last frame).",
6125
+ constraints: flux3VideoConstraints,
6126
+ description: "Text-to-video with synchronized audio, plus image-to-video (animate up to 10 images) and video continuation.",
5803
6127
  features: [
5804
6128
  feat("Image & Video Input", "input"),
5805
- feat("Start/End Frame", "frame"),
5806
6129
  feat("Audio", "audio"),
5807
6130
  feat("Up to 20s", "duration"),
5808
- feat("720p", "resolution")
6131
+ feat("1080p", "resolution")
5809
6132
  ],
5810
6133
  paramConfig: {
5811
6134
  ...params.prompt(),
5812
- // Checkpoint: `high` (default, full conditioning + draft) vs `optimized`
5813
- // (faster, text-to-video only). Sent as the wire `model` field.
5814
- ...p.enum("model", [
5815
- { id: "flux-3-preview-high", label: "High" },
5816
- { id: "flux-3-preview-optimized", label: "Optimized" }
5817
- ], "flux-3-preview-high", { label: "Model" }),
5818
- ...params.aspectRatio(["auto", "21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "9:21"], "auto"),
5819
- ...params.resolution(["480p", "720p"], "720p"),
5820
- // 'auto' lets the model fit length; an explicit whole number is required
5821
- // for a two-image (start+end) morph.
6135
+ ...params.aspectRatio(["auto", "21:9", "2:1", "16:9", "4:3", "1:1", "3:4", "9:16"], "auto"),
6136
+ ...params.resolution(["hd", "fhd"], "hd"),
6137
+ // 'auto' lets the model fit length; or a whole number of seconds (5–20).
5822
6138
  ...p.enum("duration", ["auto", "5", "10", "15", "20"], "auto", { label: "Duration" }),
5823
- // startFrame → keyframe @0 (i2v); endFrame keyframe @duration×24 (morph).
5824
- ...params.startFrame("Start Frame"),
5825
- ...params.endFrame("End Frame"),
5826
- // referenceImages (ir2v): who/what appears, never shown on screen.
5827
- ...params.imageInput(10, "Reference Images", false, "reference"),
5828
- // startVideo (f2v): continue from a clip's final frames.
6139
+ // keyframes (i2v): 1–10 images to animate. Providing these selects i2v mode.
6140
+ ...params.imageInput(10, "Images", false, "asset"),
6141
+ // startVideo (v2v): continue from a clip's final frames.
5829
6142
  ...params.videoInput("Start Video", "asset", false, 15),
5830
- // referenceVideo (vr2v): carry subjects into a brand-new clip.
5831
- ...params.videoInputs(1, "Reference Video", false),
5832
6143
  ...params.generateAudio(true),
5833
- ...p.boolean("grounding", true, "Grounding"),
5834
- ...p.range("seed", 0, 4294967295, 0, { label: "Seed" }),
5835
- ...p.text("version", { label: "Version", placeholder: "latest" })
6144
+ // Moderation level: 0 (strict) 4 (permissive).
6145
+ ...p.range("safetyTolerance", 0, 4, 2, { label: "Safety Tolerance" }),
6146
+ // draft: fast low-step preview.
6147
+ ...p.boolean("draft", false, "Draft")
5836
6148
  }
5837
6149
  }
5838
6150
  ]);
@@ -5840,29 +6152,19 @@ var { MODELS: MODELS21 } = defineModels("flux", [
5840
6152
  // src/vendors/catalog/flux.payloads.ts
5841
6153
  var buildFlux3VideoPayload = (input) => {
5842
6154
  const duration = input.duration && input.duration !== "auto" ? Number(input.duration) : "auto";
5843
- const keyframes = [];
5844
- if (input.startFrame) keyframes.push({ imageUrl: input.startFrame, frameIndex: 0 });
5845
- if (input.endFrame && typeof duration === "number") {
5846
- keyframes.push({ imageUrl: input.endFrame, frameIndex: duration * 24 });
5847
- }
5848
6155
  return {
5849
6156
  prompt: input.prompt,
5850
- model: input.model ?? "flux-3-preview-high",
5851
6157
  aspectRatio: input.aspectRatio ?? "auto",
5852
- resolution: input.resolution ?? "720p",
6158
+ resolution: input.resolution ?? "hd",
5853
6159
  duration,
5854
6160
  generateAudio: input.generateAudio ?? true,
5855
- grounding: input.grounding ?? true,
5856
- ...keyframes.length ? { keyframes } : {},
5857
- // referenceImages (ir2v) reference images that define who/what appears.
5858
- ...input.imageUrls?.length ? { referenceImages: input.imageUrls } : {},
5859
- // startVideo (f2v) — continue from a clip's final frames.
6161
+ safetyTolerance: input.safetyTolerance ?? 2,
6162
+ // keyframes (i2v): 1–10 images to animate.
6163
+ ...input.imageUrls?.length ? { keyframes: input.imageUrls } : {},
6164
+ // startVideo (v2v): continue from a clip's final frames.
5860
6165
  ...input.videoUrl ? { startVideo: input.videoUrl } : {},
5861
- // referenceVideo (vr2v) — carry a clip's subjects into a brand-new video.
5862
- ...input.videoUrls?.length ? { referenceVideo: input.videoUrls[0] } : {},
5863
- // seed omitted when unset → vendor randomizes.
5864
- ...input.seed != null ? { seed: input.seed } : {},
5865
- ...input.version ? { version: input.version } : {}
6166
+ // draft: fast low-step preview.
6167
+ ...input.draft ? { draft: input.draft } : {}
5866
6168
  };
5867
6169
  };
5868
6170
  registerPayloads(MODELS21, {
@@ -10700,9 +11002,13 @@ var Seedance20MiniVideoEdit = "seedance-2.0-mini-video-edit";
10700
11002
  var Seedance20MiniVideoExtend = "seedance-2.0-mini-video-extend";
10701
11003
  var Seedance20VideoEdit = "seedance-2.0-video-edit";
10702
11004
  var Seedance20VideoExtend = "seedance-2.0-video-extend";
11005
+ var Seedance25 = "seedance-2.5";
11006
+ var Seedance25VideoEdit = "seedance-2.5-video-edit";
11007
+ var Seedance25VideoExtend = "seedance-2.5-video-extend";
10703
11008
  var SeedanceI2v = "seedance-i2v";
10704
11009
  var Seedream40 = "seedream-4.0";
10705
11010
  var Seedream45 = "seedream-4.5";
11011
+ var Seedream47 = "seedream-4.7";
10706
11012
  var Seedream50Lite = "seedream-5.0-lite";
10707
11013
  var Seedream50Pro = "seedream-5.0-pro";
10708
11014
  var Sora2 = "sora-2";
@@ -10900,9 +11206,13 @@ var Models = {
10900
11206
  Seedance20MiniVideoExtend,
10901
11207
  Seedance20VideoEdit,
10902
11208
  Seedance20VideoExtend,
11209
+ Seedance25,
11210
+ Seedance25VideoEdit,
11211
+ Seedance25VideoExtend,
10903
11212
  SeedanceI2v,
10904
11213
  Seedream40,
10905
11214
  Seedream45,
11215
+ Seedream47,
10906
11216
  Seedream50Lite,
10907
11217
  Seedream50Pro,
10908
11218
  Sora2,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picsart/ai-sdk",
3
- "version": "3.32.0",
3
+ "version": "3.35.5",
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",