@oh-my-pi/pi-catalog 18.2.7 → 18.2.8
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 +10 -3
- package/README.md +18 -18
- package/dist/types/compat/types.d.ts +2 -2
- package/dist/types/types.d.ts +5 -2
- package/package.json +38 -38
- package/src/compat/rules/README.md +33 -32
- package/src/compat/rules/providers/openai.kdl +58 -0
- package/src/compat/rules/providers/openrouter.kdl +108 -0
- package/src/compat/rules.json +12526 -1
- package/src/compat/types.ts +2 -2
- package/src/discovery/devin.ts +3 -1
- package/src/models.json +1 -1
- package/src/provider-models/openai-compat.ts +231 -119
- package/src/types.ts +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.2.8] - 2026-09-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Expanded OpenRouter provider support with embedding, reranking, video generation, text-to-speech, and speech-to-text capabilities, including five new speech-to-text models.
|
|
10
|
+
- Added speech-to-text support to the OpenAI provider.
|
|
11
|
+
|
|
5
12
|
## [18.2.7] - 2026-09-21
|
|
6
13
|
|
|
7
14
|
### Added
|
|
@@ -181,9 +188,9 @@
|
|
|
181
188
|
### Fixed
|
|
182
189
|
|
|
183
190
|
- Fixed OpenCode Go/Zen live model discovery (`GET /v1/models`) missing `x-opencode-session` and omp's `User-Agent`: discovery requests now attribute with the stable install id so the requests OpenCode flags as `Bun fetch` carry the required session header.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
191
|
+
- Fixed GPT-6 Astra requests through GitHub Copilot failing with an unsupported endpoint error ([#10874](https://github.com/can1357/oh-my-pi/pull/10874) by [@xpcmdshell](https://github.com/xpcmdshell)).
|
|
192
|
+
- Fixed GPT-6 Astra showing as free with a 272K-token window in the OpenAI Codex catalog by applying its documented pricing; `/extended-context` enables the wire-advertised 872K-token maximum ([#10980](https://github.com/can1357/oh-my-pi/pull/10980) by [@H4vC](https://github.com/H4vC)).
|
|
193
|
+
- Made extended-context catalog rebuilds faster by resolving each model's maximum window once per process ([#11039](https://github.com/can1357/oh-my-pi/pull/11039) by [@H4vC](https://github.com/H4vC)).
|
|
187
194
|
|
|
188
195
|
## [18.1.9] - 2026-09-04
|
|
189
196
|
|
package/README.md
CHANGED
|
@@ -4,18 +4,18 @@ Model catalog for [oh-my-pi](https://github.com/can1357/oh-my-pi): bundled model
|
|
|
4
4
|
|
|
5
5
|
## What's inside
|
|
6
6
|
|
|
7
|
-
| Module | Purpose
|
|
8
|
-
| ------------------------------- |
|
|
9
|
-
| `models.json` + `models` | Bundled model database (pricing, context windows, modalities, thinking support)
|
|
10
|
-
| `provider-models` | Provider catalog descriptors (`CATALOG_PROVIDERS`), per-provider model resolution rules
|
|
11
|
-
| `discovery` | Runtime model discovery for OpenAI-compatible endpoints, Gemini, Codex, Cursor, Antigravity, Ollama
|
|
12
|
-
| `compat/rules` | Checked-in KDL policy tree: taxonomy (classes/families/revisions), class/provider cascade rules, runtime behavior vocabulary; compiled by `bun run gen:compat` into the committed `rules.json`
|
|
7
|
+
| Module | Purpose |
|
|
8
|
+
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `models.json` + `models` | Bundled model database (pricing, context windows, modalities, thinking support) |
|
|
10
|
+
| `provider-models` | Provider catalog descriptors (`CATALOG_PROVIDERS`), per-provider model resolution rules |
|
|
11
|
+
| `discovery` | Runtime model discovery for OpenAI-compatible endpoints, Gemini, Codex, Cursor, Antigravity, Ollama |
|
|
12
|
+
| `compat/rules` | Checked-in KDL policy tree: taxonomy (classes/families/revisions), class/provider cascade rules, runtime behavior vocabulary; compiled by `bun run gen:compat` into the committed `rules.json` |
|
|
13
13
|
| `compat` | The rule engine: `classifyModel` (taxonomy), `resolveModelPolicy` (cascade), behavior accessors (`api-routes`, `model-limits`, `exclude-models`, `pricing-peer`), collapse, and OpenAI/Anthropic wire builders that consume resolved records |
|
|
14
|
-
| `identity` | Mechanical id utilities: reference resolution against the bundled index, dialects, selection priority, tokenizer families
|
|
15
|
-
| `model-thinking` | Runtime thinking helpers (`getSupportedEfforts`, effort clamping/mapping, wire-id routing) over resolved model records
|
|
16
|
-
| `model-manager` / `model-cache` | Runtime model registry with discovery refresh and on-disk caching
|
|
17
|
-
| `wire` | Wire-level helpers: Codex, Gemini headers, GitHub Copilot
|
|
18
|
-
| `effort` | Reasoning-effort level definitions
|
|
14
|
+
| `identity` | Mechanical id utilities: reference resolution against the bundled index, dialects, selection priority, tokenizer families |
|
|
15
|
+
| `model-thinking` | Runtime thinking helpers (`getSupportedEfforts`, effort clamping/mapping, wire-id routing) over resolved model records |
|
|
16
|
+
| `model-manager` / `model-cache` | Runtime model registry with discovery refresh and on-disk caching |
|
|
17
|
+
| `wire` | Wire-level helpers: Codex, Gemini headers, GitHub Copilot |
|
|
18
|
+
| `effort` | Reasoning-effort level definitions |
|
|
19
19
|
|
|
20
20
|
Import from subpaths (`@oh-my-pi/pi-catalog/<module>`) or the root barrel.
|
|
21
21
|
|
|
@@ -42,13 +42,13 @@ Ships TypeScript source directly (no build step); requires Bun ≥ 1.3.14.
|
|
|
42
42
|
|
|
43
43
|
The `models` subpath (also exported from the root) provides timestamp-aware pricing helpers:
|
|
44
44
|
|
|
45
|
-
| API
|
|
46
|
-
|
|
|
47
|
-
| `calculateCost(model, usage, timestamp?)`
|
|
48
|
-
| `calculateUsageCost(cost, usage, timestamp?)`
|
|
49
|
-
| `calculateUncachedInputCost(cost, promptInputTokens, timestamp?)` | Returns the cost of a fully uncached prompt.
|
|
50
|
-
| `getTimeBasedPricingPeriod(cost, timestamp?)`
|
|
51
|
-
| `getNextTimeBasedPricingTransition(cost, timestamp?)`
|
|
45
|
+
| API | Result |
|
|
46
|
+
| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `calculateCost(model, usage, timestamp?)` | Updates and returns `usage.cost` using `model.cost`. |
|
|
48
|
+
| `calculateUsageCost(cost, usage, timestamp?)` | Updates and returns `usage.cost` using a `ModelCost`. |
|
|
49
|
+
| `calculateUncachedInputCost(cost, promptInputTokens, timestamp?)` | Returns the cost of a fully uncached prompt. |
|
|
50
|
+
| `getTimeBasedPricingPeriod(cost, timestamp?)` | Returns `"peak"`, `"off-peak"`, or `undefined` without a schedule. |
|
|
51
|
+
| `getNextTimeBasedPricingTransition(cost, timestamp?)` | Returns the next actual peak/off-peak change strictly after the timestamp, or `undefined` if none exists. |
|
|
52
52
|
|
|
53
53
|
Timestamps are Unix milliseconds; omitted timestamps use the current time for scheduled pricing. Flat token prices are unaffected. Pricing selects the latest applicable effective rate card, then its long-context tier, then the peak/off-peak multiplier. A transition query concerns the recurring tariff, not dated rate-card changes.
|
|
54
54
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `behavior.ts`, `resolve.ts`) exposes to consumers.
|
|
6
6
|
*/
|
|
7
7
|
import type { Effort } from "../effort.js";
|
|
8
|
-
import type { Api, ThinkingControlMode, TokenCost } from "../types.js";
|
|
8
|
+
import type { Api, KindApiKind, ThinkingControlMode, TokenCost } from "../types.js";
|
|
9
9
|
import type { RevisionOp } from "./revision.js";
|
|
10
10
|
/** Class-membership matcher kinds, most to least specific. */
|
|
11
11
|
export type MatcherKind = "exact" | "bounded" | "namespace" | "prefix" | "glob";
|
|
@@ -620,7 +620,7 @@ export interface CompiledProvider {
|
|
|
620
620
|
/** Present only for providers enrolled in `generate-models.ts` discovery. */
|
|
621
621
|
discovery?: CompiledProviderDiscovery;
|
|
622
622
|
/** Non-chat model kinds mapped to their runtime transport APIs. */
|
|
623
|
-
kindApis?: Partial<Record<
|
|
623
|
+
kindApis?: Partial<Record<KindApiKind, Api>>;
|
|
624
624
|
/** Authored bundled rows, when the provider cannot be discovered at generation time. */
|
|
625
625
|
seed?: CompiledSeed;
|
|
626
626
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -5,13 +5,16 @@ export type { KnownProvider } from "./provider-models/descriptors.js";
|
|
|
5
5
|
export type KnownApi = "openai-completions" | "openai-responses" | "openrouter" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent" | "gitlab-duo-agent" | "devin-agent";
|
|
6
6
|
export type Api = KnownApi | (string & {});
|
|
7
7
|
/** Catalog kinds used to isolate role-specific runners from session chat models. */
|
|
8
|
-
export declare const MODEL_KINDS: readonly ["chat", "tiny", "image", "tts", "stt", "search", "judge"];
|
|
8
|
+
export declare const MODEL_KINDS: readonly ["chat", "tiny", "image", "tts", "stt", "search", "judge", "embedding", "rerank", "video"];
|
|
9
9
|
/** Technical capability of a catalog model; absent model kinds mean chat. */
|
|
10
10
|
export type ModelKind = (typeof MODEL_KINDS)[number];
|
|
11
|
+
/** Kinds a provider maps to a runner transport through `kind-apis` in its KDL; discovery drops rows of these kinds when the provider declares no API. */
|
|
12
|
+
export declare const KIND_API_KINDS: readonly ["image", "tts", "stt", "embedding", "rerank", "video"];
|
|
13
|
+
export type KindApiKind = (typeof KIND_API_KINDS)[number];
|
|
11
14
|
/** Grounding transport available to chat models selected by the web role. */
|
|
12
15
|
export type WebSearchGrounding = "gemini" | "anthropic" | "codex" | "xai" | "openrouter";
|
|
13
16
|
/** Non-chat runner protocols accepted by catalog seeds, outside the chat dispatch union. */
|
|
14
|
-
export declare const RUNNER_APIS: readonly ["local-inference", "web-search", "typesafe", "openrouter-decisions", "openai-images", "openrouter-images", "xai-tts", "openai-speech"];
|
|
17
|
+
export declare const RUNNER_APIS: readonly ["local-inference", "web-search", "typesafe", "openrouter-decisions", "openai-images", "openrouter-images", "xai-tts", "openai-speech", "openai-embeddings", "openrouter-rerank", "openrouter-video", "openai-transcriptions"];
|
|
15
18
|
/** Resolve a model's kind while preserving chat semantics for existing catalog rows. */
|
|
16
19
|
export declare function modelKind(model: Pick<Model, "kind">): ModelKind;
|
|
17
20
|
/** Canonical thinking transport used by a model. */
|
package/package.json
CHANGED
|
@@ -1,51 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"type": "module",
|
|
3
2
|
"name": "@oh-my-pi/pi-catalog",
|
|
4
|
-
"version": "18.2.
|
|
3
|
+
"version": "18.2.8",
|
|
5
4
|
"description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"catalog",
|
|
8
|
+
"discovery",
|
|
9
|
+
"llm",
|
|
10
|
+
"models"
|
|
11
|
+
],
|
|
6
12
|
"homepage": "https://omp.sh",
|
|
7
|
-
"
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/can1357/oh-my-pi/issues"
|
|
15
|
+
},
|
|
8
16
|
"license": "MIT",
|
|
17
|
+
"author": "Stencil Labs, Inc.",
|
|
9
18
|
"repository": {
|
|
10
19
|
"type": "git",
|
|
11
20
|
"url": "git+https://github.com/can1357/oh-my-pi.git",
|
|
12
21
|
"directory": "packages/catalog"
|
|
13
22
|
},
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/can1357/oh-my-pi/issues"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"ai",
|
|
19
|
-
"llm",
|
|
20
|
-
"models",
|
|
21
|
-
"catalog",
|
|
22
|
-
"discovery"
|
|
23
|
-
],
|
|
24
|
-
"main": "./src/index.ts",
|
|
25
|
-
"types": "./dist/types/index.d.ts",
|
|
26
|
-
"scripts": {
|
|
27
|
-
"check": "oxlint . && oxfmt --check --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts' && bun run check:types",
|
|
28
|
-
"check:types": "tsgo -p tsconfig.json --noEmit",
|
|
29
|
-
"lint": "oxlint .",
|
|
30
|
-
"test": "bun test --parallel",
|
|
31
|
-
"fix": "oxlint --fix --fix-suggestions . && bun run fmt",
|
|
32
|
-
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'",
|
|
33
|
-
"gen:models": "bun scripts/generate-models.ts",
|
|
34
|
-
"gen:compat": "bun scripts/compile-compat.ts",
|
|
35
|
-
"gen:proto": "bun scripts/generate-protocols.ts"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@oh-my-pi/omptype": "18.2.7",
|
|
39
|
-
"@oh-my-pi/pi-utils": "18.2.7"
|
|
40
|
-
},
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"@bgotink/kdl": "0.4.0",
|
|
43
|
-
"@oh-my-pi/pi-ai": "18.2.7",
|
|
44
|
-
"@types/bun": "^1.3.14"
|
|
45
|
-
},
|
|
46
|
-
"engines": {
|
|
47
|
-
"bun": ">=1.3.14"
|
|
48
|
-
},
|
|
49
23
|
"files": [
|
|
50
24
|
"src",
|
|
51
25
|
"README.md",
|
|
@@ -54,6 +28,9 @@
|
|
|
54
28
|
"THIRD-PARTY-NOTICES.txt",
|
|
55
29
|
"dist/types"
|
|
56
30
|
],
|
|
31
|
+
"type": "module",
|
|
32
|
+
"main": "./src/index.ts",
|
|
33
|
+
"types": "./dist/types/index.d.ts",
|
|
57
34
|
"exports": {
|
|
58
35
|
".": {
|
|
59
36
|
"types": "./dist/types/index.d.ts",
|
|
@@ -100,5 +77,28 @@
|
|
|
100
77
|
"import": "./src/*.ts"
|
|
101
78
|
},
|
|
102
79
|
"./*.js": "./src/*.ts"
|
|
80
|
+
},
|
|
81
|
+
"scripts": {
|
|
82
|
+
"check": "oxlint . && oxfmt --check --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts' && bun run check:types",
|
|
83
|
+
"check:types": "tsgo -p tsconfig.json --noEmit",
|
|
84
|
+
"lint": "oxlint .",
|
|
85
|
+
"test": "bun test --parallel",
|
|
86
|
+
"fix": "oxlint --fix --fix-suggestions . && bun run fmt",
|
|
87
|
+
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'",
|
|
88
|
+
"gen:models": "bun scripts/generate-models.ts",
|
|
89
|
+
"gen:compat": "bun scripts/compile-compat.ts",
|
|
90
|
+
"gen:proto": "bun scripts/generate-protocols.ts"
|
|
91
|
+
},
|
|
92
|
+
"dependencies": {
|
|
93
|
+
"@oh-my-pi/omptype": "18.2.8",
|
|
94
|
+
"@oh-my-pi/pi-utils": "18.2.8"
|
|
95
|
+
},
|
|
96
|
+
"devDependencies": {
|
|
97
|
+
"@bgotink/kdl": "0.4.0",
|
|
98
|
+
"@oh-my-pi/pi-ai": "18.2.8",
|
|
99
|
+
"@types/bun": "^1.3.14"
|
|
100
|
+
},
|
|
101
|
+
"engines": {
|
|
102
|
+
"bun": ">=1.3.14"
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -50,14 +50,14 @@ class "anthropic" {
|
|
|
50
50
|
|
|
51
51
|
Classification trims and lowercases the full model identifier. The **bare name** is the segment after its final `/`. Matcher tokens are also lowercased while parsing.
|
|
52
52
|
|
|
53
|
-
| Node
|
|
54
|
-
|
|
|
55
|
-
| `exact "token"`
|
|
56
|
-
| `bounded "token"`
|
|
57
|
-
| `namespace "token"`
|
|
58
|
-
| `namespace "token" bounded=#true` |
|
|
59
|
-
| `prefix "token"`
|
|
60
|
-
| `glob "pattern"`
|
|
53
|
+
| Node | Rank | Match |
|
|
54
|
+
| --------------------------------- | ---: | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
55
|
+
| `exact "token"` | 4 | The whole bare name equals `token`. |
|
|
56
|
+
| `bounded "token"` | 3 | The bare name equals `token`, or starts with it followed by `-`, `_`, `.`, `:`, or an ASCII digit. |
|
|
57
|
+
| `namespace "token"` | 2 | A non-empty `/`-separated segment of the full identifier equals `token`. |
|
|
58
|
+
| `namespace "token" bounded=#true` | 2 | Split the full identifier on `/`, `.`, and `:`; a segment must satisfy the bounded rule above. This is the only matcher property. |
|
|
59
|
+
| `prefix "token"` | 1 | The bare name starts with `token`. |
|
|
60
|
+
| `glob "pattern"` | 0 | An anchored `*` wildcard match over the bare name. `*` spans any substring; all non-wildcard text remains anchored in order. |
|
|
61
61
|
|
|
62
62
|
A class match is ranked by `(matcher-kind rank, token byte length)`. The greatest tuple wins. Equal tuples from different classes are an ambiguity error; source order is not a tiebreak. If nothing matches, classification returns class `unknown` with no family or revision.
|
|
63
63
|
|
|
@@ -93,16 +93,16 @@ revision skip-bare "o1" "o3" "o4"
|
|
|
93
93
|
|
|
94
94
|
Optional properties are:
|
|
95
95
|
|
|
96
|
-
| Property
|
|
97
|
-
|
|
|
98
|
-
| `provider`
|
|
99
|
-
| `logical`
|
|
100
|
-
| `class`
|
|
101
|
-
| `family`
|
|
102
|
-
| `revision`
|
|
103
|
-
| `effort`
|
|
104
|
-
| `thinking-variant` | Boolean marker for a separately exposed thinking sibling.
|
|
105
|
-
| `expires-at-ms`
|
|
96
|
+
| Property | Shape and meaning |
|
|
97
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `provider` | Exact provider key, compared case-insensitively. A matching provider-specific override wins over a provider-agnostic one. |
|
|
99
|
+
| `logical` | Corrected logical model identifier. |
|
|
100
|
+
| `class` | Corrected class ID; a non-empty string. |
|
|
101
|
+
| `family` | Corrected product-family ID; a non-empty string. |
|
|
102
|
+
| `revision` | One to three unsigned 8-bit components separated by `.` or `-`. |
|
|
103
|
+
| `effort` | `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max`. |
|
|
104
|
+
| `thinking-variant` | Boolean marker for a separately exposed thinking sibling. |
|
|
105
|
+
| `expires-at-ms` | Non-negative Unix time in milliseconds. The override is inactive when the observation time is at or after this value. |
|
|
106
106
|
|
|
107
107
|
The tuple `(provider, selector-kind, selector)` must also be unique, including provider-agnostic selectors. Active exact overrides take precedence over every glob. Within each selector kind, provider-scoped overrides precede provider-agnostic ones; matching globs rank by non-wildcard byte count. Equal-ranked globs are an ambiguity error, never resolved by declaration order. When no observation time is supplied, an expiring override remains active.
|
|
108
108
|
|
|
@@ -124,6 +124,7 @@ collapse {
|
|
|
124
124
|
provider-alias "devin" "opus" "claude-opus-5"
|
|
125
125
|
}
|
|
126
126
|
```
|
|
127
|
+
|
|
127
128
|
`variant-family` declares one reviewed provider-scoped collapsed family: positional provider and logical id, `name=` display name, and a body of `members "a" "b" …` (wire ids in priority order), `route "<tier>" "<wire-id>"` per effort tier (`off` included), and optional `mode`, `efforts`, `default-level`, `default-member`, `retired-members`, `effort-budget "<tier>" <n>`, `requires-effort`, `suppress-when-off`, `no-thinking`, `preserve-absent-effort-routes`, and `extra-aliases`. A `{rev}` placeholder in the logical id makes the node a **template**: it is instantiated once per revision found in live ids (`gemini-{rev}-flash` matches `gemini-3.8-flash-low` → family `gemini-3.8-flash`), every wire id in the body and the `name=` carry the same placeholder, and an optional `revision=` constraint (`">=3.6"`) bounds the generations it applies to. A concrete family with the same instantiated id wins over the template. `provider-alias` maps one provider-scoped selector spelling onto a logical id without making it a family member.
|
|
128
129
|
|
|
129
130
|
`thinking-suffix` accepts one non-empty suffix and no properties. `pair-token` declares bounded (possibly infix) tokens naming the thinking sibling of a live bare twin (`sonar-reasoning-pro` beside `sonar-pro`); it drives thinking-pair derivation only — never identity suffix collapse — and negated `no-`/`non-` forms never match. `effort-suffix` additionally requires `tier` with one of the effort values above, and may have `except-bare-prefix`. `routing-variant-suffix` takes one non-empty suffix followed by one or more provider IDs: a wire identifier carrying the suffix on one of those providers is a **routing variant** of its plain identifier — discovery derives base-model metadata from the plain bundled SKU while keeping the suffixed wire identifier for requests; routing variants never participate in effort collapse. `effort-lane-suffix` takes one non-empty lane suffix followed by one or more provider IDs, plus an optional `bare-prefix` gate: on a declared provider, an identifier ending in the lane suffix collapses the effort suffix wedged before the lane token while keeping the lane on the logical id. `effort-family` takes a provider, the canonical logical id, and zero or more exact aliases that fold onto it.
|
|
@@ -178,15 +179,15 @@ provider "openrouter" {
|
|
|
178
179
|
|
|
179
180
|
### Selectors and nesting
|
|
180
181
|
|
|
181
|
-
| Selector
|
|
182
|
-
|
|
|
183
|
-
| `class`
|
|
184
|
-
| `provider` | `provider "id" { ... }`
|
|
185
|
-
| `on`
|
|
186
|
-
| `on-api`
|
|
187
|
-
| `family`
|
|
188
|
-
| `revision` | `revision ">=2.5 <4" { ... }`
|
|
189
|
-
| `models`
|
|
182
|
+
| Selector | Form | Matching semantics |
|
|
183
|
+
| ---------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
184
|
+
| `class` | `class "id" { ... }` | Exact class ID. At document root it may contain `on`, `on-api`, `family`, `revision`, and `models`. Under `provider` it may contain `family`, `revision`, and `models`. |
|
|
185
|
+
| `provider` | `provider "id" { ... }` | Exact provider ID. It is root-only and may contain `class` and `models`. |
|
|
186
|
+
| `on` | `on "provider-a" "provider-b" { ... }` | One or more provider IDs, combined as OR. It is allowed only under a root `class`, and may contain `family`, `revision`, and `models`. |
|
|
187
|
+
| `on-api` | `on-api "adapter-a" "adapter-b" { ... }` | One or more request adapter IDs, combined as OR. It is allowed only under a root `class`, and may contain `family`, `revision`, and `models`. |
|
|
188
|
+
| `family` | `family "id" { ... }` | Exact classified family ID. It may contain `revision` and `models`. A target with no family does not match. |
|
|
189
|
+
| `revision` | `revision ">=2.5 <4" { ... }` | A non-empty, whitespace-separated conjunction of comparisons. It may contain `models`. A target with no revision does not match. |
|
|
190
|
+
| `models` | `models "id" "vendor/*" { ... }` | One or more alternatives, combined as OR. It cannot contain another selector. `token="name"` matches an ASCII-case-insensitive token bounded by non-alphanumerics. |
|
|
190
191
|
|
|
191
192
|
Class, provider/`on`, `on-api`, and family selector values are compared exactly and case-sensitively to the structured resolve target. Revision operators are `>=`, `>`, `<=`, `<`, and `=`; operands have one to three dot-separated unsigned 8-bit components, omitted components zero.
|
|
192
193
|
|
|
@@ -401,17 +402,17 @@ Only `discovery` enrolls a provider in `generate-models.ts`; providers without i
|
|
|
401
402
|
|
|
402
403
|
### Seed rows
|
|
403
404
|
|
|
404
|
-
A `seed`
|
|
405
|
+
A `seed` _defines_ bundled rows for providers whose catalog cannot be discovered at generation time — credential-scoped rosters, unauthenticated regens, or models ahead of upstream catalogs. Every other stratum patches rows; this one authors them. Runtime model managers hand the rows to `staticModels` through `seedModels(provider)`; the generator bundles them per the seed's `bundle` policy. Values are literal — a seed never derives from another provider's row, and pricing is never borrowed.
|
|
405
406
|
|
|
406
407
|
`seed` properties: `api` and `base-url` are per-row defaults (a `model` may override either with the same property names); `bundle` defaults to `always`; `precedence="seed"` is optional. `model` takes the wire id positionally, requires `name=`, and its body MUST declare `reasoning`, `input` (`"text"` and/or `"image"`), `cost` (all four per-million rates), and `limits` (`context=` / `max-tokens=`, an omitted limit is `null`); `supports-tools #true` is optional. Any other directive is an axis from the cascade vocabulary: thinking axes become the row's explicit `thinking` (then `thinking-mode` and `thinking-efforts` are both required), wire axes become its explicit `compat` and must apply to the row's API, and catalog axes are rejected because they stay rule-owned in the cascade block. Explicit `thinking`/`compat` on a seed row win over the cascade exactly as they do for any authored spec.
|
|
407
408
|
|
|
408
409
|
`bundle` decides when the generator includes the rows:
|
|
409
410
|
|
|
410
|
-
| Policy
|
|
411
|
-
|
|
|
412
|
-
| `always`
|
|
411
|
+
| Policy | Rows enter the bundle |
|
|
412
|
+
| ---------- | ------------------------------------------------------------------------- |
|
|
413
|
+
| `always` | Every regeneration. Same-id upstream/discovery rows win dedup. |
|
|
413
414
|
| `fallback` | Only when the provider's authoritative catalog discovery did not succeed. |
|
|
414
|
-
| `empty`
|
|
415
|
+
| `empty` | Only when no other source produced a row for the provider. |
|
|
415
416
|
|
|
416
417
|
`precedence="seed"` prepends the rows after the previous-snapshot merge and cross-provider reference fills, so the authored row wins dedup and same-id rows on other hosts never overwrite its name or capabilities (QwenCloud Token Plan, Meta). The default `upstream` precedence appends before the snapshot merge, so the current seed — not a stale snapshot copy — is the fallback row.
|
|
417
418
|
|
|
@@ -4,7 +4,9 @@ provider "openai" {
|
|
|
4
4
|
default-model "gpt-5.5"
|
|
5
5
|
env "OPENAI_API_KEY"
|
|
6
6
|
kind-apis {
|
|
7
|
+
embedding "openai-embeddings"
|
|
7
8
|
image "openai-responses"
|
|
9
|
+
stt "openai-transcriptions"
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
// Daybreak models are approval-gated first-party Responses models that are
|
|
@@ -33,6 +35,62 @@ provider "openai" {
|
|
|
33
35
|
cost input=12.5 output=75 cache-read=1.25 cache-write=15.625
|
|
34
36
|
limits context=400000 max-tokens=128000
|
|
35
37
|
}
|
|
38
|
+
|
|
39
|
+
// Catalog cost fields are per 1M tokens: GPT transcribers map documented
|
|
40
|
+
// audio-input/output-token rates directly. Whisper's $0.006/min duration
|
|
41
|
+
// tariff has no token-cost representation, so it remains zero and the
|
|
42
|
+
// transcription response's provider-reported usage/cost is authoritative.
|
|
43
|
+
model "whisper-1" name="Whisper 1" api="openai-transcriptions" base-url="https://api.openai.com/v1" {
|
|
44
|
+
reasoning #false
|
|
45
|
+
input "text"
|
|
46
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
47
|
+
limits
|
|
48
|
+
supports-tools #false
|
|
49
|
+
}
|
|
50
|
+
model "gpt-4o-transcribe" name="GPT-4o Transcribe" api="openai-transcriptions" base-url="https://api.openai.com/v1" {
|
|
51
|
+
reasoning #false
|
|
52
|
+
input "text"
|
|
53
|
+
cost input=2.5 output=10 cache-read=0 cache-write=0
|
|
54
|
+
limits context=16000 max-tokens=2000
|
|
55
|
+
supports-tools #false
|
|
56
|
+
}
|
|
57
|
+
model "gpt-4o-mini-transcribe" name="GPT-4o Mini Transcribe" api="openai-transcriptions" base-url="https://api.openai.com/v1" {
|
|
58
|
+
reasoning #false
|
|
59
|
+
input "text"
|
|
60
|
+
cost input=1.25 output=5 cache-read=0 cache-write=0
|
|
61
|
+
limits context=16000 max-tokens=2000
|
|
62
|
+
supports-tools #false
|
|
63
|
+
}
|
|
64
|
+
// OpenAI publishes embedding prices per million input tokens; embedding
|
|
65
|
+
// responses have no output-token charge.
|
|
66
|
+
model "text-embedding-3-small" name="Text Embedding 3 Small" api="openai-embeddings" base-url="https://api.openai.com/v1" {
|
|
67
|
+
reasoning #false
|
|
68
|
+
input "text"
|
|
69
|
+
cost input=0.02 output=0 cache-read=0 cache-write=0
|
|
70
|
+
limits context=8192
|
|
71
|
+
supports-tools #false
|
|
72
|
+
}
|
|
73
|
+
model "text-embedding-3-large" name="Text Embedding 3 Large" api="openai-embeddings" base-url="https://api.openai.com/v1" {
|
|
74
|
+
reasoning #false
|
|
75
|
+
input "text"
|
|
76
|
+
cost input=0.13 output=0 cache-read=0 cache-write=0
|
|
77
|
+
limits context=8192
|
|
78
|
+
supports-tools #false
|
|
79
|
+
}
|
|
80
|
+
model "text-embedding-ada-002" name="Text Embedding Ada 002" api="openai-embeddings" base-url="https://api.openai.com/v1" {
|
|
81
|
+
reasoning #false
|
|
82
|
+
input "text"
|
|
83
|
+
cost input=0.1 output=0 cache-read=0 cache-write=0
|
|
84
|
+
limits context=8192
|
|
85
|
+
supports-tools #false
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
models "whisper-1" "gpt-4o-transcribe" "gpt-4o-mini-transcribe" {
|
|
90
|
+
kind "stt"
|
|
91
|
+
}
|
|
92
|
+
models "text-embedding-3-small" "text-embedding-3-large" "text-embedding-ada-002" {
|
|
93
|
+
kind "embedding"
|
|
36
94
|
}
|
|
37
95
|
|
|
38
96
|
// Replaces the strict-mode provider whitelist entry.
|
|
@@ -5,7 +5,12 @@ provider "openrouter" {
|
|
|
5
5
|
env "OPENROUTER_API_KEY"
|
|
6
6
|
discovery label="OpenRouter" allow-unauthenticated=#true
|
|
7
7
|
kind-apis {
|
|
8
|
+
embedding "openai-embeddings"
|
|
8
9
|
image "openrouter-images"
|
|
10
|
+
rerank "openrouter-rerank"
|
|
11
|
+
video "openrouter-video"
|
|
12
|
+
tts "openai-speech"
|
|
13
|
+
stt "openai-transcriptions"
|
|
9
14
|
}
|
|
10
15
|
web-search "openrouter"
|
|
11
16
|
|
|
@@ -19,10 +24,113 @@ provider "openrouter" {
|
|
|
19
24
|
cost input=0.042 output=0 cache-read=0 cache-write=0
|
|
20
25
|
limits context=32000 max-tokens=28800
|
|
21
26
|
}
|
|
27
|
+
|
|
28
|
+
// OpenRouter's STT roster mixes per-token and duration-based prices.
|
|
29
|
+
// Token-priced GPT rows map per-token rates to catalog per-million costs;
|
|
30
|
+
// duration-priced rows remain zero because ModelCost has no seconds axis.
|
|
31
|
+
model "openai/whisper-1" name="OpenAI: Whisper 1" api="openai-transcriptions" base-url="https://openrouter.ai/api/v1" {
|
|
32
|
+
reasoning #false
|
|
33
|
+
input "text"
|
|
34
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
35
|
+
limits
|
|
36
|
+
supports-tools #false
|
|
37
|
+
}
|
|
38
|
+
model "openai/whisper-large-v3" name="OpenAI: Whisper Large V3" api="openai-transcriptions" base-url="https://openrouter.ai/api/v1" {
|
|
39
|
+
reasoning #false
|
|
40
|
+
input "text"
|
|
41
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
42
|
+
limits
|
|
43
|
+
supports-tools #false
|
|
44
|
+
}
|
|
45
|
+
model "openai/gpt-4o-transcribe" name="OpenAI: GPT-4o Transcribe" api="openai-transcriptions" base-url="https://openrouter.ai/api/v1" {
|
|
46
|
+
reasoning #false
|
|
47
|
+
input "text"
|
|
48
|
+
cost input=2.5 output=10 cache-read=0 cache-write=0
|
|
49
|
+
limits context=128000 max-tokens=115200
|
|
50
|
+
supports-tools #false
|
|
51
|
+
}
|
|
52
|
+
model "microsoft/mai-transcribe-1.5" name="Microsoft AI: MAI-Transcribe 1.5" api="openai-transcriptions" base-url="https://openrouter.ai/api/v1" {
|
|
53
|
+
reasoning #false
|
|
54
|
+
input "text"
|
|
55
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
56
|
+
limits
|
|
57
|
+
supports-tools #false
|
|
58
|
+
}
|
|
59
|
+
model "microsoft/mai-transcribe-2" name="Microsoft AI: MAI-Transcribe 2" api="openai-transcriptions" base-url="https://openrouter.ai/api/v1" {
|
|
60
|
+
reasoning #false
|
|
61
|
+
input "text"
|
|
62
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
63
|
+
limits
|
|
64
|
+
supports-tools #false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// OpenRouter bills reranking per 1,000 searches, which has no catalog cost
|
|
68
|
+
// axis. Keep token costs at zero; the provider-reported response cost is authoritative.
|
|
69
|
+
model "cohere/rerank-v3.5" name="Cohere: Rerank v3.5" api="openrouter-rerank" base-url="https://openrouter.ai/api/v1" {
|
|
70
|
+
reasoning #false
|
|
71
|
+
input "text"
|
|
72
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
73
|
+
limits context=4096 max-tokens=3686
|
|
74
|
+
supports-tools #false
|
|
75
|
+
}
|
|
76
|
+
// Bundled fallbacks keep the gateway useful offline; live
|
|
77
|
+
// `/embeddings/models` discovery refreshes this roster and its per-token
|
|
78
|
+
// pricing. Catalog token costs are per million input tokens.
|
|
79
|
+
model "openai/text-embedding-3-small" name="OpenAI: Text Embedding 3 Small" api="openai-embeddings" base-url="https://openrouter.ai/api/v1" {
|
|
80
|
+
reasoning #false
|
|
81
|
+
input "text"
|
|
82
|
+
cost input=0.02 output=0 cache-read=0 cache-write=0
|
|
83
|
+
limits context=8192
|
|
84
|
+
supports-tools #false
|
|
85
|
+
}
|
|
86
|
+
model "qwen/qwen3-embedding-8b" name="Qwen: Qwen3 Embedding 8B" api="openai-embeddings" base-url="https://openrouter.ai/api/v1" {
|
|
87
|
+
reasoning #false
|
|
88
|
+
input "text"
|
|
89
|
+
cost input=0.01 output=0 cache-read=0 cache-write=0
|
|
90
|
+
limits context=32768
|
|
91
|
+
supports-tools #false
|
|
92
|
+
}
|
|
93
|
+
// OpenRouter bills generated video by output second and resolution/SKU,
|
|
94
|
+
// which ModelCost cannot represent. Keep token costs at zero; poll-reported
|
|
95
|
+
// cost is authoritative. Live `/videos/models` discovery refreshes the roster.
|
|
96
|
+
model "google/veo-3.1" name="Google: Veo 3.1" api="openrouter-video" base-url="https://openrouter.ai/api/v1" {
|
|
97
|
+
reasoning #false
|
|
98
|
+
input "text" "image"
|
|
99
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
100
|
+
limits
|
|
101
|
+
supports-tools #false
|
|
102
|
+
}
|
|
103
|
+
model "minimax/hailuo-3" name="MiniMax: H3" api="openrouter-video" base-url="https://openrouter.ai/api/v1" {
|
|
104
|
+
reasoning #false
|
|
105
|
+
input "text" "image"
|
|
106
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
107
|
+
limits
|
|
108
|
+
supports-tools #false
|
|
109
|
+
}
|
|
110
|
+
model "alibaba/wan-2.7" name="Alibaba: Wan 2.7" api="openrouter-video" base-url="https://openrouter.ai/api/v1" {
|
|
111
|
+
reasoning #false
|
|
112
|
+
input "text" "image"
|
|
113
|
+
cost input=0 output=0 cache-read=0 cache-write=0
|
|
114
|
+
limits
|
|
115
|
+
supports-tools #false
|
|
116
|
+
}
|
|
22
117
|
}
|
|
23
118
|
models "~typesafe/*" "typesafe/*" {
|
|
24
119
|
kind "judge"
|
|
25
120
|
}
|
|
121
|
+
models "cohere/rerank-v3.5" {
|
|
122
|
+
kind "rerank"
|
|
123
|
+
}
|
|
124
|
+
models "openai/text-embedding-3-small" "qwen/qwen3-embedding-8b" {
|
|
125
|
+
kind "embedding"
|
|
126
|
+
}
|
|
127
|
+
models "google/veo-3.1" "minimax/hailuo-3" "alibaba/wan-2.7" {
|
|
128
|
+
kind "video"
|
|
129
|
+
}
|
|
130
|
+
models "openai/whisper-1" "openai/whisper-large-v3" "openai/gpt-4o-transcribe" \
|
|
131
|
+
"microsoft/mai-transcribe-1.5" "microsoft/mai-transcribe-2" {
|
|
132
|
+
kind "stt"
|
|
133
|
+
}
|
|
26
134
|
|
|
27
135
|
// Replaces the OpenRouter provider wire-model-id dispatch branch.
|
|
28
136
|
wire-model-id-mode "openrouter"
|