@shop-os/modelkit 0.3.1 → 0.3.3
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/CHANGELOG.md +19 -0
- package/README.md +2 -1
- package/dist/catalog.cjs +118 -5
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +12 -1
- package/dist/catalog.d.ts +12 -1
- package/dist/catalog.js +118 -5
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +136 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -3
- package/dist/index.d.ts +19 -3
- package/dist/index.js +134 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,6 +33,7 @@ var index_exports = {};
|
|
|
33
33
|
__export(index_exports, {
|
|
34
34
|
ADAPTER_IDS: () => ADAPTER_IDS,
|
|
35
35
|
ADAPTER_KEYS: () => ADAPTER_KEYS,
|
|
36
|
+
ARRAY_INPUT_SPEC_KEYS: () => ARRAY_INPUT_SPEC_KEYS,
|
|
36
37
|
AUDIO_INPUT_SPEC_KEYS: () => AUDIO_INPUT_SPEC_KEYS,
|
|
37
38
|
Catalog: () => Catalog,
|
|
38
39
|
CatalogModelSchema: () => CatalogModelSchema,
|
|
@@ -75,6 +76,7 @@ __export(index_exports, {
|
|
|
75
76
|
googleImageAdapter: () => googleImageAdapter,
|
|
76
77
|
hasAwsCredentials: () => hasAwsCredentials,
|
|
77
78
|
higgsfieldAdapter: () => higgsfieldAdapter,
|
|
79
|
+
isArrayInputSpecKey: () => isArrayInputSpecKey,
|
|
78
80
|
isInputSpecKey: () => isInputSpecKey,
|
|
79
81
|
isListed: () => isListed,
|
|
80
82
|
isListedOn: () => isListedOn,
|
|
@@ -286,13 +288,21 @@ var GEMINI_RATIOS = [
|
|
|
286
288
|
"5:4",
|
|
287
289
|
"adaptive"
|
|
288
290
|
];
|
|
291
|
+
var NANO_BANANA_2_1_RATIOS = [
|
|
292
|
+
...GEMINI_RATIOS.filter((r) => r !== "adaptive"),
|
|
293
|
+
"1:4",
|
|
294
|
+
"4:1",
|
|
295
|
+
"1:8",
|
|
296
|
+
"8:1",
|
|
297
|
+
"adaptive"
|
|
298
|
+
];
|
|
289
299
|
var GEMINI_PROMPT_MAX_CHARS = 5e4;
|
|
290
300
|
var GPT_IMAGE_PROMPT = { referenceSyntax: "numbered", maxChars: 32e3 };
|
|
291
|
-
function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars) {
|
|
301
|
+
function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars, aspectRatios = GEMINI_RATIOS) {
|
|
292
302
|
const prompt = { referenceSyntax: "caption" };
|
|
293
303
|
if (promptMaxChars !== void 0) prompt.maxChars = promptMaxChars;
|
|
294
304
|
const constraints = {
|
|
295
|
-
aspectRatios: [...
|
|
305
|
+
aspectRatios: [...aspectRatios],
|
|
296
306
|
sizes,
|
|
297
307
|
supports: ["safetySettings", "temperature"],
|
|
298
308
|
prompt
|
|
@@ -316,6 +326,21 @@ function geminiImage(id, label, aliases, sizes, display, exposure, references, p
|
|
|
316
326
|
return model;
|
|
317
327
|
}
|
|
318
328
|
var IMAGE_MODELS = [
|
|
329
|
+
geminiImage(
|
|
330
|
+
"gemini-nano-banana-2.1",
|
|
331
|
+
"Nano Banana 2.1",
|
|
332
|
+
["nb-2.1"],
|
|
333
|
+
["1K", "2K", "4K"],
|
|
334
|
+
{
|
|
335
|
+
provider: "google",
|
|
336
|
+
description: "Latest high-efficiency Nano Banana. Better realism, prompt adherence, text rendering and character consistency at Flash speed. Great for campaigns, infographics, and iterative edits.",
|
|
337
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
338
|
+
},
|
|
339
|
+
["cowork", "space_builder"],
|
|
340
|
+
{ images: 14 },
|
|
341
|
+
GEMINI_PROMPT_MAX_CHARS,
|
|
342
|
+
NANO_BANANA_2_1_RATIOS
|
|
343
|
+
),
|
|
319
344
|
geminiImage(
|
|
320
345
|
"gemini-3-pro-image-preview",
|
|
321
346
|
"Nano Banana Pro",
|
|
@@ -2332,7 +2357,8 @@ var VIDEO_INPUT_SPEC_KEYS = [
|
|
|
2332
2357
|
"generateAudio",
|
|
2333
2358
|
"cfgScale",
|
|
2334
2359
|
"promptExpansion",
|
|
2335
|
-
"referenceImages"
|
|
2360
|
+
"referenceImages",
|
|
2361
|
+
"sourceVideo"
|
|
2336
2362
|
];
|
|
2337
2363
|
var IMAGE_INPUT_SPEC_KEYS = [
|
|
2338
2364
|
"prompt",
|
|
@@ -2351,6 +2377,12 @@ var AUDIO_INPUT_SPEC_KEYS = [
|
|
|
2351
2377
|
"sourceVideo",
|
|
2352
2378
|
"instrumental"
|
|
2353
2379
|
];
|
|
2380
|
+
var ARRAY_INPUT_SPEC_KEYS = [
|
|
2381
|
+
"firstFrame",
|
|
2382
|
+
"referenceImages",
|
|
2383
|
+
"lastFrame",
|
|
2384
|
+
"references"
|
|
2385
|
+
];
|
|
2354
2386
|
var INPUT_SPEC_SUPPORTS_KEYS = [
|
|
2355
2387
|
"lastFrame",
|
|
2356
2388
|
"seed",
|
|
@@ -2364,6 +2396,7 @@ var INPUT_SPEC_SUPPORTS_KEYS = [
|
|
|
2364
2396
|
var VIDEO_KEY_SET = new Set(VIDEO_INPUT_SPEC_KEYS);
|
|
2365
2397
|
var IMAGE_KEY_SET = new Set(IMAGE_INPUT_SPEC_KEYS);
|
|
2366
2398
|
var AUDIO_KEY_SET = new Set(AUDIO_INPUT_SPEC_KEYS);
|
|
2399
|
+
var ARRAY_KEY_SET = new Set(ARRAY_INPUT_SPEC_KEYS);
|
|
2367
2400
|
var ALL_KEY_SET = /* @__PURE__ */ new Set([
|
|
2368
2401
|
...VIDEO_INPUT_SPEC_KEYS,
|
|
2369
2402
|
...IMAGE_INPUT_SPEC_KEYS,
|
|
@@ -2408,13 +2441,30 @@ var ValuesSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.re
|
|
|
2408
2441
|
}
|
|
2409
2442
|
});
|
|
2410
2443
|
var StaticSchema = import_zod2.z.record(import_zod2.z.string(), ProviderScalarSchema);
|
|
2444
|
+
var ArraysSchema = import_zod2.z.record(import_zod2.z.string().min(1), import_zod2.z.array(import_zod2.z.string()).min(1)).superRefine((arrays, ctx) => {
|
|
2445
|
+
for (const [name, keys] of Object.entries(arrays)) {
|
|
2446
|
+
for (const key of keys) {
|
|
2447
|
+
if (!ARRAY_KEY_SET.has(key)) {
|
|
2448
|
+
ctx.addIssue({
|
|
2449
|
+
code: "custom",
|
|
2450
|
+
path: [name],
|
|
2451
|
+
message: `inputSpec.arrays "${name}" has unknown image key "${key}"`
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
});
|
|
2411
2457
|
var InputSpecSchema = import_zod2.z.strictObject({
|
|
2412
2458
|
fields: FieldsSchema,
|
|
2413
2459
|
values: ValuesSchema.optional(),
|
|
2414
2460
|
static: StaticSchema.optional(),
|
|
2461
|
+
arrays: ArraysSchema.optional(),
|
|
2415
2462
|
editEndpoint: import_zod2.z.string().min(1).optional()
|
|
2416
2463
|
}).superRefine((spec, ctx) => {
|
|
2417
|
-
const mappedNames = new Set(
|
|
2464
|
+
const mappedNames = /* @__PURE__ */ new Set([
|
|
2465
|
+
...Object.values(spec.fields),
|
|
2466
|
+
...Object.keys(spec.arrays ?? {})
|
|
2467
|
+
]);
|
|
2418
2468
|
for (const key of Object.keys(spec.static ?? {})) {
|
|
2419
2469
|
if (mappedNames.has(key)) {
|
|
2420
2470
|
ctx.addIssue({
|
|
@@ -2428,6 +2478,9 @@ var InputSpecSchema = import_zod2.z.strictObject({
|
|
|
2428
2478
|
function isInputSpecKey(key) {
|
|
2429
2479
|
return ALL_KEY_SET.has(key);
|
|
2430
2480
|
}
|
|
2481
|
+
function isArrayInputSpecKey(key) {
|
|
2482
|
+
return ARRAY_KEY_SET.has(key);
|
|
2483
|
+
}
|
|
2431
2484
|
function validateInputSpec(raw, row) {
|
|
2432
2485
|
const parsed = InputSpecSchema.safeParse(raw);
|
|
2433
2486
|
if (!parsed.success) {
|
|
@@ -2506,14 +2559,54 @@ function validateInputSpec(raw, row) {
|
|
|
2506
2559
|
});
|
|
2507
2560
|
}
|
|
2508
2561
|
}
|
|
2562
|
+
const arrayOwner = /* @__PURE__ */ new Map();
|
|
2563
|
+
for (const [name, keys] of Object.entries(spec.arrays ?? {})) {
|
|
2564
|
+
const fieldKey = seenNames.get(name);
|
|
2565
|
+
if (fieldKey !== void 0) {
|
|
2566
|
+
issues.push({
|
|
2567
|
+
path: ["arrays", name],
|
|
2568
|
+
message: `inputSpec.arrays "${name}" is also the provider field of inputSpec.fields "${fieldKey}"`
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
for (const key of keys) {
|
|
2572
|
+
if (allowed !== void 0 && !allowed.has(key)) {
|
|
2573
|
+
issues.push({
|
|
2574
|
+
path: ["arrays", name],
|
|
2575
|
+
message: `inputSpec.arrays "${key}" is not supported for ${row.type} rows`
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2578
|
+
if (key in spec.fields) {
|
|
2579
|
+
issues.push({
|
|
2580
|
+
path: ["arrays", name],
|
|
2581
|
+
message: `inputSpec.arrays "${key}" is already mapped in inputSpec.fields`
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2584
|
+
const owner = arrayOwner.get(key);
|
|
2585
|
+
if (owner === void 0) arrayOwner.set(key, name);
|
|
2586
|
+
else {
|
|
2587
|
+
issues.push({
|
|
2588
|
+
path: ["arrays", name],
|
|
2589
|
+
message: owner === name ? `inputSpec.arrays "${name}" lists "${key}" twice` : `inputSpec.arrays "${owner}" and "${name}" both take "${key}"`
|
|
2590
|
+
});
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2509
2594
|
const supports = row.constraints.supports ?? [];
|
|
2510
2595
|
for (const key of INPUT_SPEC_SUPPORTS_KEYS) {
|
|
2511
|
-
if (
|
|
2596
|
+
if (supports.includes(key)) continue;
|
|
2597
|
+
if (key in spec.fields) {
|
|
2512
2598
|
issues.push({
|
|
2513
2599
|
path: ["fields", key],
|
|
2514
2600
|
message: `inputSpec.fields "${key}" needs "${key}" in constraints.supports`
|
|
2515
2601
|
});
|
|
2516
2602
|
}
|
|
2603
|
+
const arrayName = arrayOwner.get(key);
|
|
2604
|
+
if (arrayName !== void 0) {
|
|
2605
|
+
issues.push({
|
|
2606
|
+
path: ["arrays", arrayName],
|
|
2607
|
+
message: `inputSpec.arrays "${key}" needs "${key}" in constraints.supports`
|
|
2608
|
+
});
|
|
2609
|
+
}
|
|
2517
2610
|
}
|
|
2518
2611
|
if (issues.length > 0) return { ok: false, issues };
|
|
2519
2612
|
return { ok: true, spec };
|
|
@@ -2562,6 +2655,10 @@ var AspectRatioSchema = import_zod3.z.enum([
|
|
|
2562
2655
|
"21:9",
|
|
2563
2656
|
"9:21",
|
|
2564
2657
|
"97:30",
|
|
2658
|
+
"1:4",
|
|
2659
|
+
"4:1",
|
|
2660
|
+
"1:8",
|
|
2661
|
+
"8:1",
|
|
2565
2662
|
"adaptive"
|
|
2566
2663
|
]);
|
|
2567
2664
|
var ImageSizeSchema = import_zod3.z.enum(["512", "1K", "2K", "4K"]);
|
|
@@ -2731,6 +2828,7 @@ var CatalogCapabilitiesSchema = import_zod3.z.looseObject({
|
|
|
2731
2828
|
acceptsSourceVideo: import_zod3.z.boolean().optional(),
|
|
2732
2829
|
videoEdit: import_zod3.z.boolean().optional(),
|
|
2733
2830
|
framesExcludeReferences: import_zod3.z.boolean().optional(),
|
|
2831
|
+
sourceVideoExcludesFrames: import_zod3.z.boolean().optional(),
|
|
2734
2832
|
lastFrameRequiresFirstFrame: import_zod3.z.boolean().optional(),
|
|
2735
2833
|
reasoning: import_zod3.z.boolean().optional(),
|
|
2736
2834
|
vision: import_zod3.z.boolean().optional(),
|
|
@@ -4258,6 +4356,17 @@ function applyInputSpec(spec, req, refToUrl2, opts) {
|
|
|
4258
4356
|
const mapped = spec.values?.[canonical]?.[String(value)];
|
|
4259
4357
|
out[providerField] = mapped ?? serialised;
|
|
4260
4358
|
}
|
|
4359
|
+
for (const [providerField, keys] of Object.entries(spec.arrays ?? {})) {
|
|
4360
|
+
const urls = [];
|
|
4361
|
+
for (const key of keys) {
|
|
4362
|
+
if (!isArrayInputSpecKey(key)) continue;
|
|
4363
|
+
const value = canonicalValue(req, key);
|
|
4364
|
+
if (value === void 0) continue;
|
|
4365
|
+
if (Array.isArray(value)) urls.push(...value.map(refToUrl2));
|
|
4366
|
+
else if (isMediaRef(value)) urls.push(refToUrl2(value));
|
|
4367
|
+
}
|
|
4368
|
+
if (urls.length > 0) out[providerField] = urls;
|
|
4369
|
+
}
|
|
4261
4370
|
for (const [key, value] of Object.entries(spec.static ?? {})) {
|
|
4262
4371
|
out[key] = value;
|
|
4263
4372
|
}
|
|
@@ -8377,6 +8486,26 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
8377
8486
|
});
|
|
8378
8487
|
delete merged.sourceVideo;
|
|
8379
8488
|
}
|
|
8489
|
+
const imageInputs = ["firstFrame", "lastFrame", "referenceImages"].filter(
|
|
8490
|
+
(field) => field === "referenceImages" ? compact(merged.referenceImages).length > 0 : merged[field] !== void 0
|
|
8491
|
+
);
|
|
8492
|
+
if (merged.sourceVideo !== void 0 && imageInputs.length > 0 && model.capabilities?.sourceVideoExcludesFrames) {
|
|
8493
|
+
if (onUnsupported === "error") {
|
|
8494
|
+
throw new ModelKitError({
|
|
8495
|
+
code: "unsupported_option",
|
|
8496
|
+
message: `${model.id} takes a source video or images, not both`,
|
|
8497
|
+
model: model.id
|
|
8498
|
+
});
|
|
8499
|
+
}
|
|
8500
|
+
for (const field of imageInputs) {
|
|
8501
|
+
warnings.push({
|
|
8502
|
+
code: "option_ignored",
|
|
8503
|
+
field,
|
|
8504
|
+
message: `${model.id} takes a source video or images, not both; ${field} dropped`
|
|
8505
|
+
});
|
|
8506
|
+
delete merged[field];
|
|
8507
|
+
}
|
|
8508
|
+
}
|
|
8380
8509
|
if (merged.lastFrame !== void 0 && merged.firstFrame === void 0 && model.capabilities?.lastFrameRequiresFirstFrame) {
|
|
8381
8510
|
if (onUnsupported === "error") {
|
|
8382
8511
|
throw new ModelKitError({
|
|
@@ -9487,6 +9616,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
9487
9616
|
0 && (module.exports = {
|
|
9488
9617
|
ADAPTER_IDS,
|
|
9489
9618
|
ADAPTER_KEYS,
|
|
9619
|
+
ARRAY_INPUT_SPEC_KEYS,
|
|
9490
9620
|
AUDIO_INPUT_SPEC_KEYS,
|
|
9491
9621
|
Catalog,
|
|
9492
9622
|
CatalogModelSchema,
|
|
@@ -9529,6 +9659,7 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
|
|
|
9529
9659
|
googleImageAdapter,
|
|
9530
9660
|
hasAwsCredentials,
|
|
9531
9661
|
higgsfieldAdapter,
|
|
9662
|
+
isArrayInputSpecKey,
|
|
9532
9663
|
isInputSpecKey,
|
|
9533
9664
|
isListed,
|
|
9534
9665
|
isListedOn,
|