@agentproto/catalog-sync 0.6.3 → 0.7.1

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.
@@ -4,23 +4,45 @@ import '../types.js';
4
4
  /**
5
5
  * OpenAI LLM source contract.
6
6
  *
7
- * OpenAI does **not** publish a stable, machine-readable pricing/model catalog
8
- * endpoint. The authoritative pricing page is `openai.com/api/pricing`, but it
9
- * is HTML-only, not a documented API, and has historically changed layout
10
- * without notice.
7
+ * This source used to be `refreshable: false`, on the stated grounds that
8
+ * "OpenAI does not publish a stable, machine-readable pricing/model catalog
9
+ * endpoint". That was two claims, and both have an answer:
11
10
  *
12
- * Therefore this source is intentionally **not refreshable** in the automated
13
- * `catalog-sync` workflow. Pricing is committed by hand from the official page
14
- * and cross-checked with third-party aggregators where noted. We do not scrape
15
- * or guess.
11
+ * - **Ids.** `GET https://api.openai.com/v1/models` is authoritative and
12
+ * always existed. It carries no price and no context window — which is
13
+ * why it cannot be the only source, not a reason to ignore it. Needs
14
+ * `OPENAI_API_KEY`; its absence degrades to OpenRouter ids, never to a
15
+ * failure.
16
+ * - **Prices.** `https://platform.openai.com/docs/pricing.md` is OpenAI's
17
+ * own Markdown rendering of the pricing page — `text/markdown`, GFM pipe
18
+ * tables with labelled header rows, and advertised on the page itself
19
+ * ("Markdown versions of documentation pages are available by appending
20
+ * `.md` to the page URL"). It is still docs, not a versioned API, so the
21
+ * parser reads columns by NAME and the result is sanity-checked before
22
+ * use (`checkOfficialPricingUsable`); a page restructure falls back to
23
+ * OpenRouter's passthrough rate rather than emitting wrong numbers.
16
24
  *
17
- * If OpenAI releases a stable `/v1/models` endpoint that includes pricing, or
18
- * a documented pricing JSON feed, this source can be upgraded to refreshable.
19
- * Until then, the gap is recorded honestly in refresh results.
25
+ * We still do NOT scrape the HTML pricing page's DOM, and still do not guess.
26
+ * Rows OpenAI does not price stay unpriced (`OPENAI_GENERATED_UNPRICED_IDS`)
27
+ * instead of getting a fabricated zero.
28
+ *
29
+ * The implementation lives in `./openai-catalog.mjs` (pure, tested) and
30
+ * `scripts/catalog-sync/sync-openai.mjs` (the I/O), rather than in a
31
+ * `defineGenerator` generator, because the per-vendor `sync-*.mjs` family is
32
+ * what writes the native `*-pricing.generated.ts` files; the weekly workflow
33
+ * runs both halves.
20
34
  */
21
35
 
36
+ /** Ids: OpenAI's own models list. Authed; skipped when the key is absent. */
37
+ declare const OPENAI_MODELS_SOURCE: RefreshableSource;
38
+ /** Prices: OpenAI's published pricing page, in its Markdown rendering. */
39
+ declare const OPENAI_PRICING_SOURCE: RefreshableSource;
40
+ /**
41
+ * Back-compat alias. Historically the single OpenAI source; now the id half,
42
+ * since that is the one this catalog treats as authoritative.
43
+ */
22
44
  declare const OPENAI_LLM_SOURCE: RefreshableSource;
23
45
  /** Convenience array for workflows that want to include the OpenAI contract. */
24
46
  declare const OPENAI_SOURCES: RefreshableSource[];
25
47
 
26
- export { OPENAI_LLM_SOURCE, OPENAI_SOURCES };
48
+ export { OPENAI_LLM_SOURCE, OPENAI_MODELS_SOURCE, OPENAI_PRICING_SOURCE, OPENAI_SOURCES };
@@ -5,16 +5,29 @@
5
5
  */
6
6
 
7
7
  // src/sources/openai.ts
