@shop-os/modelkit 0.1.3 → 0.1.4
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 +17 -17
- package/dist/index.cjs +91 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +91 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -12,7 +12,7 @@ import { z } from 'zod';
|
|
|
12
12
|
/** The AI SDK video model spelling: a catalog id or a provider video model instance. */
|
|
13
13
|
type VideoModel = Parameters<typeof experimental_generateVideo>[0]["model"];
|
|
14
14
|
type AspectRatio = "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "4:5" | "5:4" | "21:9" | "9:21" | "97:30" | "adaptive";
|
|
15
|
-
type ImageSize = "1K" | "2K" | "4K";
|
|
15
|
+
type ImageSize = "512" | "1K" | "2K" | "4K";
|
|
16
16
|
type VideoResolution = "360p" | "480p" | "720p" | "768p" | "1080p" | "2k" | "4k";
|
|
17
17
|
/** "xhigh" and "max" exist only on gpt-image-2.5; gpt-image-2 rejects them at the provider. */
|
|
18
18
|
type ImageQuality = "auto" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -37,6 +37,8 @@ interface ImageRequest {
|
|
|
37
37
|
seed?: number;
|
|
38
38
|
count?: number;
|
|
39
39
|
outputFormat?: OutputFormat;
|
|
40
|
+
/** Upscale factor for upscaler rows; adapters map it to the provider's field. */
|
|
41
|
+
scaleFactor?: number;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* What a caller passes to generateImage. Same field names as the AI SDK's
|
|
@@ -120,7 +122,7 @@ interface MediaPart {
|
|
|
120
122
|
cleanup?: () => Promise<void>;
|
|
121
123
|
}
|
|
122
124
|
type RequiredInput = "firstFrame" | "sourceVideo" | "references";
|
|
123
|
-
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "instrumental";
|
|
125
|
+
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "instrumental";
|
|
124
126
|
interface ReferenceLimits {
|
|
125
127
|
images?: number;
|
|
126
128
|
videos?: number;
|
|
@@ -208,6 +210,8 @@ interface ImageResult {
|
|
|
208
210
|
images: ImageBytes[];
|
|
209
211
|
usage: UsageEvent;
|
|
210
212
|
raw?: unknown;
|
|
213
|
+
/** The provider URL the images were downloaded from, when the provider hands one back. */
|
|
214
|
+
outputUrl?: string;
|
|
211
215
|
}
|
|
212
216
|
/** What generateImage returns: the adapter result plus `image`, SDK accessors and warnings. */
|
|
213
217
|
interface ImageCallResult extends ImageResult {
|
package/dist/index.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { z } from 'zod';
|
|
|
12
12
|
/** The AI SDK video model spelling: a catalog id or a provider video model instance. */
|
|
13
13
|
type VideoModel = Parameters<typeof experimental_generateVideo>[0]["model"];
|
|
14
14
|
type AspectRatio = "1:1" | "16:9" | "9:16" | "4:3" | "3:4" | "3:2" | "2:3" | "4:5" | "5:4" | "21:9" | "9:21" | "97:30" | "adaptive";
|
|
15
|
-
type ImageSize = "1K" | "2K" | "4K";
|
|
15
|
+
type ImageSize = "512" | "1K" | "2K" | "4K";
|
|
16
16
|
type VideoResolution = "360p" | "480p" | "720p" | "768p" | "1080p" | "2k" | "4k";
|
|
17
17
|
/** "xhigh" and "max" exist only on gpt-image-2.5; gpt-image-2 rejects them at the provider. */
|
|
18
18
|
type ImageQuality = "auto" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
@@ -37,6 +37,8 @@ interface ImageRequest {
|
|
|
37
37
|
seed?: number;
|
|
38
38
|
count?: number;
|
|
39
39
|
outputFormat?: OutputFormat;
|
|
40
|
+
/** Upscale factor for upscaler rows; adapters map it to the provider's field. */
|
|
41
|
+
scaleFactor?: number;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* What a caller passes to generateImage. Same field names as the AI SDK's
|
|
@@ -120,7 +122,7 @@ interface MediaPart {
|
|
|
120
122
|
cleanup?: () => Promise<void>;
|
|
121
123
|
}
|
|
122
124
|
type RequiredInput = "firstFrame" | "sourceVideo" | "references";
|
|
123
|
-
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "instrumental";
|
|
125
|
+
type SupportedOption = "seed" | "quality" | "negativePrompt" | "cfgScale" | "generateAudio" | "promptExpansion" | "lastFrame" | "count" | "outputFormat" | "scaleFactor" | "instrumental";
|
|
124
126
|
interface ReferenceLimits {
|
|
125
127
|
images?: number;
|
|
126
128
|
videos?: number;
|
|
@@ -208,6 +210,8 @@ interface ImageResult {
|
|
|
208
210
|
images: ImageBytes[];
|
|
209
211
|
usage: UsageEvent;
|
|
210
212
|
raw?: unknown;
|
|
213
|
+
/** The provider URL the images were downloaded from, when the provider hands one back. */
|
|
214
|
+
outputUrl?: string;
|
|
211
215
|
}
|
|
212
216
|
/** What generateImage returns: the adapter result plus `image`, SDK accessors and warnings. */
|
|
213
217
|
interface ImageCallResult extends ImageResult {
|
package/dist/index.js
CHANGED
|
@@ -83,7 +83,18 @@ var Catalog = class _Catalog {
|
|
|
83
83
|
|
|
84
84
|
// src/catalog/image.ts
|
|
85
85
|
var IMAGE_USAGE = { unit: "images", modality: "IMAGE" };
|
|
86
|
-
var GEMINI_RATIOS = [
|
|
86
|
+
var GEMINI_RATIOS = [
|
|
87
|
+
"1:1",
|
|
88
|
+
"2:3",
|
|
89
|
+
"3:2",
|
|
90
|
+
"16:9",
|
|
91
|
+
"9:16",
|
|
92
|
+
"4:3",
|
|
93
|
+
"3:4",
|
|
94
|
+
"21:9",
|
|
95
|
+
"4:5",
|
|
96
|
+
"5:4"
|
|
97
|
+
];
|
|
87
98
|
function geminiImage(id, label, aliases, sizes) {
|
|
88
99
|
const model = {
|
|
89
100
|
id,
|
|
@@ -106,7 +117,8 @@ var IMAGE_MODELS = [
|
|
|
106
117
|
"gemini-3.1-flash-image-preview",
|
|
107
118
|
"Nano Banana Flash",
|
|
108
119
|
["nb-2"],
|
|
109
|
-
|
|
120
|
+
// Flash 3.1 is the only Gemini image model with the 512 tier.
|
|
121
|
+
["512", "1K", "2K", "4K"]
|
|
110
122
|
),
|
|
111
123
|
geminiImage("gemini-3.1-flash-lite-image", "Nano Banana Lite", ["nb-lite"], ["1K"]),
|
|
112
124
|
// trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
|
|
@@ -451,8 +463,12 @@ var OTHER_MODELS = [
|
|
|
451
463
|
adapter: "replicate",
|
|
452
464
|
providerModelId: "topazlabs/image-upscale",
|
|
453
465
|
lifecycle: "active",
|
|
454
|
-
constraints: {
|
|
455
|
-
|
|
466
|
+
constraints: {
|
|
467
|
+
references: { images: 1 },
|
|
468
|
+
requires: ["references"],
|
|
469
|
+
supports: ["scaleFactor", "outputFormat"]
|
|
470
|
+
},
|
|
471
|
+
defaults: { scaleFactor: 2, outputFormat: "png" },
|
|
456
472
|
usage: { unit: "compute_seconds", modality: "IMAGE" },
|
|
457
473
|
pricingKind: "flat"
|
|
458
474
|
},
|
|
@@ -508,7 +524,7 @@ var TEXT_MODELS = [
|
|
|
508
524
|
text("gpt-5.6-sol", "GPT-5.6 Sol", "gpt-5.6-sol"),
|
|
509
525
|
// Library key "claude-sonnet-4.5" maps to the SDK id "claude-sonnet-4-5".
|
|
510
526
|
text("claude-sonnet-4-5", "Claude Sonnet 4.5", "claude-sonnet-4-5", {
|
|
511
|
-
aliases: ["claude-sonnet-4.5"]
|
|
527
|
+
aliases: ["claude-sonnet-4.5", "claude-sonnet-4-5-20250929"]
|
|
512
528
|
}),
|
|
513
529
|
// Anthropic retired the dated 4.0 ids; callers that still send them get 4.6.
|
|
514
530
|
text("claude-sonnet-4-6", "Claude Sonnet 4.6", "claude-sonnet-4-6", {
|
|
@@ -524,7 +540,7 @@ var TEXT_MODELS = [
|
|
|
524
540
|
aliases: ["claude-opus-4.8", "claude-opus-4", "claude-opus-4.0", "claude-opus-4-20250514"]
|
|
525
541
|
}),
|
|
526
542
|
text("claude-haiku-4-5", "Claude Haiku 4.5", "claude-haiku-4-5", {
|
|
527
|
-
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001"]
|
|
543
|
+
aliases: ["claude-haiku-4.5", "claude-haiku-4-5-20251001", "claude-haiku-4"]
|
|
528
544
|
}),
|
|
529
545
|
text("claude-opus-5", "Claude Opus 5", "claude-opus-5", {
|
|
530
546
|
aliases: ["claude-opus-5.0"]
|
|
@@ -1007,7 +1023,7 @@ var MODELS = [
|
|
|
1007
1023
|
];
|
|
1008
1024
|
|
|
1009
1025
|
// src/resolve-options.ts
|
|
1010
|
-
var SIZE_ORDER = ["1K", "2K", "4K"];
|
|
1026
|
+
var SIZE_ORDER = ["512", "1K", "2K", "4K"];
|
|
1011
1027
|
var RESOLUTION_ORDER = ["360p", "480p", "720p", "768p", "1080p", "2k", "4k"];
|
|
1012
1028
|
function ratioValue(r) {
|
|
1013
1029
|
if (r === "adaptive") return 1;
|
|
@@ -1139,7 +1155,13 @@ function resolveImageOptions(model, request, onUnsupported = "error") {
|
|
|
1139
1155
|
model: model.id
|
|
1140
1156
|
});
|
|
1141
1157
|
}
|
|
1142
|
-
dropUnsupported(merged, model, warnings, [
|
|
1158
|
+
dropUnsupported(merged, model, warnings, [
|
|
1159
|
+
"seed",
|
|
1160
|
+
"quality",
|
|
1161
|
+
"count",
|
|
1162
|
+
"outputFormat",
|
|
1163
|
+
"scaleFactor"
|
|
1164
|
+
]);
|
|
1143
1165
|
return { request: merged, warnings };
|
|
1144
1166
|
}
|
|
1145
1167
|
function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
@@ -1920,6 +1942,7 @@ function createModelKit(config, adapters) {
|
|
|
1920
1942
|
providerOptions,
|
|
1921
1943
|
references,
|
|
1922
1944
|
exactSize: exactSizeField,
|
|
1945
|
+
scaleFactor,
|
|
1923
1946
|
quality: _quality,
|
|
1924
1947
|
outputFormat: _outputFormat
|
|
1925
1948
|
} = req;
|
|
@@ -1945,6 +1968,8 @@ function createModelKit(config, adapters) {
|
|
|
1945
1968
|
if (_quality !== void 0) pushIgnored(warnings, "quality", _quality, model.modelId);
|
|
1946
1969
|
if (_outputFormat !== void 0)
|
|
1947
1970
|
pushIgnored(warnings, "outputFormat", _outputFormat, model.modelId);
|
|
1971
|
+
if (scaleFactor !== void 0)
|
|
1972
|
+
pushIgnored(warnings, "scaleFactor", scaleFactor, model.modelId);
|
|
1948
1973
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
1949
1974
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
1950
1975
|
const result = await aiGenerateImage(options);
|
|
@@ -4004,6 +4029,10 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
|
|
|
4004
4029
|
imageQuality: "auto"
|
|
4005
4030
|
};
|
|
4006
4031
|
if (req.size !== void 0) usage2.imageSize = req.size;
|
|
4032
|
+
if (result.usage?.inputTokens !== void 0)
|
|
4033
|
+
usage2.inputTokens = result.usage.inputTokens;
|
|
4034
|
+
if (result.usage?.outputTokens !== void 0)
|
|
4035
|
+
usage2.outputTokens = result.usage.outputTokens;
|
|
4007
4036
|
return { images, usage: usage2, raw: result };
|
|
4008
4037
|
}
|
|
4009
4038
|
};
|
|
@@ -4535,7 +4564,7 @@ function aspectRatioToSize(ratio, tier) {
|
|
|
4535
4564
|
};
|
|
4536
4565
|
const MIN_PIXELS = 655360;
|
|
4537
4566
|
const MAX_PIXELS = 8294400;
|
|
4538
|
-
const maxLong = TIER_LONG_EDGE[tier];
|
|
4567
|
+
const maxLong = TIER_LONG_EDGE[tier] ?? 1024;
|
|
4539
4568
|
const RATIO_MAP = /* @__PURE__ */ new Map([
|
|
4540
4569
|
["1:1", [1, 1]],
|
|
4541
4570
|
["16:9", [16, 9]],
|
|
@@ -5169,6 +5198,9 @@ function isUpscaler(providerModelId) {
|
|
|
5169
5198
|
const id = isLower(providerModelId);
|
|
5170
5199
|
return id.includes("upscal") || id.includes("crystal") || id.includes("topaz");
|
|
5171
5200
|
}
|
|
5201
|
+
function isTopazUpscaler(providerModelId) {
|
|
5202
|
+
return isLower(providerModelId).includes("topazlabs/image-upscale");
|
|
5203
|
+
}
|
|
5172
5204
|
function isQwen(providerModelId) {
|
|
5173
5205
|
return isLower(providerModelId).includes("qwen");
|
|
5174
5206
|
}
|
|
@@ -5218,8 +5250,36 @@ function wanImageSize(aspectRatio, size) {
|
|
|
5218
5250
|
}
|
|
5219
5251
|
async function generateReplicateImage(req, ctx, deps) {
|
|
5220
5252
|
const id = ctx.model.providerModelId;
|
|
5221
|
-
|
|
5222
|
-
if (
|
|
5253
|
+
let input;
|
|
5254
|
+
if (isTopazUpscaler(id)) {
|
|
5255
|
+
const first = (req.references ?? [])[0];
|
|
5256
|
+
if (!first) {
|
|
5257
|
+
throw new ModelKitError({
|
|
5258
|
+
code: "missing_input",
|
|
5259
|
+
message: `${ctx.model.id} requires a reference image to upscale`,
|
|
5260
|
+
provider: "replicate",
|
|
5261
|
+
model: ctx.model.id,
|
|
5262
|
+
retryable: false
|
|
5263
|
+
});
|
|
5264
|
+
}
|
|
5265
|
+
let format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat ?? "png";
|
|
5266
|
+
if (format !== "png" && format !== "jpg") {
|
|
5267
|
+
ctx.warnings.push({
|
|
5268
|
+
code: "option_ignored",
|
|
5269
|
+
field: "outputFormat",
|
|
5270
|
+
from: format,
|
|
5271
|
+
message: "topazlabs/image-upscale supports only png and jpg; using png"
|
|
5272
|
+
});
|
|
5273
|
+
format = "png";
|
|
5274
|
+
}
|
|
5275
|
+
input = {
|
|
5276
|
+
image: refToUrl3(first),
|
|
5277
|
+
enhance_model: "Standard V2",
|
|
5278
|
+
output_format: format,
|
|
5279
|
+
upscale_factor: `${req.scaleFactor ?? 2}x`,
|
|
5280
|
+
face_enhancement: true
|
|
5281
|
+
};
|
|
5282
|
+
} else if (isUpscaler(id)) {
|
|
5223
5283
|
const refs = req.references ?? [];
|
|
5224
5284
|
const first = refs[0];
|
|
5225
5285
|
if (!first) {
|
|
@@ -5231,24 +5291,29 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
5231
5291
|
retryable: false
|
|
5232
5292
|
});
|
|
5233
5293
|
}
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5294
|
+
const imageInput = { prompt: req.prompt };
|
|
5295
|
+
imageInput.image = refToUrl3(first);
|
|
5296
|
+
imageInput.creativity = 0;
|
|
5297
|
+
imageInput.scale_factor = 2;
|
|
5298
|
+
imageInput.output_format = "png";
|
|
5299
|
+
input = imageInput;
|
|
5238
5300
|
} else if (isWanImage(id)) {
|
|
5239
5301
|
const refs = (req.references ?? []).map(refToUrl3);
|
|
5240
|
-
|
|
5241
|
-
|
|
5302
|
+
const imageInput = { prompt: req.prompt };
|
|
5303
|
+
if (refs.length > 0) imageInput.images = refs;
|
|
5304
|
+
imageInput.size = wanImageSize(req.aspectRatio, req.size);
|
|
5305
|
+
input = imageInput;
|
|
5242
5306
|
} else if (isQwen(id)) {
|
|
5243
5307
|
const refs = (req.references ?? []).map(refToUrl3);
|
|
5244
5308
|
const firstUrl = refs[0];
|
|
5309
|
+
const imageInput = { prompt: req.prompt };
|
|
5245
5310
|
if (firstUrl !== void 0) {
|
|
5246
|
-
|
|
5247
|
-
if (!isQwenEditPlus(id))
|
|
5311
|
+
imageInput.image = firstUrl;
|
|
5312
|
+
if (!isQwenEditPlus(id)) imageInput.match_input_image = true;
|
|
5248
5313
|
}
|
|
5249
5314
|
const ratios = isQwenEditPlus(id) ? QWEN_EDIT_RATIOS : QWEN_IMAGE_RATIOS;
|
|
5250
5315
|
if (req.aspectRatio !== void 0) {
|
|
5251
|
-
if (ratios.has(req.aspectRatio))
|
|
5316
|
+
if (ratios.has(req.aspectRatio)) imageInput.aspect_ratio = req.aspectRatio;
|
|
5252
5317
|
else
|
|
5253
5318
|
ctx.warnings.push({
|
|
5254
5319
|
code: "option_ignored",
|
|
@@ -5258,18 +5323,21 @@ async function generateReplicateImage(req, ctx, deps) {
|
|
|
5258
5323
|
});
|
|
5259
5324
|
}
|
|
5260
5325
|
if (isQwenEditPlus(id) && req.outputFormat !== void 0) {
|
|
5261
|
-
|
|
5326
|
+
imageInput.output_format = req.outputFormat === "jpeg" ? "jpg" : req.outputFormat;
|
|
5262
5327
|
}
|
|
5328
|
+
input = imageInput;
|
|
5263
5329
|
} else {
|
|
5264
5330
|
const refs = req.references ?? [];
|
|
5265
5331
|
const first = refs[0];
|
|
5266
|
-
|
|
5332
|
+
const imageInput = { prompt: req.prompt };
|
|
5333
|
+
if (first) imageInput.image = refToUrl3(first);
|
|
5334
|
+
input = imageInput;
|
|
5267
5335
|
}
|
|
5268
5336
|
const { url, predictTime, raw } = await runPrediction(ctx, input, deps);
|
|
5269
5337
|
const file = await download(ctx, url);
|
|
5270
5338
|
const usage2 = imageUsage2(ctx, req);
|
|
5271
5339
|
usage2.quantity = predictTime;
|
|
5272
|
-
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw };
|
|
5340
|
+
return { images: [{ bytes: file.bytes, mime: file.mime }], usage: usage2, raw, outputUrl: url };
|
|
5273
5341
|
}
|
|
5274
5342
|
function wanSize(aspectRatio) {
|
|
5275
5343
|
if (!aspectRatio || aspectRatio === "adaptive" || aspectRatio === "1:1") return "2K";
|