@shop-os/modelkit 0.3.0 → 0.3.2
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 +21 -0
- package/README.md +3 -3
- package/dist/catalog.cjs +55 -7
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +9 -1
- package/dist/catalog.d.ts +9 -1
- package/dist/catalog.js +55 -7
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +165 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +165 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,27 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.3.2] - Unreleased
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- Aspect ratios `1:4`, `4:1`, `1:8` and `8:1` in the `AspectRatio` type and the row schema. Gemini Nano Banana 2.1 serves them at 1K, 2K and 4K.
|
|
16
|
+
- Snapshot row `gemini-nano-banana-2.1` (alias `nb-2.1`, 1K/2K/4K, 14 references, the four new ratios plus the usual Gemini set). It runs on the existing `google-image` adapter.
|
|
17
|
+
|
|
18
|
+
### Live rows to update after publish
|
|
19
|
+
The live `gemini-nano-banana-2.1` rows (dev, stg, prod) keep the old ratio list until the four ratios are added in pro-admin. An app on 0.3.1 or older rejects a row that carries a ratio it does not know, so edit the live rows only after every app that reads the catalog runs 0.3.2.
|
|
20
|
+
|
|
21
|
+
## [0.3.1] - Unreleased
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- `providerOptions.modelkit.inputSpec` now works on fal image rows, so a new fal image model is a database row. The spec uses the image keys (`prompt`, `references`, `aspectRatio`, `size`, `outputFormat`, `seed`) with `fields`, `values` and `static`, exactly as on Replicate image rows. The new optional `editEndpoint` (fal rows only) names the endpoint called instead of `providerModelId` when the request has references, for models that split text-to-image and edit across two endpoints. Only the mapped fields are sent: no `num_images`, so a spec row returns one image per call. A fal row without an `inputSpec` keeps the Muse-shaped request and Ideogram keeps its own path. fal video rows still reject `inputSpec`. On fal an explicit `inputSpec` wins over the built-in Ideogram path, and `editEndpoint` needs a `references` entry in `fields`.
|
|
25
|
+
- `resolveRowInputSpec(req, ctx)` and `invalidInputSpecError(provider, ctx, issues)` in the shared mapper, used by the Replicate and fal adapters.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- fal image calls decode every image in the response that has a URL and fail only when none do. The Muse path used to fail when the first image had no URL even if later ones did.
|
|
29
|
+
|
|
30
|
+
### Live rows to add after publish
|
|
31
|
+
Add a fal image row that carries an `inputSpec` only after every app that will call it runs 0.3.1. An older kit accepts the row but ignores the `inputSpec`, so it sends the Muse-shaped request and the call fails or loses its fields.
|
|
32
|
+
|
|
12
33
|
## [0.3.0] - Unreleased
|
|
13
34
|
|
|
14
35
|
### Added
|
package/README.md
CHANGED
|
@@ -213,8 +213,8 @@ The Bedrock model id is `<routing.bedrockProfile>.anthropic.<providerModelId>`
|
|
|
213
213
|
breaks the pattern sets `providerOptions.modelkit.bedrockModelId` on its row.
|
|
214
214
|
See the CHANGELOG entry for the caller-visible Bedrock limits.
|
|
215
215
|
|
|
216
|
-
A Replicate video, image or audio row for a new model carries `providerOptions.modelkit.inputSpec`
|
|
217
|
-
instead of a kit change. It is read by the Replicate
|
|
216
|
+
A Replicate video, image or audio row, or a fal image row, for a new model carries `providerOptions.modelkit.inputSpec`
|
|
217
|
+
instead of a kit change. It is read by the Replicate and fal adapters only. `fields` maps a canonical key to the provider field name,
|
|
218
218
|
`values` remaps canonical values per key, and `static` merges literal provider fields
|
|
219
219
|
last. Video rows use `VIDEO_INPUT_SPEC_KEYS` (`prompt`, `durationSeconds`,
|
|
220
220
|
`aspectRatio`, `resolution`, `firstFrame`, `lastFrame`, `seed`, `negativePrompt`,
|
|
@@ -223,7 +223,7 @@ last. Video rows use `VIDEO_INPUT_SPEC_KEYS` (`prompt`, `durationSeconds`,
|
|
|
223
223
|
`seed`; map `references` to the provider's array field and remap `size` and `outputFormat`
|
|
224
224
|
with `values`); audio rows use
|
|
225
225
|
`AUDIO_INPUT_SPEC_KEYS` (`prompt`, `durationSeconds`, `seed`, `negativePrompt`,
|
|
226
|
-
`references`, `sourceVideo`, `instrumental`). `aspectRatio: "adaptive"` is omitted.
|
|
226
|
+
`references`, `sourceVideo`, `instrumental`). `aspectRatio: "adaptive"` is omitted. A fal image row has no kind and builds its whole input from the spec; the optional `editEndpoint` (fal rows only) is the fal endpoint called instead of `providerModelId` when the request has references. fal rows without an `inputSpec` keep the Muse-shaped request and Ideogram keeps its own path; an `inputSpec` on an Ideogram row replaces that path. `editEndpoint` needs a `references` entry in `fields`. `inputSpec` on fal video rows is not supported.
|
|
227
227
|
`validateInputSpec` is the shared contract the write schema, `dataOnlyCapable`, and
|
|
228
228
|
the Replicate mapper all check. `dataOnlyCapable(row)` reports whether such a row would
|
|
229
229
|
be served.
|
package/dist/catalog.cjs
CHANGED
|
@@ -222,13 +222,21 @@ var GEMINI_RATIOS = [
|
|
|
222
222
|
"5:4",
|
|
223
223
|
"adaptive"
|
|
224
224
|
];
|
|
225
|
+
var NANO_BANANA_2_1_RATIOS = [
|
|
226
|
+
...GEMINI_RATIOS.filter((r) => r !== "adaptive"),
|
|
227
|
+
"1:4",
|
|
228
|
+
"4:1",
|
|
229
|
+
"1:8",
|
|
230
|
+
"8:1",
|
|
231
|
+
"adaptive"
|
|
232
|
+
];
|
|
225
233
|
var GEMINI_PROMPT_MAX_CHARS = 5e4;
|
|
226
234
|
var GPT_IMAGE_PROMPT = { referenceSyntax: "numbered", maxChars: 32e3 };
|
|
227
|
-
function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars) {
|
|
235
|
+
function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars, aspectRatios = GEMINI_RATIOS) {
|
|
228
236
|
const prompt = { referenceSyntax: "caption" };
|
|
229
237
|
if (promptMaxChars !== void 0) prompt.maxChars = promptMaxChars;
|
|
230
238
|
const constraints = {
|
|
231
|
-
aspectRatios: [...
|
|
239
|
+
aspectRatios: [...aspectRatios],
|
|
232
240
|
sizes,
|
|
233
241
|
supports: ["safetySettings", "temperature"],
|
|
234
242
|
prompt
|
|
@@ -252,6 +260,21 @@ function geminiImage(id, label, aliases, sizes, display, exposure, references, p
|
|
|
252
260
|
return model;
|
|
253
261
|
}
|
|
254
262
|
var IMAGE_MODELS = [
|
|
263
|
+
geminiImage(
|
|
264
|
+
"gemini-nano-banana-2.1",
|
|
265
|
+
"Nano Banana 2.1",
|
|
266
|
+
["nb-2.1"],
|
|
267
|
+
["1K", "2K", "4K"],
|
|
268
|
+
{
|
|
269
|
+
provider: "google",
|
|
270
|
+
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.",
|
|
271
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
272
|
+
},
|
|
273
|
+
["cowork", "space_builder"],
|
|
274
|
+
{ images: 14 },
|
|
275
|
+
GEMINI_PROMPT_MAX_CHARS,
|
|
276
|
+
NANO_BANANA_2_1_RATIOS
|
|
277
|
+
),
|
|
255
278
|
geminiImage(
|
|
256
279
|
"gemini-3-pro-image-preview",
|
|
257
280
|
"Nano Banana Pro",
|
|
@@ -2317,6 +2340,10 @@ var ALL_KEY_SET = /* @__PURE__ */ new Set([
|
|
|
2317
2340
|
...IMAGE_INPUT_SPEC_KEYS,
|
|
2318
2341
|
...AUDIO_INPUT_SPEC_KEYS
|
|
2319
2342
|
]);
|
|
2343
|
+
var TYPES_BY_ADAPTER = /* @__PURE__ */ new Map([
|
|
2344
|
+
["replicate", ["video", "image", "audio"]],
|
|
2345
|
+
["fal", ["image"]]
|
|
2346
|
+
]);
|
|
2320
2347
|
var ALLOWED_KEYS_BY_TYPE = /* @__PURE__ */ new Map([
|
|
2321
2348
|
["video", VIDEO_KEY_SET],
|
|
2322
2349
|
["image", IMAGE_KEY_SET],
|
|
@@ -2355,7 +2382,8 @@ var StaticSchema = import_zod2.z.record(import_zod2.z.string(), ProviderScalarSc
|
|
|
2355
2382
|
var InputSpecSchema = import_zod2.z.strictObject({
|
|
2356
2383
|
fields: FieldsSchema,
|
|
2357
2384
|
values: ValuesSchema.optional(),
|
|
2358
|
-
static: StaticSchema.optional()
|
|
2385
|
+
static: StaticSchema.optional(),
|
|
2386
|
+
editEndpoint: import_zod2.z.string().min(1).optional()
|
|
2359
2387
|
}).superRefine((spec, ctx) => {
|
|
2360
2388
|
const mappedNames = new Set(Object.values(spec.fields));
|
|
2361
2389
|
for (const key of Object.keys(spec.static ?? {})) {
|
|
@@ -2380,18 +2408,21 @@ function validateInputSpec(raw, row) {
|
|
|
2380
2408
|
};
|
|
2381
2409
|
}
|
|
2382
2410
|
const spec = parsed.data;
|
|
2383
|
-
|
|
2411
|
+
const supportedTypes = TYPES_BY_ADAPTER.get(row.adapter);
|
|
2412
|
+
if (supportedTypes === void 0) {
|
|
2384
2413
|
return {
|
|
2385
2414
|
ok: false,
|
|
2386
|
-
issues: [
|
|
2415
|
+
issues: [
|
|
2416
|
+
{ path: [], message: "inputSpec is only supported on replicate and fal rows" }
|
|
2417
|
+
]
|
|
2387
2418
|
};
|
|
2388
2419
|
}
|
|
2389
2420
|
const issues = [];
|
|
2390
2421
|
const allowed = ALLOWED_KEYS_BY_TYPE.get(row.type);
|
|
2391
|
-
if (allowed === void 0) {
|
|
2422
|
+
if (allowed === void 0 || !supportedTypes.includes(row.type)) {
|
|
2392
2423
|
issues.push({
|
|
2393
2424
|
path: [],
|
|
2394
|
-
message: `inputSpec is not supported for "${row.type}" rows`
|
|
2425
|
+
message: row.adapter === "fal" ? `inputSpec on fal rows is only supported for image rows, not "${row.type}"` : `inputSpec is not supported for "${row.type}" rows`
|
|
2395
2426
|
});
|
|
2396
2427
|
} else {
|
|
2397
2428
|
for (const key of Object.keys(spec.fields)) {
|
|
@@ -2411,6 +2442,19 @@ function validateInputSpec(raw, row) {
|
|
|
2411
2442
|
}
|
|
2412
2443
|
}
|
|
2413
2444
|
}
|
|
2445
|
+
if (spec.editEndpoint !== void 0) {
|
|
2446
|
+
if (row.adapter !== "fal") {
|
|
2447
|
+
issues.push({
|
|
2448
|
+
path: ["editEndpoint"],
|
|
2449
|
+
message: "inputSpec.editEndpoint is only supported on fal rows"
|
|
2450
|
+
});
|
|
2451
|
+
} else if (!("references" in spec.fields)) {
|
|
2452
|
+
issues.push({
|
|
2453
|
+
path: ["editEndpoint"],
|
|
2454
|
+
message: 'inputSpec.editEndpoint needs a "references" entry in inputSpec.fields'
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2414
2458
|
const seenNames = /* @__PURE__ */ new Map();
|
|
2415
2459
|
for (const [key, name] of Object.entries(spec.fields)) {
|
|
2416
2460
|
const first = seenNames.get(name);
|
|
@@ -2486,6 +2530,10 @@ var AspectRatioSchema = import_zod3.z.enum([
|
|
|
2486
2530
|
"21:9",
|
|
2487
2531
|
"9:21",
|
|
2488
2532
|
"97:30",
|
|
2533
|
+
"1:4",
|
|
2534
|
+
"4:1",
|
|
2535
|
+
"1:8",
|
|
2536
|
+
"8:1",
|
|
2489
2537
|
"adaptive"
|
|
2490
2538
|
]);
|
|
2491
2539
|
var ImageSizeSchema = import_zod3.z.enum(["512", "1K", "2K", "4K"]);
|