8
- var OPENAI_LLM_SOURCE = {
8
+ var OPENAI_MODELS_SOURCE = {
9
9
  source: {
10
10
  id: "llm-openai",
11
- url: "https://openai.com/api/pricing"
11
+ url: "https://api.openai.com/v1/models",
12
+ headers: { Authorization: "Bearer env:OPENAI_API_KEY" }
12
13
  },
13
- refreshable: false,
14
- notes: "OpenAI has no stable machine-readable pricing endpoint. Pricing in @agentproto/model-catalog is committed manually from openai.com/api/pricing and verified against independent aggregators where possible. Automated refresh is disabled to avoid scraping or fabricating prices."
14
+ refreshable: true,
15
+ notes: "Authoritative OpenAI model id list. Carries no pricing and no context window, so it is merged with a price source rather than used alone. Without OPENAI_API_KEY the sync falls back to OpenRouter's openai/* ids."
15
16
  };
16
- var OPENAI_SOURCES = [OPENAI_LLM_SOURCE];
17
+ var OPENAI_PRICING_SOURCE = {
18
+ source: {
19
+ id: "llm-openai-pricing",
20
+ url: "https://platform.openai.com/docs/pricing.md"
21
+ },
22
+ refreshable: true,
23
+ notes: "OpenAI's own Markdown rendering of the pricing page (text/markdown, GFM tables). Parsed by column name and sanity-checked before use; on a page restructure the sync falls back to OpenRouter passthrough rates and says so in the generated file's banner."
24
+ };
25
+ var OPENAI_LLM_SOURCE = OPENAI_MODELS_SOURCE;
26
+ var OPENAI_SOURCES = [
27
+ OPENAI_MODELS_SOURCE,
28
+ OPENAI_PRICING_SOURCE
29
+ ];
17
30
 
18
- export { OPENAI_LLM_SOURCE, OPENAI_SOURCES };
31
+ export { OPENAI_LLM_SOURCE, OPENAI_MODELS_SOURCE, OPENAI_PRICING_SOURCE, OPENAI_SOURCES };
19
32
  //# sourceMappingURL=openai.mjs.map
20
33
  //# sourceMappingURL=openai.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sources/openai.ts"],"names":[],"mappings":";;;;;;;AAoBO,IAAM,iBAAA,GAAuC;AAAA,EAClD,MAAA,EAAQ;AAAA,IACN,EAAA,EAAI,YAAA;AAAA,IACJ,GAAA,EAAK;AAAA,GACP;AAAA,EACA,WAAA,EAAa,KAAA;AAAA,EACb,KAAA,EACE;AAKJ;AAGO,IAAM,cAAA,GAAsC,CAAC,iBAAiB","file":"openai.mjs","sourcesContent":["/**\n * OpenAI LLM source contract.\n *\n * OpenAI does **not** publish a stable, machine-readable pricing/model catalog\n * endpoint. The authoritative pricing page is `openai.com/api/pricing`, but it\n * is HTML-only, not a documented API, and has historically changed layout\n * without notice.\n *\n * Therefore this source is intentionally **not refreshable** in the automated\n * `catalog-sync` workflow. Pricing is committed by hand from the official page\n * and cross-checked with third-party aggregators where noted. We do not scrape\n * or guess.\n *\n * If OpenAI releases a stable `/v1/models` endpoint that includes pricing, or\n * a documented pricing JSON feed, this source can be upgraded to refreshable.\n * Until then, the gap is recorded honestly in refresh results.\n */\n\nimport type { RefreshableSource } from \"../refresh-workflow.js\"\n\nexport const OPENAI_LLM_SOURCE: RefreshableSource = {\n source: {\n id: \"llm-openai\",\n url: \"https://openai.com/api/pricing\",\n },\n refreshable: false,\n notes:\n \"OpenAI has no stable machine-readable pricing endpoint. \" +\n \"Pricing in @agentproto/model-catalog is committed manually from \" +\n \"openai.com/api/pricing and verified against independent aggregators \" +\n \"where possible. Automated refresh is disabled to avoid scraping or \" +\n \"fabricating prices.\",\n}\n\n/** Convenience array for workflows that want to include the OpenAI contract. */\nexport const OPENAI_SOURCES: RefreshableSource[] = [OPENAI_LLM_SOURCE]\n"]}
1
+ {"version":3,"sources":["../../src/sources/openai.ts"],"names":[],"mappings":";;;;;;;AAmCO,IAAM,oBAAA,GAA0C;AAAA,EACrD,MAAA,EAAQ;AAAA,IACN,EAAA,EAAI,YAAA;AAAA,IACJ,GAAA,EAAK,kCAAA;AAAA,IACL,OAAA,EAAS,EAAE,aAAA,EAAe,2BAAA;AAA4B,GACxD;AAAA,EACA,WAAA,EAAa,IAAA;AAAA,EACb,KAAA,EACE;AAGJ;AAGO,IAAM,qBAAA,GAA2C;AAAA,EACtD,MAAA,EAAQ;AAAA,IACN,EAAA,EAAI,oBAAA;AAAA,IACJ,GAAA,EAAK;AAAA,GACP;AAAA,EACA,WAAA,EAAa,IAAA;AAAA,EACb,KAAA,EACE;AAIJ;AAMO,IAAM,iBAAA,GAAuC;AAG7C,IAAM,cAAA,GAAsC;AAAA,EACjD,oBAAA;AAAA,EACA;AACF","file":"openai.mjs","sourcesContent":["/**\n * OpenAI LLM source contract.\n *\n * This source used to be `refreshable: false`, on the stated grounds that\n * \"OpenAI does not publish a stable, machine-readable pricing/model catalog\n * endpoint\". That was two claims, and both have an answer:\n *\n * - **Ids.** `GET https://api.openai.com/v1/models` is authoritative and\n * always existed. It carries no price and no context window — which is\n * why it cannot be the only source, not a reason to ignore it. Needs\n * `OPENAI_API_KEY`; its absence degrades to OpenRouter ids, never to a\n * failure.\n * - **Prices.** `https://platform.openai.com/docs/pricing.md` is OpenAI's\n * own Markdown rendering of the pricing page — `text/markdown`, GFM pipe\n * tables with labelled header rows, and advertised on the page itself\n * (\"Markdown versions of documentation pages are available by appending\n * `.md` to the page URL\"). It is still docs, not a versioned API, so the\n * parser reads columns by NAME and the result is sanity-checked before\n * use (`checkOfficialPricingUsable`); a page restructure falls back to\n * OpenRouter's passthrough rate rather than emitting wrong numbers.\n *\n * We still do NOT scrape the HTML pricing page's DOM, and still do not guess.\n * Rows OpenAI does not price stay unpriced (`OPENAI_GENERATED_UNPRICED_IDS`)\n * instead of getting a fabricated zero.\n *\n * The implementation lives in `./openai-catalog.mjs` (pure, tested) and\n * `scripts/catalog-sync/sync-openai.mjs` (the I/O), rather than in a\n * `defineGenerator` generator, because the per-vendor `sync-*.mjs` family is\n * what writes the native `*-pricing.generated.ts` files; the weekly workflow\n * runs both halves.\n */\n\nimport type { RefreshableSource } from \"../refresh-workflow.js\"\n\n/** Ids: OpenAI's own models list. Authed; skipped when the key is absent. */\nexport const OPENAI_MODELS_SOURCE: RefreshableSource = {\n source: {\n id: \"llm-openai\",\n url: \"https://api.openai.com/v1/models\",\n headers: { Authorization: \"Bearer env:OPENAI_API_KEY\" },\n },\n refreshable: true,\n notes:\n \"Authoritative OpenAI model id list. Carries no pricing and no context \" +\n \"window, so it is merged with a price source rather than used alone. \" +\n \"Without OPENAI_API_KEY the sync falls back to OpenRouter's openai/* ids.\",\n}\n\n/** Prices: OpenAI's published pricing page, in its Markdown rendering. */\nexport const OPENAI_PRICING_SOURCE: RefreshableSource = {\n source: {\n id: \"llm-openai-pricing\",\n url: \"https://platform.openai.com/docs/pricing.md\",\n },\n refreshable: true,\n notes:\n \"OpenAI's own Markdown rendering of the pricing page (text/markdown, GFM \" +\n \"tables). Parsed by column name and sanity-checked before use; on a page \" +\n \"restructure the sync falls back to OpenRouter passthrough rates and says \" +\n \"so in the generated file's banner.\",\n}\n\n/**\n * Back-compat alias. Historically the single OpenAI source; now the id half,\n * since that is the one this catalog treats as authoritative.\n */\nexport const OPENAI_LLM_SOURCE: RefreshableSource = OPENAI_MODELS_SOURCE\n\n/** Convenience array for workflows that want to include the OpenAI contract. */\nexport const OPENAI_SOURCES: RefreshableSource[] = [\n OPENAI_MODELS_SOURCE,\n OPENAI_PRICING_SOURCE,\n]\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/catalog-sync",
3
- "version": "0.6.3",
3
+ "version": "0.7.1",
4
4
  "description": "Build-time generator framework for @agentproto/model-catalog. Generates *.generated.ts from pinned provider sources (LLM, image, video, audio, voice).",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -79,7 +79,7 @@
79
79
  },
80
80
  "dependencies": {
81
81
  "zod": "^4.6.5",
82
- "@agentproto/model-catalog": "0.10.3"
82
+ "@agentproto/model-catalog": "0.11.1"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@types/node": "^25.9.5",