@shop-os/modelkit 0.2.2 → 0.2.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/CHANGELOG.md +13 -0
- package/dist/catalog.cjs +41 -33
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +16 -9
- package/dist/catalog.d.ts +16 -9
- package/dist/catalog.js +41 -33
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +157 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -9
- package/dist/index.d.ts +16 -9
- package/dist/index.js +157 -146
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,19 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.2.4] - 2026-09-15
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Catalog prime and fallback log lines carry origin, row count, revision and the error in the message string. pino-style loggers dropped the trailing object argument, so services such as template-service logged no origin.
|
|
16
|
+
|
|
17
|
+
## [0.2.3] - 2026-09-15
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- `display.sortOrder` sorts descending: a higher number shows first, so a new model takes the next number up. No published row set it before.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- `primeCatalog` treats a remote response with zero rows as a failure and keeps the last-good or snapshot rows, so a pro-backend whose catalog table is not seeded yet cannot empty every consumer's pickers.
|
|
24
|
+
|
|
12
25
|
## [0.2.2] - 2026-09-15
|
|
13
26
|
|
|
14
27
|
Option audit against provider docs, limited to options a product surface sets.
|
package/dist/catalog.cjs
CHANGED
|
@@ -164,6 +164,12 @@ var GEMINI_RATIOS = [
|
|
|
164
164
|
"adaptive"
|
|
165
165
|
];
|
|
166
166
|
function geminiImage(id, label, aliases, sizes, display, exposure, references) {
|
|
167
|
+
const constraints = {
|
|
168
|
+
aspectRatios: [...GEMINI_RATIOS],
|
|
169
|
+
sizes,
|
|
170
|
+
supports: ["safetySettings", "temperature"]
|
|
171
|
+
};
|
|
172
|
+
if (references !== void 0) constraints.references = references;
|
|
167
173
|
const model = {
|
|
168
174
|
id,
|
|
169
175
|
aliases,
|
|
@@ -173,12 +179,7 @@ function geminiImage(id, label, aliases, sizes, display, exposure, references) {
|
|
|
173
179
|
providerModelId: id,
|
|
174
180
|
lifecycle: "active",
|
|
175
181
|
exposure,
|
|
176
|
-
constraints
|
|
177
|
-
aspectRatios: [...GEMINI_RATIOS],
|
|
178
|
-
sizes,
|
|
179
|
-
supports: ["safetySettings", "temperature"],
|
|
180
|
-
...references ? { references } : {}
|
|
181
|
-
},
|
|
182
|
+
constraints,
|
|
182
183
|
defaults: { size: "1K", aspectRatio: "1:1" },
|
|
183
184
|
usage: { ...IMAGE_USAGE, slug: "gemini" },
|
|
184
185
|
pricingKind: "image_size",
|
|
@@ -2079,31 +2080,31 @@ var liveState = store[KEY] ??= {
|
|
|
2079
2080
|
var liveCatalog = liveState.catalog;
|
|
2080
2081
|
|
|
2081
2082
|
// src/catalog/load.ts
|
|
2083
|
+
var import_zod2 = require("zod");
|
|
2082
2084
|
function rowCount() {
|
|
2083
2085
|
return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
|
|
2084
2086
|
}
|
|
2085
2087
|
function authHeaders(auth) {
|
|
2086
2088
|
return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
|
|
2087
2089
|
}
|
|
2090
|
+
var EnvelopeSchema = import_zod2.z.object({
|
|
2091
|
+
rows: CatalogSchema,
|
|
2092
|
+
revision: import_zod2.z.string().optional()
|
|
2093
|
+
});
|
|
2094
|
+
function toEnvelope(data) {
|
|
2095
|
+
if (data.rows.length === 0) throw new Error("invalid catalog response: no rows");
|
|
2096
|
+
const envelope = { rows: data.rows };
|
|
2097
|
+
if (data.revision !== void 0) envelope.revision = data.revision;
|
|
2098
|
+
return envelope;
|
|
2099
|
+
}
|
|
2088
2100
|
function describeError(err) {
|
|
2089
2101
|
return err instanceof Error ? err.message : String(err);
|
|
2090
2102
|
}
|
|
2091
|
-
function parseEnvelope(json) {
|
|
2092
|
-
if (typeof json !== "object" || json === null || !("rows" in json)) {
|
|
2093
|
-
throw new Error("invalid catalog response: missing rows");
|
|
2094
|
-
}
|
|
2095
|
-
const rows = CatalogSchema.parse(json.rows);
|
|
2096
|
-
const rev = json.revision;
|
|
2097
|
-
if (typeof rev === "string") return { rows, revision: rev };
|
|
2098
|
-
return { rows };
|
|
2099
|
-
}
|
|
2100
2103
|
function logPrimed(logger, result) {
|
|
2101
|
-
const
|
|
2102
|
-
logger.info(
|
|
2103
|
-
origin
|
|
2104
|
-
|
|
2105
|
-
revision: loggedRevision
|
|
2106
|
-
});
|
|
2104
|
+
const revision = result.revision === void 0 ? "" : ` revision=${result.revision}`;
|
|
2105
|
+
logger.info(
|
|
2106
|
+
`[modelkit] catalog primed origin=${result.origin} rowCount=${result.rowCount}${revision}`
|
|
2107
|
+
);
|
|
2107
2108
|
}
|
|
2108
2109
|
async function fetchRemote(source, logger) {
|
|
2109
2110
|
const fetchImpl = source.fetch ?? globalThis.fetch;
|
|
@@ -2116,7 +2117,9 @@ async function fetchRemote(source, logger) {
|
|
|
2116
2117
|
if (res.status === 304) return { kept: true };
|
|
2117
2118
|
if (!res.ok) throw new Error(`catalog fetch failed with status ${res.status}`);
|
|
2118
2119
|
const json = await res.json();
|
|
2119
|
-
const
|
|
2120
|
+
const parsed = EnvelopeSchema.safeParse(json);
|
|
2121
|
+
if (!parsed.success) throw new Error("invalid catalog response: missing rows");
|
|
2122
|
+
const { rows, revision: rev } = toEnvelope(parsed.data);
|
|
2120
2123
|
if (rev === void 0) return { rows, fromCache: false };
|
|
2121
2124
|
return { rows, revision: rev, fromCache: false };
|
|
2122
2125
|
}
|
|
@@ -2125,7 +2128,7 @@ async function writeCache(source, logger, rows, rev) {
|
|
|
2125
2128
|
try {
|
|
2126
2129
|
await source.cache.set(JSON.stringify({ rows, revision: rev }));
|
|
2127
2130
|
} catch (err) {
|
|
2128
|
-
logger.warn(
|
|
2131
|
+
logger.warn(`[modelkit] catalog cache write failed: ${describeError(err)}`);
|
|
2129
2132
|
}
|
|
2130
2133
|
}
|
|
2131
2134
|
async function prime(source, logger) {
|
|
@@ -2146,12 +2149,14 @@ async function prime(source, logger) {
|
|
|
2146
2149
|
logPrimed(logger, result);
|
|
2147
2150
|
return result;
|
|
2148
2151
|
} catch (err) {
|
|
2149
|
-
logger.warn(
|
|
2152
|
+
logger.warn(`[modelkit] catalog remote failed, trying cache: ${describeError(err)}`);
|
|
2150
2153
|
const error = describeError(err);
|
|
2151
2154
|
try {
|
|
2152
2155
|
const cached = await source.cache?.get();
|
|
2153
2156
|
if (!cached) throw new Error("no cached catalog");
|
|
2154
|
-
const
|
|
2157
|
+
const cachedParsed = EnvelopeSchema.safeParse(JSON.parse(cached));
|
|
2158
|
+
if (!cachedParsed.success) throw new Error("invalid catalog response: missing rows");
|
|
2159
|
+
const { rows, revision: rev } = toEnvelope(cachedParsed.data);
|
|
2155
2160
|
liveCatalog.replace(rows);
|
|
2156
2161
|
liveState.origin = "last-good";
|
|
2157
2162
|
liveState.revision = rev;
|
|
@@ -2164,7 +2169,9 @@ async function prime(source, logger) {
|
|
|
2164
2169
|
logPrimed(logger, result);
|
|
2165
2170
|
return result;
|
|
2166
2171
|
} catch (cacheErr) {
|
|
2167
|
-
logger.warn(
|
|
2172
|
+
logger.warn(
|
|
2173
|
+
`[modelkit] catalog cache failed, using snapshot: ${describeError(cacheErr)}`
|
|
2174
|
+
);
|
|
2168
2175
|
liveCatalog.replace([...MODELS]);
|
|
2169
2176
|
liveState.origin = "snapshot";
|
|
2170
2177
|
liveState.revision = void 0;
|
|
@@ -2187,23 +2194,24 @@ async function refresh(source, logger) {
|
|
|
2187
2194
|
liveState.revision = fetched.revision;
|
|
2188
2195
|
await writeCache(source, logger, fetched.rows, fetched.revision);
|
|
2189
2196
|
} catch (err) {
|
|
2190
|
-
logger.warn(
|
|
2197
|
+
logger.warn(
|
|
2198
|
+
`[modelkit] catalog refresh failed, keeping current rows: ${describeError(err)}`
|
|
2199
|
+
);
|
|
2191
2200
|
}
|
|
2192
2201
|
}
|
|
2193
2202
|
function primeCatalog(source) {
|
|
2194
|
-
|
|
2195
|
-
if (memo) return memo;
|
|
2203
|
+
if (liveState.memo) return liveState.memo;
|
|
2196
2204
|
const logger = source.logger ?? console;
|
|
2197
|
-
|
|
2205
|
+
const pending = prime(source, logger).then((result) => {
|
|
2198
2206
|
const ttlMs = source.ttlMs ?? 3e5;
|
|
2199
2207
|
if (ttlMs > 0 && liveState.timer === void 0) {
|
|
2200
2208
|
liveState.timer = setInterval(() => void refresh(source, logger), ttlMs);
|
|
2201
|
-
|
|
2202
|
-
maybeUnref.unref?.();
|
|
2209
|
+
liveState.timer.unref?.();
|
|
2203
2210
|
}
|
|
2204
2211
|
return result;
|
|
2205
2212
|
});
|
|
2206
|
-
|
|
2213
|
+
liveState.memo = pending;
|
|
2214
|
+
return pending;
|
|
2207
2215
|
}
|
|
2208
2216
|
function resetLiveCatalog() {
|
|
2209
2217
|
if (liveState.timer !== void 0) {
|