@agentproto/catalog-sync 0.5.7 → 0.5.9
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 +74 -0
- package/dist/bin.mjs +248 -13
- package/dist/bin.mjs.map +1 -1
- package/dist/generators/llm-openrouter.mjs +66 -2
- package/dist/generators/llm-openrouter.mjs.map +1 -1
- package/dist/generators/llm-requesty.mjs +66 -2
- package/dist/generators/llm-requesty.mjs.map +1 -1
- package/dist/index.d.ts +98 -2
- package/dist/index.mjs +168 -15
- package/dist/index.mjs.map +1 -1
- package/dist/runner.d.ts +8 -1
- package/dist/runner.mjs +79 -3
- package/dist/runner.mjs.map +1 -1
- package/package.json +3 -3
- package/snapshots/llm-huggingface.json +2716 -2377
- package/snapshots/llm-mistral.json +1941 -0
- package/snapshots/llm-moonshot.json +8 -166
- package/snapshots/llm-openrouter.json +8629 -8658
- package/snapshots/llm-requesty.json +21768 -7459
- package/snapshots/llm-xai.json +48 -2
- package/snapshots/voice-elevenlabs.json +5607 -5415
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
2
|
import { dirname, join, resolve } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { z } from 'zod';
|
|
@@ -14,22 +14,111 @@ import { ElevenLabsVoicesSnapshotSchema, mapElevenLabsVoices, MinimaxVoicesSnaps
|
|
|
14
14
|
function defineGenerator(g) {
|
|
15
15
|
return g;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
// src/changelog.ts
|
|
19
|
+
var RECORD_KEY_RE = /^ {2}"([^"]+)":\s*\{/gm;
|
|
20
|
+
function extractRecordIds(source) {
|
|
21
|
+
const ids = /* @__PURE__ */ new Set();
|
|
22
|
+
for (const m of source.matchAll(RECORD_KEY_RE)) {
|
|
23
|
+
if (m[1] !== void 0) ids.add(m[1]);
|
|
24
|
+
}
|
|
25
|
+
return ids;
|
|
26
|
+
}
|
|
27
|
+
function diffModelIds(before, after) {
|
|
28
|
+
const beforeIds = before !== void 0 ? extractRecordIds(before) : /* @__PURE__ */ new Set();
|
|
29
|
+
const afterIds = extractRecordIds(after);
|
|
30
|
+
const added = [...afterIds].filter((id) => !beforeIds.has(id)).sort();
|
|
31
|
+
const removed = [...beforeIds].filter((id) => !afterIds.has(id)).sort();
|
|
32
|
+
return { added, removed };
|
|
33
|
+
}
|
|
34
|
+
function renderChangelogSection(date, entries) {
|
|
35
|
+
const nonEmpty = entries.filter((e) => e.added.length > 0 || e.removed.length > 0);
|
|
36
|
+
if (nonEmpty.length === 0) return "";
|
|
37
|
+
const lines = [`## ${date}`, ""];
|
|
38
|
+
for (const e of nonEmpty) {
|
|
39
|
+
lines.push(`### ${e.generator}`);
|
|
40
|
+
if (e.added.length > 0) lines.push(`- Added: ${e.added.join(", ")}`);
|
|
41
|
+
if (e.removed.length > 0) lines.push(`- Removed: ${e.removed.join(", ")}`);
|
|
42
|
+
lines.push("");
|
|
43
|
+
}
|
|
44
|
+
return lines.join("\n").replace(/\n+$/, "\n");
|
|
45
|
+
}
|
|
46
|
+
var CATALOG_CHANGELOG_HEADER = `# Catalog Changelog
|
|
47
|
+
|
|
48
|
+
Human-readable log of model additions/removals detected by
|
|
49
|
+
\`@agentproto/catalog-sync\` runs \u2014 NOT \`CHANGELOG.md\` next to it (that one is
|
|
50
|
+
changesets-driven package-version history). A dated section is appended
|
|
51
|
+
automatically here whenever a sync run adds or removes model ids; sections
|
|
52
|
+
are appended at the END of the file (newest last). Pricing-only drift (no id
|
|
53
|
+
added/removed) is not logged here \u2014 see the generated files' own git history
|
|
54
|
+
for that.
|
|
55
|
+
`;
|
|
56
|
+
function appendChangelog(existing, date, entries) {
|
|
57
|
+
const section = renderChangelogSection(date, entries);
|
|
58
|
+
if (section === "") return void 0;
|
|
59
|
+
const base = existing !== void 0 && existing.length > 0 ? existing.replace(/\n+$/, "\n") : CATALOG_CHANGELOG_HEADER;
|
|
60
|
+
return `${base}
|
|
61
|
+
${section}`;
|
|
62
|
+
}
|
|
17
63
|
var __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
18
64
|
function catalogSyncDir() {
|
|
19
65
|
return resolve(__dirname$1, "..");
|
|
20
66
|
}
|
|
67
|
+
function ledgerAbsPath(ledgerId) {
|
|
68
|
+
return join(catalogSyncDir(), "ledger", `${ledgerId}.json`);
|
|
69
|
+
}
|
|
70
|
+
function ledgerRelPath(ledgerId) {
|
|
71
|
+
return `packages/catalog-sync/ledger/${ledgerId}.json`;
|
|
72
|
+
}
|
|
73
|
+
function readLedger(ledgerId) {
|
|
74
|
+
const path = ledgerAbsPath(ledgerId);
|
|
75
|
+
if (!existsSync(path)) return {};
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
78
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
79
|
+
return parsed;
|
|
80
|
+
} catch {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function serializeLedger(ledger) {
|
|
85
|
+
const sorted = {};
|
|
86
|
+
for (const id of Object.keys(ledger).sort()) sorted[id] = ledger[id];
|
|
87
|
+
return `${JSON.stringify(sorted, null, 2)}
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
function computeAddedAtLedger(currentIds, previous, createdAt, today) {
|
|
91
|
+
const next = { ...previous };
|
|
92
|
+
for (const id of currentIds) {
|
|
93
|
+
if (next[id] !== void 0) continue;
|
|
94
|
+
next[id] = createdAt[id] ?? today;
|
|
95
|
+
}
|
|
96
|
+
return next;
|
|
97
|
+
}
|
|
98
|
+
function todayIso() {
|
|
99
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
100
|
+
}
|
|
101
|
+
function isoDateFromUnixSeconds(seconds) {
|
|
102
|
+
return new Date(seconds * 1e3).toISOString().slice(0, 10);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/runner.ts
|
|
106
|
+
var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
107
|
+
function catalogSyncDir2() {
|
|
108
|
+
return resolve(__dirname2, "..");
|
|
109
|
+
}
|
|
21
110
|
function snapshotPath(id) {
|
|
22
|
-
return join(
|
|
111
|
+
return join(catalogSyncDir2(), "snapshots", `${id}.json`);
|
|
23
112
|
}
|
|
24
113
|
function repoRoot() {
|
|
25
|
-
let dir =
|
|
114
|
+
let dir = catalogSyncDir2();
|
|
26
115
|
for (let i = 0; i < 12; i++) {
|
|
27
116
|
if (existsSync(join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
28
117
|
const parent = dirname(dir);
|
|
29
118
|
if (parent === dir) break;
|
|
30
119
|
dir = parent;
|
|
31
120
|
}
|
|
32
|
-
return dirname(dirname(
|
|
121
|
+
return dirname(dirname(catalogSyncDir2()));
|
|
33
122
|
}
|
|
34
123
|
function readIfExists(absPath) {
|
|
35
124
|
if (!existsSync(absPath)) return void 0;
|
|
@@ -51,8 +140,13 @@ function resolveHeaders(headers) {
|
|
|
51
140
|
}
|
|
52
141
|
return { headers: out, missing };
|
|
53
142
|
}
|
|
143
|
+
var CATALOG_CHANGELOG_PATH = "packages/model-catalog/CATALOG-CHANGELOG.md";
|
|
144
|
+
function isChangelogEligible(relPath) {
|
|
145
|
+
return relPath.endsWith(".generated.ts");
|
|
146
|
+
}
|
|
54
147
|
async function runGenerators(gens, opts) {
|
|
55
148
|
const files = {};
|
|
149
|
+
const pathToGenerator = {};
|
|
56
150
|
for (const gen of gens) {
|
|
57
151
|
const ctx = {
|
|
58
152
|
refresh: opts.refresh,
|
|
@@ -99,10 +193,12 @@ async function runGenerators(gens, opts) {
|
|
|
99
193
|
const out = await gen.generate(ctx);
|
|
100
194
|
for (const [path, content] of Object.entries(out)) {
|
|
101
195
|
files[path] = content;
|
|
196
|
+
pathToGenerator[path] = gen.name;
|
|
102
197
|
}
|
|
103
198
|
}
|
|
104
199
|
const root = repoRoot();
|
|
105
200
|
const changed = [];
|
|
201
|
+
const changelogEntries = [];
|
|
106
202
|
for (const [relPath, content] of Object.entries(files)) {
|
|
107
203
|
const abs = join(root, relPath);
|
|
108
204
|
const existing = readIfExists(abs);
|
|
@@ -113,6 +209,23 @@ async function runGenerators(gens, opts) {
|
|
|
113
209
|
writeFileSync(abs, content, "utf8");
|
|
114
210
|
}
|
|
115
211
|
}
|
|
212
|
+
if (isChangelogEligible(relPath)) {
|
|
213
|
+
const { added, removed } = diffModelIds(existing, content);
|
|
214
|
+
if (added.length > 0 || removed.length > 0) {
|
|
215
|
+
changelogEntries.push({ generator: pathToGenerator[relPath] ?? relPath, added, removed });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const changelogAbs = join(root, CATALOG_CHANGELOG_PATH);
|
|
220
|
+
const changelogExisting = readIfExists(changelogAbs);
|
|
221
|
+
const newChangelog = appendChangelog(changelogExisting, todayIso(), changelogEntries);
|
|
222
|
+
if (newChangelog !== void 0) {
|
|
223
|
+
files[CATALOG_CHANGELOG_PATH] = newChangelog;
|
|
224
|
+
changed.push(CATALOG_CHANGELOG_PATH);
|
|
225
|
+
if (opts.write) {
|
|
226
|
+
mkdirSync(dirname(changelogAbs), { recursive: true });
|
|
227
|
+
writeFileSync(changelogAbs, newChangelog, "utf8");
|
|
228
|
+
}
|
|
116
229
|
}
|
|
117
230
|
return { files, changed };
|
|
118
231
|
}
|
|
@@ -126,7 +239,8 @@ var PricingSchema = z.object({
|
|
|
126
239
|
}).passthrough();
|
|
127
240
|
var ModelSchema = z.object({
|
|
128
241
|
id: z.string(),
|
|
129
|
-
pricing: PricingSchema.optional()
|
|
242
|
+
pricing: PricingSchema.optional(),
|
|
243
|
+
created: z.number().optional()
|
|
130
244
|
}).passthrough();
|
|
131
245
|
var SnapshotSchema = z.object({
|
|
132
246
|
data: z.array(ModelSchema)
|
|
@@ -159,6 +273,9 @@ function serializeEntry(e) {
|
|
|
159
273
|
if (e.cacheWriteMultiplier !== void 0) {
|
|
160
274
|
fields.push(`cacheWriteMultiplier: ${fmt(e.cacheWriteMultiplier)}`);
|
|
161
275
|
}
|
|
276
|
+
if (e.addedAt !== void 0) {
|
|
277
|
+
fields.push(`addedAt: ${JSON.stringify(e.addedAt)}`);
|
|
278
|
+
}
|
|
162
279
|
fields.push(`vendor: ${JSON.stringify(e.vendor)}`);
|
|
163
280
|
fields.push(`provider: ${JSON.stringify(e.provider)}`);
|
|
164
281
|
return `{
|
|
@@ -175,6 +292,9 @@ function serializeFile(entries) {
|
|
|
175
292
|
"// Pricing carries provider USD (inputPer1M / outputPer1M) plus cache",
|
|
176
293
|
"// multipliers (cacheReadMultiplier / cacheWriteMultiplier) derived from the",
|
|
177
294
|
"// source's input_cache_read / input_cache_write per-token fields when present.",
|
|
295
|
+
"// addedAt is the ISO date this id was first seen by a sync run \u2014 backfilled",
|
|
296
|
+
"// from the source's own `created` timestamp, then NEVER mutated; see",
|
|
297
|
+
"// packages/catalog-sync/src/added-at.ts and the package README.",
|
|
178
298
|
"",
|
|
179
299
|
'import type { LLMPricing } from "./catalog.js"',
|
|
180
300
|
"",
|
|
@@ -194,11 +314,13 @@ function serializeFile(entries) {
|
|
|
194
314
|
lines.push("");
|
|
195
315
|
return lines.join("\n");
|
|
196
316
|
}
|
|
317
|
+
var LEDGER_ID = "llm-openrouter";
|
|
197
318
|
async function generate(ctx) {
|
|
198
319
|
const src = sources[0];
|
|
199
320
|
if (!src) throw new Error("llm:openrouter: no source configured");
|
|
200
321
|
const parsed = SnapshotSchema.parse(await ctx.fetchSource(src));
|
|
201
322
|
const entries = {};
|
|
323
|
+
const createdAt = {};
|
|
202
324
|
for (const model of parsed.data) {
|
|
203
325
|
const pricing = model.pricing;
|
|
204
326
|
if (!pricing) continue;
|
|
@@ -221,8 +343,19 @@ async function generate(ctx) {
|
|
|
221
343
|
entry.cacheWriteMultiplier = round6(cacheWritePer1M / inputPer1M);
|
|
222
344
|
}
|
|
223
345
|
entries[model.id] = entry;
|
|
346
|
+
if (model.created !== void 0) createdAt[model.id] = isoDateFromUnixSeconds(model.created);
|
|
224
347
|
}
|
|
225
|
-
|
|
348
|
+
const ledger = computeAddedAtLedger(
|
|
349
|
+
Object.keys(entries),
|
|
350
|
+
readLedger(LEDGER_ID),
|
|
351
|
+
createdAt,
|
|
352
|
+
todayIso()
|
|
353
|
+
);
|
|
354
|
+
for (const [id, entry] of Object.entries(entries)) entry.addedAt = ledger[id];
|
|
355
|
+
return {
|
|
356
|
+
[OUTPUT_PATH]: serializeFile(entries),
|
|
357
|
+
[ledgerRelPath(LEDGER_ID)]: serializeLedger(ledger)
|
|
358
|
+
};
|
|
226
359
|
}
|
|
227
360
|
var sources = [{ id: "llm-openrouter", url: OPENROUTER_MODELS_URL }];
|
|
228
361
|
var llmOpenRouterGenerator = defineGenerator({
|
|
@@ -238,7 +371,8 @@ var ModelSchema2 = z.object({
|
|
|
238
371
|
input_price: z.number().optional(),
|
|
239
372
|
output_price: z.number().optional(),
|
|
240
373
|
cached_price: z.number().optional(),
|
|
241
|
-
supports_caching: z.boolean().optional()
|
|
374
|
+
supports_caching: z.boolean().optional(),
|
|
375
|
+
created: z.number().optional()
|
|
242
376
|
}).passthrough();
|
|
243
377
|
var SnapshotSchema2 = z.object({
|
|
244
378
|
data: z.array(ModelSchema2)
|
|
@@ -267,6 +401,9 @@ function serializeEntry2(e) {
|
|
|
267
401
|
if (e.cacheReadMultiplier !== void 0) {
|
|
268
402
|
fields.push(`cacheReadMultiplier: ${fmt2(e.cacheReadMultiplier)}`);
|
|
269
403
|
}
|
|
404
|
+
if (e.addedAt !== void 0) {
|
|
405
|
+
fields.push(`addedAt: ${JSON.stringify(e.addedAt)}`);
|
|
406
|
+
}
|
|
270
407
|
fields.push(`vendor: ${JSON.stringify(e.vendor)}`);
|
|
271
408
|
fields.push(`provider: ${JSON.stringify(e.provider)}`);
|
|
272
409
|
return `{
|
|
@@ -284,6 +421,9 @@ function serializeFile2(entries) {
|
|
|
284
421
|
"// multiplier (cacheReadMultiplier) derived from the source's cached_price",
|
|
285
422
|
"// per-token field when `supports_caching` is true. Requesty has no",
|
|
286
423
|
"// cache-write price, so cacheWriteMultiplier is never emitted.",
|
|
424
|
+
"// addedAt is the ISO date this id was first seen by a sync run \u2014 backfilled",
|
|
425
|
+
"// from the source's own `created` timestamp, then NEVER mutated; see",
|
|
426
|
+
"// packages/catalog-sync/src/added-at.ts and the package README.",
|
|
287
427
|
"",
|
|
288
428
|
'import type { LLMPricing } from "./catalog.js"',
|
|
289
429
|
"",
|
|
@@ -303,11 +443,13 @@ function serializeFile2(entries) {
|
|
|
303
443
|
lines.push("");
|
|
304
444
|
return lines.join("\n");
|
|
305
445
|
}
|
|
446
|
+
var LEDGER_ID2 = "llm-requesty";
|
|
306
447
|
async function generate2(ctx) {
|
|
307
448
|
const src = sources2[0];
|
|
308
449
|
if (!src) throw new Error("llm:requesty: no source configured");
|
|
309
450
|
const parsed = SnapshotSchema2.parse(await ctx.fetchSource(src));
|
|
310
451
|
const entries = {};
|
|
452
|
+
const createdAt = {};
|
|
311
453
|
for (const model of parsed.data) {
|
|
312
454
|
const inputPer1M = per1m2(model.input_price);
|
|
313
455
|
const outputPer1M = per1m2(model.output_price);
|
|
@@ -326,8 +468,19 @@ async function generate2(ctx) {
|
|
|
326
468
|
}
|
|
327
469
|
}
|
|
328
470
|
entries[model.id] = entry;
|
|
471
|
+
if (model.created !== void 0) createdAt[model.id] = isoDateFromUnixSeconds(model.created);
|
|
329
472
|
}
|
|
330
|
-
|
|
473
|
+
const ledger = computeAddedAtLedger(
|
|
474
|
+
Object.keys(entries),
|
|
475
|
+
readLedger(LEDGER_ID2),
|
|
476
|
+
createdAt,
|
|
477
|
+
todayIso()
|
|
478
|
+
);
|
|
479
|
+
for (const [id, entry] of Object.entries(entries)) entry.addedAt = ledger[id];
|
|
480
|
+
return {
|
|
481
|
+
[OUTPUT_PATH2]: serializeFile2(entries),
|
|
482
|
+
[ledgerRelPath(LEDGER_ID2)]: serializeLedger(ledger)
|
|
483
|
+
};
|
|
331
484
|
}
|
|
332
485
|
var sources2 = [
|
|
333
486
|
{
|
|
@@ -844,22 +997,22 @@ var imageReplicate = defineGenerator({
|
|
|
844
997
|
return { [outputPath]: lines.join("\n") };
|
|
845
998
|
}
|
|
846
999
|
});
|
|
847
|
-
var
|
|
848
|
-
function
|
|
849
|
-
return resolve(
|
|
1000
|
+
var __dirname3 = dirname(fileURLToPath(import.meta.url));
|
|
1001
|
+
function catalogSyncDir3() {
|
|
1002
|
+
return resolve(__dirname3, "..");
|
|
850
1003
|
}
|
|
851
1004
|
function snapshotPath2(id) {
|
|
852
|
-
return join(
|
|
1005
|
+
return join(catalogSyncDir3(), "snapshots", `${id}.json`);
|
|
853
1006
|
}
|
|
854
1007
|
function repoRoot2() {
|
|
855
|
-
let dir =
|
|
1008
|
+
let dir = catalogSyncDir3();
|
|
856
1009
|
for (let i = 0; i < 12; i++) {
|
|
857
1010
|
if (existsSync(join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
858
1011
|
const parent = dirname(dir);
|
|
859
1012
|
if (parent === dir) break;
|
|
860
1013
|
dir = parent;
|
|
861
1014
|
}
|
|
862
|
-
return dirname(dirname(
|
|
1015
|
+
return dirname(dirname(catalogSyncDir3()));
|
|
863
1016
|
}
|
|
864
1017
|
function readIfExists2(absPath) {
|
|
865
1018
|
if (!existsSync(absPath)) return void 0;
|
|
@@ -1003,6 +1156,6 @@ var OPENAI_LLM_SOURCE = {
|
|
|
1003
1156
|
};
|
|
1004
1157
|
var OPENAI_SOURCES = [OPENAI_LLM_SOURCE];
|
|
1005
1158
|
|
|
1006
|
-
export { OPENAI_LLM_SOURCE, OPENAI_SOURCES, defineGenerator, imageReplicate, llmHuggingfaceGenerator, llmOpenRouterGenerator, llmRequestyGenerator, refreshSources, reviewedRefresh, runGenerators, voiceElevenlabs, voiceMinimax };
|
|
1159
|
+
export { CATALOG_CHANGELOG_HEADER, CATALOG_CHANGELOG_PATH, OPENAI_LLM_SOURCE, OPENAI_SOURCES, appendChangelog, computeAddedAtLedger, defineGenerator, diffModelIds, extractRecordIds, imageReplicate, isoDateFromUnixSeconds, ledgerAbsPath, ledgerRelPath, llmHuggingfaceGenerator, llmOpenRouterGenerator, llmRequestyGenerator, readLedger, refreshSources, renderChangelogSection, reviewedRefresh, runGenerators, serializeLedger, todayIso, voiceElevenlabs, voiceMinimax };
|
|
1007
1160
|
//# sourceMappingURL=index.mjs.map
|
|
1008
1161
|
//# sourceMappingURL=index.mjs.map
|