@agentproto/catalog-sync 0.4.0 → 0.5.0

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 CHANGED
@@ -66,3 +66,18 @@ Source: `https://openrouter.ai/api/v1/models` (pinned snapshot:
66
66
  (P3 spec: "plus cache fields if the source has them") — additive and
67
67
  `LLMPricing`-compatible.
68
68
  - Unpriced routes (`openrouter/auto`) are skipped.
69
+
70
+ ### `llm:context-windows`
71
+
72
+ Sources: Anthropic, Groq, xAI, and Moonshot models-list endpoints (pinned
73
+ snapshots: `snapshots/llm-anthropic.json`, `snapshots/llm-groq.json`,
74
+ `snapshots/llm-xai.json`, `snapshots/llm-moonshot.json`). Emits
75
+ `packages/model-catalog/src/llm/context-windows.generated.ts` — a drop-in
76
+ `CONTEXT_WINDOWS: Record<string, ContextWindowEntry>`.
77
+
78
+ - `contextWindow` maps to each provider's max-input/context-length field.
79
+ - `maxOutput` is captured when the source publishes one.
80
+ - This is **not pricing**; billing data still comes from `llm:openrouter` and
81
+ hand-maintained pricing entries in `model-catalog`.
82
+ - OpenAI and ZAI/Zhipu are excluded because they don't publish a stable,
83
+ machine-readable context-window list.
package/dist/bin.mjs CHANGED
@@ -133,7 +133,120 @@ var llmOpenRouterGenerator = defineGenerator({
133
133
  sources,
134
134
  generate
135
135
  });
136
- var OUTPUT_PATH2 = "packages/model-catalog/src/llm/context-windows.generated.ts";
136
+ var REQUESTY_MODELS_URL = "https://router.requesty.ai/v1/models";
137
+ var OUTPUT_PATH2 = "packages/model-catalog/src/llm/requesty-routes.generated.ts";
138
+ var ModelSchema2 = z.object({
139
+ id: z.string(),
140
+ input_price: z.number().optional(),
141
+ output_price: z.number().optional(),
142
+ cached_price: z.number().optional(),
143
+ supports_caching: z.boolean().optional()
144
+ }).passthrough();
145
+ var SnapshotSchema2 = z.object({
146
+ data: z.array(ModelSchema2)
147
+ });
148
+ function round62(n) {
149
+ return Math.round(n * 1e6) / 1e6;
150
+ }
151
+ function per1m2(tokenPrice) {
152
+ if (tokenPrice === void 0) return void 0;
153
+ if (!Number.isFinite(tokenPrice)) return void 0;
154
+ return round62(tokenPrice * 1e6);
155
+ }
156
+ function fmt2(n) {
157
+ if (!Number.isFinite(n)) return "0";
158
+ return `${round62(n)}`;
159
+ }
160
+ function vendorOf2(id) {
161
+ if (!id.includes("/")) return id;
162
+ return id.split("/")[0] ?? id;
163
+ }
164
+ function serializeEntry2(e) {
165
+ const fields = [
166
+ `inputPer1M: ${fmt2(e.inputPer1M)}`,
167
+ `outputPer1M: ${fmt2(e.outputPer1M)}`
168
+ ];
169
+ if (e.cacheReadMultiplier !== void 0) {
170
+ fields.push(`cacheReadMultiplier: ${fmt2(e.cacheReadMultiplier)}`);
171
+ }
172
+ fields.push(`vendor: ${JSON.stringify(e.vendor)}`);
173
+ fields.push(`provider: ${JSON.stringify(e.provider)}`);
174
+ return `{
175
+ ${fields.join(",\n ")},
176
+ }`;
177
+ }
178
+ function serializeFile2(entries) {
179
+ const ids = Object.keys(entries).sort();
180
+ const providers = Array.from(new Set(ids.map(vendorOf2))).sort();
181
+ const lines = [
182
+ "// AUTO-GENERATED by @agentproto/catalog-sync (llm:requesty).",
183
+ "// Do not edit by hand \u2014 re-run `pnpm --filter @agentproto/catalog-sync generate`.",
184
+ `// Source: ${REQUESTY_MODELS_URL}`,
185
+ "// Pricing carries provider USD (inputPer1M / outputPer1M) plus a cache",
186
+ "// multiplier (cacheReadMultiplier) derived from the source's cached_price",
187
+ "// per-token field when `supports_caching` is true. Requesty has no",
188
+ "// cache-write price, so cacheWriteMultiplier is never emitted.",
189
+ "",
190
+ 'import type { LLMPricing } from "./catalog.js"',
191
+ "",
192
+ "export const REQUESTY_ROUTES: Record<string, LLMPricing> = {"
193
+ ];
194
+ for (const id of ids) {
195
+ lines.push(` ${JSON.stringify(id)}: ${serializeEntry2(entries[id])},`);
196
+ }
197
+ lines.push("}");
198
+ lines.push("");
199
+ lines.push("/** Provider slugs treated as Requesty routes by the picker. */");
200
+ lines.push("export const REQUESTY_PROVIDERS: readonly string[] = [");
201
+ for (const p of providers) {
202
+ lines.push(` ${JSON.stringify(p)},`);
203
+ }
204
+ lines.push("]");
205
+ lines.push("");
206
+ return lines.join("\n");
207
+ }
208
+ async function generate2(ctx) {
209
+ const src = sources2[0];
210
+ if (!src) throw new Error("llm:requesty: no source configured");
211
+ const parsed = SnapshotSchema2.parse(await ctx.fetchSource(src));
212
+ const entries = {};
213
+ for (const model of parsed.data) {
214
+ const inputPer1M = per1m2(model.input_price);
215
+ const outputPer1M = per1m2(model.output_price);
216
+ if (inputPer1M === void 0 || outputPer1M === void 0) continue;
217
+ if (inputPer1M === 0 && outputPer1M === 0) continue;
218
+ const entry = {
219
+ inputPer1M,
220
+ outputPer1M,
221
+ vendor: vendorOf2(model.id),
222
+ provider: "requesty"
223
+ };
224
+ if (model.supports_caching === true && inputPer1M > 0) {
225
+ const cachePer1M = per1m2(model.cached_price);
226
+ if (cachePer1M !== void 0) {
227
+ entry.cacheReadMultiplier = round62(cachePer1M / inputPer1M);
228
+ }
229
+ }
230
+ entries[model.id] = entry;
231
+ }
232
+ return { [OUTPUT_PATH2]: serializeFile2(entries) };
233
+ }
234
+ var sources2 = [
235
+ {
236
+ id: "llm-requesty",
237
+ url: REQUESTY_MODELS_URL,
238
+ // Live refresh needs the account key (Bearer). Without REQUESTY_API_KEY
239
+ // set, the framework reuses the committed snapshot.
240
+ headers: { Authorization: "Bearer env:REQUESTY_API_KEY" }
241
+ }
242
+ ];
243
+ var llmRequestyGenerator = defineGenerator({
244
+ name: "llm:requesty",
245
+ modality: "llm",
246
+ sources: sources2,
247
+ generate: generate2
248
+ });
249
+ var OUTPUT_PATH3 = "packages/model-catalog/src/llm/context-windows.generated.ts";
137
250
  var AnthropicModelSchema = z.object({
138
251
  id: z.string(),
139
252
  display_name: z.string().optional(),
@@ -157,14 +270,14 @@ var MoonshotModelSchema = z.object({
157
270
  context_length: z.number().optional()
158
271
  }).passthrough();
159
272
  var MoonshotSnapshotSchema = z.object({ data: z.array(MoonshotModelSchema) });
160
- function serializeEntry2(e) {
273
+ function serializeEntry3(e) {
161
274
  const fields = [`contextWindow: ${e.contextWindow}`];
162
275
  if (e.maxOutput !== void 0) fields.push(`maxOutput: ${e.maxOutput}`);
163
276
  if (e.displayName !== void 0) fields.push(`displayName: ${JSON.stringify(e.displayName)}`);
164
277
  fields.push(`provider: ${JSON.stringify(e.provider)}`);
165
278
  return `{ ${fields.join(", ")} }`;
166
279
  }
167
- function serializeFile2(entries) {
280
+ function serializeFile3(entries) {
168
281
  const ids = Object.keys(entries).sort();
169
282
  const lines = [
170
283
  "// AUTO-GENERATED by @agentproto/catalog-sync (llm:context-windows).",
@@ -184,15 +297,15 @@ function serializeFile2(entries) {
184
297
  "export const CONTEXT_WINDOWS: Record<string, ContextWindowEntry> = {"
185
298
  ];
186
299
  for (const id of ids) {
187
- lines.push(` ${JSON.stringify(id)}: ${serializeEntry2(entries[id])},`);
300
+ lines.push(` ${JSON.stringify(id)}: ${serializeEntry3(entries[id])},`);
188
301
  }
189
302
  lines.push("}");
190
303
  lines.push("");
191
304
  return lines.join("\n");
192
305
  }
193
- async function generate2(ctx) {
306
+ async function generate3(ctx) {
194
307
  const entries = {};
195
- const anthropicSrc = sources2.find((s) => s.id === "llm-anthropic");
308
+ const anthropicSrc = sources3.find((s) => s.id === "llm-anthropic");
196
309
  if (anthropicSrc) {
197
310
  const parsed = AnthropicSnapshotSchema.parse(await ctx.fetchSource(anthropicSrc));
198
311
  for (const m of parsed.data) {
@@ -205,7 +318,7 @@ async function generate2(ctx) {
205
318
  };
206
319
  }
207
320
  }
208
- const groqSrc = sources2.find((s) => s.id === "llm-groq");
321
+ const groqSrc = sources3.find((s) => s.id === "llm-groq");
209
322
  if (groqSrc) {
210
323
  const parsed = GroqSnapshotSchema.parse(await ctx.fetchSource(groqSrc));
211
324
  for (const m of parsed.data) {
@@ -217,7 +330,7 @@ async function generate2(ctx) {
217
330
  };
218
331
  }
219
332
  }
220
- const xaiSrc = sources2.find((s) => s.id === "llm-xai");
333
+ const xaiSrc = sources3.find((s) => s.id === "llm-xai");
221
334
  if (xaiSrc) {
222
335
  const parsed = XaiSnapshotSchema.parse(await ctx.fetchSource(xaiSrc));
223
336
  for (const m of parsed.data) {
@@ -225,7 +338,7 @@ async function generate2(ctx) {
225
338
  entries[m.id] = { contextWindow: m.context_length, provider: "xai" };
226
339
  }
227
340
  }
228
- const moonshotSrc = sources2.find((s) => s.id === "llm-moonshot");
341
+ const moonshotSrc = sources3.find((s) => s.id === "llm-moonshot");
229
342
  if (moonshotSrc) {
230
343
  const parsed = MoonshotSnapshotSchema.parse(await ctx.fetchSource(moonshotSrc));
231
344
  for (const m of parsed.data) {
@@ -233,9 +346,9 @@ async function generate2(ctx) {
233
346
  entries[m.id] = { contextWindow: m.context_length, provider: "moonshot" };
234
347
  }
235
348
  }
236
- return { [OUTPUT_PATH2]: serializeFile2(entries) };
349
+ return { [OUTPUT_PATH3]: serializeFile3(entries) };
237
350
  }
238
- var sources2 = [
351
+ var sources3 = [
239
352
  {
240
353
  id: "llm-anthropic",
241
354
  url: "https://api.anthropic.com/v1/models?limit=1000",
@@ -263,8 +376,8 @@ var sources2 = [
263
376
  var llmContextWindowsGenerator = defineGenerator({
264
377
  name: "llm:context-windows",
265
378
  modality: "llm",
266
- sources: sources2,
267
- generate: generate2
379
+ sources: sources3,
380
+ generate: generate3
268
381
  });
269
382
 
270
383
  // src/generators/serialize-voices.ts
@@ -309,7 +422,7 @@ var ELEVENLABS_SOURCE = {
309
422
  // Live refresh needs the account key; offline reads ignore this.
310
423
  headers: { "xi-api-key": "env:ELEVENLABS_API_KEY" }
311
424
  };
312
- var OUTPUT_PATH3 = "packages/catalog-sync/generated/voice-elevenlabs.generated.ts";
425
+ var OUTPUT_PATH4 = "packages/catalog-sync/generated/voice-elevenlabs.generated.ts";
313
426
  var voiceElevenlabs = defineGenerator({
314
427
  name: "voice:elevenlabs",
315
428
  modality: "voice",
@@ -320,7 +433,7 @@ var voiceElevenlabs = defineGenerator({
320
433
  );
321
434
  const voices = mapElevenLabsVoices(snapshot);
322
435
  return {
323
- [OUTPUT_PATH3]: serializeVoiceModule(
436
+ [OUTPUT_PATH4]: serializeVoiceModule(
324
437
  "voice:elevenlabs",
325
438
  "ELEVENLABS_VOICES",
326
439
  voices
@@ -340,7 +453,7 @@ var MINIMAX_SOURCE = {
340
453
  },
341
454
  body: { voice_type: "system" }
342
455
  };
343
- var OUTPUT_PATH4 = "packages/catalog-sync/generated/voice-minimax.generated.ts";
456
+ var OUTPUT_PATH5 = "packages/catalog-sync/generated/voice-minimax.generated.ts";
344
457
  var voiceMinimax = defineGenerator({
345
458
  name: "voice:minimax",
346
459
  modality: "voice",
@@ -351,7 +464,7 @@ var voiceMinimax = defineGenerator({
351
464
  );
352
465
  const voices = mapMinimaxVoices(snapshot);
353
466
  return {
354
- [OUTPUT_PATH4]: serializeVoiceModule(
467
+ [OUTPUT_PATH5]: serializeVoiceModule(
355
468
  "voice:minimax",
356
469
  "MINIMAX_VOICES",
357
470
  voices
@@ -764,6 +877,7 @@ var refresh = flags.has("--refresh");
764
877
  var check = flags.has("--check");
765
878
  var generators = [
766
879
  llmOpenRouterGenerator,
880
+ llmRequestyGenerator,
767
881
  llmContextWindowsGenerator,
768
882
  voiceElevenlabs,
769
883
  voiceMinimax,