@oh-my-pi/pi-catalog 18.8.4 → 18.8.5
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 +11 -0
- package/dist/types/discovery/antigravity.d.ts +13 -3
- package/dist/types/provider-models/account-access.d.ts +11 -0
- package/dist/types/provider-models/google.d.ts +23 -1
- package/dist/types/types.d.ts +5 -5
- package/package.json +4 -4
- package/src/build.ts +35 -34
- package/src/compat/rules/README.md +1 -1
- package/src/compat/rules/classes/anthropic.kdl +2 -1
- package/src/compat/rules/providers/cursor.kdl +18 -0
- package/src/compat/rules/providers/github-copilot.kdl +25 -0
- package/src/compat/rules.json +1 -1
- package/src/discovery/antigravity.ts +33 -17
- package/src/provider-models/account-access.ts +30 -0
- package/src/provider-models/google.ts +70 -14
- package/src/provider-models/special.ts +6 -18
- package/src/types.ts +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.8.5] - 2026-10-08
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- `googleAntigravityModelManagerOptions` takes `resolveAccounts` instead of `oauthToken`, and `fetchAntigravityDiscoveryModels` returns a roster or credential-rejection result instead of a bare list ([#14924](https://github.com/can1357/oh-my-pi/issues/14924)).
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed Claude Haiku 5.5 on Cursor showing as unpriced; it now uses Cursor's $0.10/$0.50 rate card and 5x long-context tier above 100K input tokens ([#14890](https://github.com/can1357/oh-my-pi/pull/14890) by [@eggpeat](https://github.com/eggpeat)).
|
|
14
|
+
- Fixed Claude Haiku 5.5 on GitHub Copilot pricing cache reads and writes at $0 on both the standard and `-1m` long-context rows, and the `-1m` row billing the 5x long-context band a second time above 100K input tokens ([#14890](https://github.com/can1357/oh-my-pi/pull/14890) by [@eggpeat](https://github.com/eggpeat)).
|
|
15
|
+
|
|
5
16
|
## [18.8.4] - 2026-10-08
|
|
6
17
|
|
|
7
18
|
### Fixed
|
|
@@ -63,13 +63,23 @@ export interface FetchAntigravityDiscoveryModelsOptions {
|
|
|
63
63
|
*/
|
|
64
64
|
collapseTable?: VariantCollapseTable;
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* A complete account roster, or a definitive 401/403 credential rejection.
|
|
68
|
+
* `null` from {@link fetchAntigravityDiscoveryModels} instead means a transient
|
|
69
|
+
* failure or invalid response, which must not replace an authoritative catalog.
|
|
70
|
+
*/
|
|
71
|
+
export interface AntigravityModelDiscoveryResult {
|
|
72
|
+
models: ModelSpec<"google-gemini-cli">[];
|
|
73
|
+
rejectedStatus?: 401 | 403;
|
|
74
|
+
}
|
|
66
75
|
/**
|
|
67
76
|
* Fetches discoverable Antigravity models and normalizes them into canonical model entries.
|
|
68
77
|
*
|
|
69
|
-
* Returns `null` on network
|
|
70
|
-
*
|
|
78
|
+
* Returns `null` on network, server, or payload failures; a 401/403 is reported
|
|
79
|
+
* separately so multi-account discovery can skip a rejected credential.
|
|
80
|
+
* A successful empty roster has `models: []` without `rejectedStatus`.
|
|
71
81
|
*/
|
|
72
|
-
export declare function fetchAntigravityDiscoveryModels(options: FetchAntigravityDiscoveryModelsOptions): Promise<
|
|
82
|
+
export declare function fetchAntigravityDiscoveryModels(options: FetchAntigravityDiscoveryModelsOptions): Promise<AntigravityModelDiscoveryResult | null>;
|
|
73
83
|
/** Advertised image model and serving endpoint for one Antigravity account. */
|
|
74
84
|
export interface AntigravityImageModel {
|
|
75
85
|
id: string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Api, ModelSpec } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Merge per-account discovery catalogs into one list, deduped by model id.
|
|
4
|
+
*
|
|
5
|
+
* The first catalog to list an id supplies its spec; {@link ModelSpec.accountAccess}
|
|
6
|
+
* is merged from every catalog listing that id, so credential selection can
|
|
7
|
+
* route account-gated models to the accounts that serve them. Used by
|
|
8
|
+
* multi-account discovery for Codex and Antigravity, whose rosters differ per
|
|
9
|
+
* account.
|
|
10
|
+
*/
|
|
11
|
+
export declare function unionAccountCatalogs<TApi extends Api>(catalogs: readonly (readonly ModelSpec<TApi>[])[]): ModelSpec<TApi>[];
|
|
@@ -11,8 +11,30 @@ export interface GoogleVertexModelManagerConfig {
|
|
|
11
11
|
signal?: AbortSignal;
|
|
12
12
|
fetch?: FetchImpl;
|
|
13
13
|
}
|
|
14
|
+
/** One Antigravity OAuth account whose `fetchAvailableModels` roster discovery reads. */
|
|
15
|
+
export interface GoogleAntigravityAccount {
|
|
16
|
+
/** OAuth access token used for `Authorization: Bearer ...`. */
|
|
17
|
+
accessToken: string;
|
|
18
|
+
/**
|
|
19
|
+
* Credential identity recorded in {@link ModelSpec.accountAccess} for every
|
|
20
|
+
* model this account serves (see `oauthAccountKey` in `@oh-my-pi/pi-ai`).
|
|
21
|
+
* When any account lacks one, no model records per-account access.
|
|
22
|
+
*/
|
|
23
|
+
accountKey?: string;
|
|
24
|
+
}
|
|
14
25
|
export interface GoogleAntigravityModelManagerConfig {
|
|
15
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Resolves every configured Antigravity account at discovery time. Rosters
|
|
28
|
+
* are plan-scoped (Claude 5.5 is served to some accounts only) and
|
|
29
|
+
* authoritative, so each account's roster is fetched and the results are
|
|
30
|
+
* unioned; reading one account's roster would prune models only its
|
|
31
|
+
* siblings serve (#14924).
|
|
32
|
+
*
|
|
33
|
+
* Returns `null` to abort discovery (e.g. an account's credential failed to
|
|
34
|
+
* refresh), keeping the previous/bundled catalog instead of caching a
|
|
35
|
+
* partial one.
|
|
36
|
+
*/
|
|
37
|
+
resolveAccounts?: () => Promise<readonly GoogleAntigravityAccount[] | null>;
|
|
16
38
|
endpoint?: string;
|
|
17
39
|
fetch?: FetchImpl;
|
|
18
40
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1209,11 +1209,11 @@ export interface Model<TApi extends Api = Api> {
|
|
|
1209
1209
|
cursorMaxModeRoutes?: Readonly<Record<string, boolean>>;
|
|
1210
1210
|
/**
|
|
1211
1211
|
* Per-account availability recorded by multi-account discovery: provider
|
|
1212
|
-
* account
|
|
1213
|
-
* entitlements on this model. An account appears
|
|
1214
|
-
* lists the model, so credential selection can
|
|
1215
|
-
* (e.g. `gpt-daybreak-blue-latest
|
|
1216
|
-
*
|
|
1212
|
+
* account key (Codex: ChatGPT `chatgpt_account_id`; Antigravity: login
|
|
1213
|
+
* email) → that account's entitlements on this model. An account appears
|
|
1214
|
+
* only when its own catalog lists the model, so credential selection can
|
|
1215
|
+
* route account-gated models (e.g. `gpt-daybreak-blue-latest`, Antigravity
|
|
1216
|
+
* Claude 5.5) straight to eligible accounts. Absent on bundled/config rows.
|
|
1217
1217
|
*/
|
|
1218
1218
|
accountAccess?: Readonly<Record<string, ModelAccountAccess>>;
|
|
1219
1219
|
/** Cursor `RequestedModel.parameters` for this model's default variant. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-catalog",
|
|
3
|
-
"version": "18.8.
|
|
3
|
+
"version": "18.8.5",
|
|
4
4
|
"description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -93,12 +93,12 @@
|
|
|
93
93
|
"gen:proto": "bun scripts/generate-protocols.ts"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
|
-
"@oh-my-pi/omptype": "18.8.
|
|
97
|
-
"@oh-my-pi/pi-utils": "18.8.
|
|
96
|
+
"@oh-my-pi/omptype": "18.8.5",
|
|
97
|
+
"@oh-my-pi/pi-utils": "18.8.5"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@bgotink/kdl": "0.4.0",
|
|
101
|
-
"@oh-my-pi/pi-ai": "18.8.
|
|
101
|
+
"@oh-my-pi/pi-ai": "18.8.5",
|
|
102
102
|
"@types/bun": "^1.3.14"
|
|
103
103
|
},
|
|
104
104
|
"engines": {
|
package/src/build.ts
CHANGED
|
@@ -176,40 +176,6 @@ export function applyCatalogCorrections(
|
|
|
176
176
|
model: Pick<ModelSpec<Api>, "cost" | "contextWindow" | "maxTokens" | "input">,
|
|
177
177
|
catalog: Record<string, unknown>,
|
|
178
178
|
): void {
|
|
179
|
-
const longContext = objectPayload(catalog.longContext);
|
|
180
|
-
if (longContext !== undefined) {
|
|
181
|
-
const inputThreshold = numberField(longContext, "inputThreshold");
|
|
182
|
-
const inclusive = Reflect.get(longContext, "inputThresholdInclusive") === true;
|
|
183
|
-
const multiplier = numberField(longContext, "multiplier");
|
|
184
|
-
const input = numberField(longContext, "input");
|
|
185
|
-
const output = numberField(longContext, "output");
|
|
186
|
-
const cacheRead = numberField(longContext, "cacheRead");
|
|
187
|
-
const cacheWrite = numberField(longContext, "cacheWrite");
|
|
188
|
-
const base = model.cost;
|
|
189
|
-
const hasTokenPrice = base.input !== 0 || base.output !== 0 || base.cacheRead !== 0 || base.cacheWrite !== 0;
|
|
190
|
-
if (inputThreshold !== undefined && multiplier !== undefined && hasTokenPrice) {
|
|
191
|
-
// Multiplier form: tier rates derive from the row's live list price.
|
|
192
|
-
model.cost = {
|
|
193
|
-
...base,
|
|
194
|
-
longContext: {
|
|
195
|
-
inputThreshold,
|
|
196
|
-
...(inclusive && { inputThresholdInclusive: true }),
|
|
197
|
-
input: base.input * multiplier,
|
|
198
|
-
output: base.output * multiplier,
|
|
199
|
-
cacheRead: base.cacheRead * multiplier,
|
|
200
|
-
cacheWrite: base.cacheWrite * multiplier,
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
} else if (
|
|
204
|
-
inputThreshold !== undefined &&
|
|
205
|
-
input !== undefined &&
|
|
206
|
-
output !== undefined &&
|
|
207
|
-
cacheRead !== undefined &&
|
|
208
|
-
cacheWrite !== undefined
|
|
209
|
-
) {
|
|
210
|
-
model.cost = { ...model.cost, longContext: { inputThreshold, input, output, cacheRead, cacheWrite } };
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
179
|
const patch = objectPayload(catalog.costPatch);
|
|
214
180
|
if (patch !== undefined) {
|
|
215
181
|
model.cost = { ...model.cost };
|
|
@@ -246,6 +212,41 @@ export function applyCatalogCorrections(
|
|
|
246
212
|
applyEffectiveFallbackRates(model.cost, Reflect.get(fallback, "effectiveRates"));
|
|
247
213
|
}
|
|
248
214
|
}
|
|
215
|
+
const longContext = objectPayload(catalog.longContext);
|
|
216
|
+
if (longContext !== undefined) {
|
|
217
|
+
const inputThreshold = numberField(longContext, "inputThreshold");
|
|
218
|
+
const inclusive = Reflect.get(longContext, "inputThresholdInclusive") === true;
|
|
219
|
+
const multiplier = numberField(longContext, "multiplier");
|
|
220
|
+
const input = numberField(longContext, "input");
|
|
221
|
+
const output = numberField(longContext, "output");
|
|
222
|
+
const cacheRead = numberField(longContext, "cacheRead");
|
|
223
|
+
const cacheWrite = numberField(longContext, "cacheWrite");
|
|
224
|
+
const base = model.cost;
|
|
225
|
+
const hasTokenPrice = base.input !== 0 || base.output !== 0 || base.cacheRead !== 0 || base.cacheWrite !== 0;
|
|
226
|
+
if (inputThreshold !== undefined && multiplier !== undefined && hasTokenPrice) {
|
|
227
|
+
// Multiplier form: tier rates derive from the row's final base card,
|
|
228
|
+
// after `cost-patch`/`cost-fallback` corrected the live list price.
|
|
229
|
+
model.cost = {
|
|
230
|
+
...base,
|
|
231
|
+
longContext: {
|
|
232
|
+
inputThreshold,
|
|
233
|
+
...(inclusive && { inputThresholdInclusive: true }),
|
|
234
|
+
input: base.input * multiplier,
|
|
235
|
+
output: base.output * multiplier,
|
|
236
|
+
cacheRead: base.cacheRead * multiplier,
|
|
237
|
+
cacheWrite: base.cacheWrite * multiplier,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
} else if (
|
|
241
|
+
inputThreshold !== undefined &&
|
|
242
|
+
input !== undefined &&
|
|
243
|
+
output !== undefined &&
|
|
244
|
+
cacheRead !== undefined &&
|
|
245
|
+
cacheWrite !== undefined
|
|
246
|
+
) {
|
|
247
|
+
model.cost = { ...model.cost, longContext: { inputThreshold, input, output, cacheRead, cacheWrite } };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
249
250
|
if (catalog.cacheReadAtInputRate === true) {
|
|
250
251
|
const { longContext } = model.cost;
|
|
251
252
|
model.cost = {
|
|
@@ -213,7 +213,7 @@ The three value shapes are:
|
|
|
213
213
|
- **Object**: no arguments and a child block, including an empty block. Child names are kebab-case: an axis-directive spelling compiles to its resolved axis key (`template-reasoning-effort` → `qwenTemplateReasoningEffort`), anything else converts mechanically (`input-threshold` → `inputThreshold`); camelCase names are a compile error. `extra-body` payloads (top-level or nested) are the exception — their child names are literal wire JSON keys copied verbatim (`enable_thinking`). Each child is either one scalar or another object; arrays are not representable inside an object payload.
|
|
214
214
|
|
|
215
215
|
A rule cannot assign the same resolved axis twice in one block.
|
|
216
|
-
One object axis carries a computed form: `long-context-cost` accepts either the absolute rates (`input-threshold` + `input`/`output`/`cache-read`/`cache-write`) or `input-threshold` + `multiplier` (with optional `input-threshold-inclusive`), which derives the tier from the row's
|
|
216
|
+
One object axis carries a computed form: `long-context-cost` accepts either the absolute rates (`input-threshold` + `input`/`output`/`cache-read`/`cache-write`) or `input-threshold` + `multiplier` (with optional `input-threshold-inclusive`), which derives the tier from the row's base price at build time, after `cost-patch` and `cost-fallback`, so the rule tracks upstream list-price updates (xAI's SuperGrok 200K tier). Rows without a token price carry no tier. An empty `long-context-cost {}` adds no tier; a more specific rule uses it to opt a host out of a broader rule's band (GitHub Copilot's Haiku 5.5 rows, whose long tier is the `-1m` sibling).
|
|
217
217
|
|
|
218
218
|
`context-window-authoritative #true` preserves a host's supplied context window through runtime model selection instead of applying inferred expansion or reference-price-tier caps. Explicit user context overrides still apply afterward. It applies to rows materialized through `buildModel` (discovery and regenerated bundles). See [`providers/factory-droid.kdl`](providers/factory-droid.kdl).
|
|
219
219
|
|
|
@@ -102,7 +102,8 @@ class "anthropic" {
|
|
|
102
102
|
}
|
|
103
103
|
// Haiku 5.5 bills every rate 5x for prompts over 100K. Derived from each
|
|
104
104
|
// host's list price so non-Anthropic hosts get the band too; the Claude
|
|
105
|
-
// API
|
|
105
|
+
// API and Cursor pin absolute rates, and GitHub Copilot opts out because
|
|
106
|
+
// its long tier is the `-1m` sibling row.
|
|
106
107
|
// https://platform.claude.com/docs/en/models/haiku-5-5/overview#pricing
|
|
107
108
|
revision ">=5.5 <6" {
|
|
108
109
|
long-context-cost {
|
|
@@ -167,6 +167,24 @@ provider "cursor" {
|
|
|
167
167
|
cache-write 12.5
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
// Claude Haiku 5.5: $0.10/$0.50, cache $0.01/$0.125. Requests above
|
|
171
|
+
// 100k input tokens bill every leg at 5x ($0.50/$2.50, cache
|
|
172
|
+
// $0.05/$0.625), on the 1M lane too.
|
|
173
|
+
models "claude-haiku-5-5" "claude-haiku-5-5-1m" {
|
|
174
|
+
cost-patch {
|
|
175
|
+
input 0.1
|
|
176
|
+
output 0.5
|
|
177
|
+
cache-read 0.01
|
|
178
|
+
cache-write 0.125
|
|
179
|
+
}
|
|
180
|
+
long-context-cost {
|
|
181
|
+
input-threshold 100000
|
|
182
|
+
input 0.5
|
|
183
|
+
output 2.5
|
|
184
|
+
cache-read 0.05
|
|
185
|
+
cache-write 0.625
|
|
186
|
+
}
|
|
187
|
+
}
|
|
170
188
|
// Claude 4.7 Opus: $5/$25, cache $0.50/$6.25. Up to 1M same rates.
|
|
171
189
|
models "claude-opus-4-7-high" "claude-opus-4-7-low" "claude-opus-4-7-max" "claude-opus-4-7-medium" "claude-opus-4-7-xhigh" {
|
|
172
190
|
cost-patch {
|
|
@@ -76,4 +76,29 @@ provider "github-copilot" {
|
|
|
76
76
|
}
|
|
77
77
|
max-context-window 1050000
|
|
78
78
|
}
|
|
79
|
+
// Claude Haiku 5.5: `billing.token_prices` reports its input/output rates
|
|
80
|
+
// but no cache legs, so discovered rows priced cache reads and writes at
|
|
81
|
+
// $0. Copilot's rate card bills $0.01 read / $0.125 write up to 100K and
|
|
82
|
+
// $0.05 / $0.625 on the long tier (the `-1m` sibling).
|
|
83
|
+
// https://docs.github.com/en/copilot/reference/copilot-billing/models-and-pricing
|
|
84
|
+
// Copilot serves that tier as the `-1m` row (promotion target of the base
|
|
85
|
+
// row), so both rows opt out of the class-wide 100K 5x band: the base row
|
|
86
|
+
// would otherwise bill the band on top of the promotion, and the `-1m`
|
|
87
|
+
// row would charge 5x twice.
|
|
88
|
+
models "claude-haiku-5.5" {
|
|
89
|
+
cost-patch {
|
|
90
|
+
cache-read 0.01
|
|
91
|
+
cache-write 0.125
|
|
92
|
+
}
|
|
93
|
+
long-context-cost {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
models "claude-haiku-5.5-1m" {
|
|
97
|
+
cost-patch {
|
|
98
|
+
cache-read 0.05
|
|
99
|
+
cache-write 0.625
|
|
100
|
+
}
|
|
101
|
+
long-context-cost {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
79
104
|
}
|