@picsart/ai-sdk 6.41.0 → 6.42.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.
Files changed (3) hide show
  1. package/index.d.ts +13 -0
  2. package/index.js +89 -8
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -650,6 +650,8 @@ type ModelInputById = {
650
650
  "gpt-image-2.5-flare": {
651
651
  prompt: string;
652
652
  aspectRatio?: "1:1" | "3:2" | "2:3" | "16:9" | "9:16" | "4:3" | "3:4" | "auto";
653
+ resolution?: "1K" | "2K" | "4K";
654
+ size?: string;
653
655
  quality?: "max" | "xhigh" | "high" | "medium" | "low";
654
656
  background?: "opaque" | "transparent";
655
657
  outputFormat?: "png" | "jpeg" | "webp";
@@ -659,6 +661,8 @@ type ModelInputById = {
659
661
  "gpt-image-2.5-sunburst": {
660
662
  prompt: string;
661
663
  aspectRatio?: "1:1" | "3:2" | "2:3" | "16:9" | "9:16" | "4:3" | "3:4" | "auto";
664
+ resolution?: "1K" | "2K" | "4K";
665
+ size?: string;
662
666
  quality?: "max" | "xhigh" | "high" | "medium" | "low";
663
667
  background?: "opaque" | "transparent";
664
668
  outputFormat?: "png" | "jpeg" | "webp";
@@ -2646,6 +2650,8 @@ interface GenerationContext {
2646
2650
  /** Qwen 3.0 family — thinking mode (requires prompt_extend), sent as `enable_thinking`. */
2647
2651
  enableThinking?: boolean;
2648
2652
  }
2653
+ /** See `ModelDefinition.validateInput`. */
2654
+ type InputValidator = (input: Record<string, unknown>) => void;
2649
2655
  type PayloadBuilder<TContext extends GenerationContext = GenerationContext> = (ctx: TContext) => object;
2650
2656
  /** Lightweight runtime schema contract used by SDK integrations. */
2651
2657
  interface RuntimeSchema<T = unknown> {
@@ -2736,6 +2742,13 @@ interface ModelDefinition {
2736
2742
  paramConfig: ModelParams;
2737
2743
  /** Declarative inter-parameter constraints (e.g. "1080p requires 8s duration"). */
2738
2744
  constraints?: Constraint[];
2745
+ /**
2746
+ * Model-specific input check that the declarative layer cannot express —
2747
+ * a value format, or a "this OR those, never both" rule. Runs after the
2748
+ * per-param and constraint validation, on the raw input (no defaults
2749
+ * merged), and throws an `Error` whose message names the offending param.
2750
+ */
2751
+ validateInput?: InputValidator;
2739
2752
  /** Payload builder. Optional — omit for pass-through (param values sent as-is). */
2740
2753
  buildPayload?: PayloadBuilder;
2741
2754
  /** I2V/edit payload builder when different from buildPayload. */
package/index.js CHANGED
@@ -591,7 +591,7 @@ function validateDescriptor(key, d, val, required) {
591
591
  function isAbsent(val) {
592
592
  return val == null || typeof val === "string" && val.trim().length === 0 || Array.isArray(val) && val.length === 0;
593
593
  }
594
- function validateAll(params2, input, constraints) {
594
+ function validateAll(params2, input, constraints, validateInput) {
595
595
  for (const [key, entry] of Object.entries(params2)) {
596
596
  validateDescriptor(key, entry.descriptor, input[key], entry.required);
597
597
  }
@@ -600,6 +600,7 @@ function validateAll(params2, input, constraints) {
600
600
  throw new Error(requirement.reason ? `"${key}" is required: ${requirement.reason}` : `"${key}" is required`);
601
601
  }
602
602
  }
603
+ validateInput?.(input);
603
604
  }
604
605
  function descriptorsToSchema(params2) {
605
606
  const schema = {};
@@ -1209,6 +1210,7 @@ function defineModels(provider, configs) {
1209
1210
  if (c.release !== void 0) model.release = c.release;
1210
1211
  if (c.modelId !== void 0) model.modelId = c.modelId;
1211
1212
  if (c.constraints !== void 0) model.constraints = c.constraints;
1213
+ if (c.validateInput !== void 0) model.validateInput = c.validateInput;
1212
1214
  const contract = createModelContract(model);
1213
1215
  model.outputSchema = c.outputSchema ?? contract.output;
1214
1216
  MODELS40.push(model);
@@ -7155,6 +7157,54 @@ var GPT_IMAGE_2_AR_TO_SIZE = {
7155
7157
  "4:3": "1360x1024",
7156
7158
  "3:4": "1024x1360"
7157
7159
  };
7160
+ var GPT_IMAGE_25_SIZES = {
7161
+ "1K": GPT_IMAGE_2_AR_TO_SIZE,
7162
+ "2K": {
7163
+ "1:1": "2048x2048",
7164
+ "3:2": "2496x1664",
7165
+ "2:3": "1664x2496",
7166
+ "16:9": "2560x1440",
7167
+ "9:16": "1440x2560",
7168
+ "4:3": "2304x1728",
7169
+ "3:4": "1728x2304"
7170
+ },
7171
+ "4K": {
7172
+ "1:1": "2880x2880",
7173
+ "3:2": "3504x2336",
7174
+ "2:3": "2336x3504",
7175
+ "16:9": "3840x2160",
7176
+ "9:16": "2160x3840",
7177
+ "4:3": "3264x2448",
7178
+ "3:4": "2448x3264"
7179
+ }
7180
+ };
7181
+ var GPT_IMAGE_SIZE_PATTERN = /^([1-9]\d*)x([1-9]\d*)$/;
7182
+ var GPT_IMAGE_SIZE_GRID = 16;
7183
+ var GPT_IMAGE_MAX_ASPECT_RATIO = 3;
7184
+ var GPT_IMAGE_MAX_EDGE = 3840;
7185
+ var GPT_IMAGE_MIN_PIXELS = 655360;
7186
+ var GPT_IMAGE_MAX_PIXELS = 8294400;
7187
+ function gptImageSizeViolation(size) {
7188
+ const match = GPT_IMAGE_SIZE_PATTERN.exec(size);
7189
+ if (!match) return "must be WIDTHxHEIGHT, e.g. 2048x1152";
7190
+ const width = Number(match[1]);
7191
+ const height = Number(match[2]);
7192
+ if (width % GPT_IMAGE_SIZE_GRID !== 0 || height % GPT_IMAGE_SIZE_GRID !== 0) {
7193
+ return `both dimensions must be divisible by ${GPT_IMAGE_SIZE_GRID}`;
7194
+ }
7195
+ const ratio = width / height;
7196
+ if (ratio > GPT_IMAGE_MAX_ASPECT_RATIO || ratio < 1 / GPT_IMAGE_MAX_ASPECT_RATIO) {
7197
+ return "the aspect ratio must be between 1:3 and 3:1";
7198
+ }
7199
+ if (Math.max(width, height) > GPT_IMAGE_MAX_EDGE) {
7200
+ return `the longest edge must be at most ${GPT_IMAGE_MAX_EDGE}`;
7201
+ }
7202
+ const pixels = width * height;
7203
+ if (pixels < GPT_IMAGE_MIN_PIXELS || pixels > GPT_IMAGE_MAX_PIXELS) {
7204
+ return `the total pixel count must be between ${GPT_IMAGE_MIN_PIXELS} and ${GPT_IMAGE_MAX_PIXELS}`;
7205
+ }
7206
+ return null;
7207
+ }
7158
7208
  var buildGptImage1Payload = (ctx) => ({
7159
7209
  prompt: ctx.prompt,
7160
7210
  model: "gpt-image-1",
@@ -7219,6 +7269,7 @@ var buildGptImage2EditPayload = (ctx) => ({
7219
7269
  var GPT_IMAGE_PROMPT_MAX = 32e3;
7220
7270
  var GPT_IMAGE_25_QUALITIES = ["max", "xhigh", "high", "medium", "low"];
7221
7271
  var GPT_IMAGE_25_ASPECT_RATIOS = ["1:1", "3:2", "2:3", "16:9", "9:16", "4:3", "3:4", "auto"];
7272
+ var GPT_IMAGE_25_RESOLUTIONS = Object.keys(GPT_IMAGE_25_SIZES);
7222
7273
  var GPT_IMAGE_25_MAX_INPUT_IMAGES = 16;
7223
7274
  var gptImage2Constraints = [
7224
7275
  {
@@ -7236,6 +7287,25 @@ var gptImageBgConstraints = [
7236
7287
  then: { outputFormat: { allowed: ["png", "webp"], reason: "Transparent background needs PNG or WEBP \u2014 JPEG has no alpha channel." } }
7237
7288
  }
7238
7289
  ];
7290
+ var gptImage25SizeConstraints = [
7291
+ {
7292
+ when: { size: { exists: true } },
7293
+ then: {
7294
+ aspectRatio: { disabled: true, reason: "A custom size sets the output size." },
7295
+ resolution: { disabled: true, reason: "A custom size sets the output size." }
7296
+ }
7297
+ },
7298
+ {
7299
+ when: { aspectRatio: { is: "auto" } },
7300
+ then: { resolution: { disabled: true, reason: "Auto lets the model pick the size." } }
7301
+ }
7302
+ ];
7303
+ var isGiven = (value) => value != null && !(typeof value === "string" && value.trim().length === 0);
7304
+ var validateGptImage25Input = (input) => {
7305
+ if (!isGiven(input.size)) return;
7306
+ const violation = gptImageSizeViolation(String(input.size).trim());
7307
+ if (violation) throw new Error(`"size" ${violation}`);
7308
+ };
7239
7309
  var { MODELS: MODELS23 } = defineModels("openai", [
7240
7310
  // ── Image ─────────────────────────────────────────
7241
7311
  {
@@ -7252,13 +7322,16 @@ var { MODELS: MODELS23 } = defineModels("openai", [
7252
7322
  paramConfig: {
7253
7323
  ...params.prompt({ maxLength: GPT_IMAGE_PROMPT_MAX }),
7254
7324
  ...params.aspectRatio(GPT_IMAGE_25_ASPECT_RATIOS, "1:1"),
7325
+ ...params.resolution(GPT_IMAGE_25_RESOLUTIONS, "1K"),
7326
+ ...p.text("size", { label: "Custom Size", placeholder: "WIDTHxHEIGHT, e.g. 2048x1152" }),
7255
7327
  ...p.quality(GPT_IMAGE_25_QUALITIES, "high"),
7256
7328
  ...p.enum("background", ["opaque", "transparent"], "opaque", { label: "Background" }),
7257
7329
  ...p.enum("outputFormat", ["png", "jpeg", "webp"], "png", { label: "Format" }),
7258
7330
  ...params.count(),
7259
7331
  ...params.imageInput(GPT_IMAGE_25_MAX_INPUT_IMAGES, "Source Images")
7260
7332
  },
7261
- constraints: gptImageBgConstraints
7333
+ constraints: [...gptImageBgConstraints, ...gptImage25SizeConstraints],
7334
+ validateInput: validateGptImage25Input
7262
7335
  },
7263
7336
  {
7264
7337
  id: "gpt-image-2.5-flare",
@@ -7274,13 +7347,16 @@ var { MODELS: MODELS23 } = defineModels("openai", [
7274
7347
  paramConfig: {
7275
7348
  ...params.prompt({ maxLength: GPT_IMAGE_PROMPT_MAX }),
7276
7349
  ...params.aspectRatio(GPT_IMAGE_25_ASPECT_RATIOS, "1:1"),
7350
+ ...params.resolution(GPT_IMAGE_25_RESOLUTIONS, "1K"),
7351
+ ...p.text("size", { label: "Custom Size", placeholder: "WIDTHxHEIGHT, e.g. 2048x1152" }),
7277
7352
  ...p.quality(GPT_IMAGE_25_QUALITIES, "high"),
7278
7353
  ...p.enum("background", ["opaque", "transparent"], "opaque", { label: "Background" }),
7279
7354
  ...p.enum("outputFormat", ["png", "jpeg", "webp"], "png", { label: "Format" }),
7280
7355
  ...params.count(),
7281
7356
  ...params.imageInput(GPT_IMAGE_25_MAX_INPUT_IMAGES, "Source Images")
7282
7357
  },
7283
- constraints: gptImageBgConstraints
7358
+ constraints: [...gptImageBgConstraints, ...gptImage25SizeConstraints],
7359
+ validateInput: validateGptImage25Input
7284
7360
  },
7285
7361
  {
7286
7362
  id: "gpt-image-2",
@@ -7363,12 +7439,17 @@ var { MODELS: MODELS23 } = defineModels("openai", [
7363
7439
  ]);
7364
7440
 
7365
7441
  // src/vendors/catalog/openai.payloads.ts
7366
- var resolveSize = (aspectRatio, fallback) => aspectRatio === "auto" ? "auto" : GPT_IMAGE_2_AR_TO_SIZE[aspectRatio ?? ""] ?? fallback;
7442
+ var resolveSize = (input, defaultAspectRatio) => {
7443
+ if (input.size?.trim()) return input.size.trim();
7444
+ const aspectRatio = input.aspectRatio ?? defaultAspectRatio;
7445
+ if (aspectRatio === "auto") return "auto";
7446
+ return GPT_IMAGE_25_SIZES[input.resolution ?? "1K"]?.[aspectRatio] ?? "1024x1024";
7447
+ };
7367
7448
  var generateFor = (model) => (input) => ({
7368
7449
  prompt: input.prompt,
7369
7450
  model,
7370
7451
  n: input.count ?? 1,
7371
- size: resolveSize(input.aspectRatio, "1024x1024"),
7452
+ size: resolveSize(input, "1:1"),
7372
7453
  quality: input.quality ?? "high",
7373
7454
  ...input.background ? { background: input.background } : {},
7374
7455
  ...input.outputFormat ? { output_format: input.outputFormat } : {}
@@ -7378,7 +7459,7 @@ var editFor = (model) => (input) => ({
7378
7459
  model,
7379
7460
  images: input.imageUrls ?? [],
7380
7461
  n: input.count ?? 1,
7381
- size: resolveSize(input.aspectRatio, "auto"),
7462
+ size: resolveSize(input, "auto"),
7382
7463
  quality: input.quality ?? "high",
7383
7464
  ...input.background ? { background: input.background } : {},
7384
7465
  ...input.outputFormat ? { output_format: input.outputFormat } : {}
@@ -11375,7 +11456,7 @@ function buildInputSchema(model) {
11375
11456
  parse(input) {
11376
11457
  requireObject(input, `Invalid input for model "${model.id}"`);
11377
11458
  try {
11378
- validateAll(model.paramConfig, input, model.constraints);
11459
+ validateAll(model.paramConfig, input, model.constraints, model.validateInput);
11379
11460
  } catch (err) {
11380
11461
  if (err instanceof ApiError) throw err;
11381
11462
  throw new ApiError(err instanceof Error ? err.message : String(err), {
@@ -12153,7 +12234,7 @@ var ModelDescriptorImpl = class {
12153
12234
  return { valid: false, errors: [`Invalid input for model "${this.def.id}"`] };
12154
12235
  }
12155
12236
  try {
12156
- validateAll(this.def.paramConfig, input, this.def.constraints);
12237
+ validateAll(this.def.paramConfig, input, this.def.constraints, this.def.validateInput);
12157
12238
  return { valid: true };
12158
12239
  } catch (err) {
12159
12240
  return { valid: false, errors: [err instanceof Error ? err.message : String(err)] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picsart/ai-sdk",
3
- "version": "6.41.0",
3
+ "version": "6.42.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",