@oh-my-pi/pi-catalog 18.3.4 → 18.4.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/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.4.0] - 2026-09-28
6
+
7
+ ### Fixed
8
+
9
+ - Corrected Cerebras model pricing so cached input tokens are charged at the model’s input rate, consistent with Cerebras billing.
10
+
11
+ ## [18.3.5] - 2026-09-27
12
+
13
+ ### Added
14
+
15
+ - Added the `openai` web-search grounding for OpenAI API models that support Responses web search (`gpt-5.5`, `gpt-5.6-luna`, `gpt-6-astra`, `gpt-6-luna`) ([#13467](https://github.com/can1357/oh-my-pi/pull/13467) by [@anatoli-tsinovoy](https://github.com/anatoli-tsinovoy)).
16
+ - Added `Model.promptCache`, per-retention-tier prompt-cache entry lifetimes in seconds (`short` / `long`), declared per provider through the `prompt-cache` KDL rule (bundled: direct Anthropic, 5 min / 1 h). Custom models and `modelOverrides` opt in with the models.yml `promptCache` key ([#12699](https://github.com/can1357/oh-my-pi/pull/12699) by [@KamijoToma](https://github.com/KamijoToma)).
17
+
5
18
  ## [18.3.1] - 2026-09-25
6
19
 
7
20
  ### Added
@@ -9,8 +9,8 @@
9
9
  import { type Api, type Model, type ModelSpec } from "./types.js";
10
10
  /**
11
11
  * Applies reviewed catalog-data value corrections (`cost-patch`,
12
- * `limits-patch`, `long-context-cost`, `context-window-floor`,
13
- * `input-modalities`) onto an upstream-sourced spec. Applied by
12
+ * `cache-read-at-input-rate`, `limits-patch`, `long-context-cost`,
13
+ * `context-window-floor`, `input-modalities`) onto an upstream-sourced spec. Applied by
14
14
  * `buildModel` to every upstream-sourced spec; user-authored overrides are
15
15
  * recomposed after building by the override applicators, so explicit user
16
16
  * limits and pricing still win.
@@ -5070,6 +5070,11 @@ export interface TruncatedToolCallSuccess extends ProtoMessage {
5070
5070
  export declare const TruncatedToolCallSuccessSchema: MessageCodec<TruncatedToolCallSuccess>;
5071
5071
  /** Cursor agent message agent.v1.TurnEndedUpdate. */
5072
5072
  export interface TurnEndedUpdate extends ProtoMessage {
5073
+ inputTokens?: bigint;
5074
+ outputTokens?: bigint;
5075
+ cacheReadTokens?: bigint;
5076
+ cacheWriteTokens?: bigint;
5077
+ reasoningTokens?: bigint;
5073
5078
  }
5074
5079
  export declare const TurnEndedUpdateSchema: MessageCodec<TurnEndedUpdate>;
5075
5080
  /** Cursor agent message agent.v1.TypeAction. */
@@ -12,7 +12,7 @@ export type ModelKind = (typeof MODEL_KINDS)[number];
12
12
  export declare const KIND_API_KINDS: readonly ["image", "tts", "stt", "embedding", "rerank", "video"];
13
13
  export type KindApiKind = (typeof KIND_API_KINDS)[number];
14
14
  /** Grounding transport available to chat models selected by the web role. */
15
- export type WebSearchGrounding = "gemini" | "anthropic" | "codex" | "xai" | "openrouter";
15
+ export type WebSearchGrounding = "gemini" | "anthropic" | "codex" | "xai" | "openrouter" | "openai";
16
16
  /** Non-chat runner protocols accepted by catalog seeds, outside the chat dispatch union. */
17
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"];
18
18
  /** Resolve a model's kind while preserving chat semantics for existing catalog rows. */
@@ -951,6 +951,12 @@ export interface TimeBasedCost {
951
951
  peakWindows: readonly PeakPricingWindow[];
952
952
  effectiveRates?: readonly EffectiveTokenCost[];
953
953
  }
954
+ /**
955
+ * Best-effort prompt-cache entry lifetime in seconds for each retention tier a
956
+ * request can ask for. A missing tier means the lifetime is unknown; consumers
957
+ * must not schedule cache warming against unknown lifetimes.
958
+ */
959
+ export type ModelPromptCache = Partial<Record<"short" | "long", number>>;
954
960
  /** Base token rates plus optional long-context and time-based pricing. */
955
961
  export interface ModelCost extends TokenCost {
956
962
  longContext?: LongContextTokenCost;
@@ -1077,6 +1083,14 @@ export interface Model<TApi extends Api = Api> {
1077
1083
  */
1078
1084
  accountAccess?: Readonly<Record<string, ModelAccountAccess>>;
1079
1085
  cost: ModelCost;
1086
+ /**
1087
+ * Prompt-cache entry lifetime per retention tier, in seconds. Populated only
1088
+ * for providers whose cache-expiry and replay behavior has been validated
1089
+ * for cache warming (direct Anthropic: 5m / 1h). A missing entry means the
1090
+ * provider's cache behavior is unknown — such models are never warmed.
1091
+ * Custom models and provider overrides opt in via models.yml `promptCache`.
1092
+ */
1093
+ promptCache?: ModelPromptCache;
1080
1094
  /** Premium Copilot requests charged per user-initiated request (defaults to 1). */
1081
1095
  premiumMultiplier?: number;
1082
1096
  contextWindow: number | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-catalog",
3
- "version": "18.3.4",
3
+ "version": "18.4.0",
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.3.4",
97
- "@oh-my-pi/pi-utils": "18.3.4"
96
+ "@oh-my-pi/omptype": "18.4.0",
97
+ "@oh-my-pi/pi-utils": "18.4.0"
98
98
  },
99
99
  "devDependencies": {
100
100
  "@bgotink/kdl": "0.4.0",
101
- "@oh-my-pi/pi-ai": "18.3.4",
101
+ "@oh-my-pi/pi-ai": "18.4.0",
102
102
  "@types/bun": "^1.3.14"
103
103
  },
104
104
  "engines": {
package/src/build.ts CHANGED
@@ -82,7 +82,8 @@ function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog:
82
82
  webSearch === "anthropic" ||
83
83
  webSearch === "codex" ||
84
84
  webSearch === "xai" ||
85
- webSearch === "openrouter"
85
+ webSearch === "openrouter" ||
86
+ webSearch === "openai"
86
87
  ) {
87
88
  model.webSearch = webSearch;
88
89
  }
@@ -97,6 +98,15 @@ function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog:
97
98
  }
98
99
  const priority = catalog.priority;
99
100
  if (typeof priority === "number") model.priority = priority;
101
+ const promptCache = objectPayload(catalog.promptCache);
102
+ if (promptCache !== undefined) {
103
+ const short = numberField(promptCache, "short");
104
+ const long = numberField(promptCache, "long");
105
+ model.promptCache = {
106
+ ...(short !== undefined && { short }),
107
+ ...(long !== undefined && { long }),
108
+ };
109
+ }
100
110
  const applyPatchToolType = catalog.applyPatchToolType;
101
111
  if (applyPatchToolType === "freeform" || applyPatchToolType === "function") {
102
112
  model.applyPatchToolType = applyPatchToolType;
@@ -130,8 +140,8 @@ function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog:
130
140
 
131
141
  /**
132
142
  * Applies reviewed catalog-data value corrections (`cost-patch`,
133
- * `limits-patch`, `long-context-cost`, `context-window-floor`,
134
- * `input-modalities`) onto an upstream-sourced spec. Applied by
143
+ * `cache-read-at-input-rate`, `limits-patch`, `long-context-cost`,
144
+ * `context-window-floor`, `input-modalities`) onto an upstream-sourced spec. Applied by
135
145
  * `buildModel` to every upstream-sourced spec; user-authored overrides are
136
146
  * recomposed after building by the override applicators, so explicit user
137
147
  * limits and pricing still win.
@@ -210,6 +220,14 @@ export function applyCatalogCorrections(
210
220
  applyEffectiveFallbackRates(model.cost, Reflect.get(fallback, "effectiveRates"));
211
221
  }
212
222
  }
223
+ if (catalog.cacheReadAtInputRate === true) {
224
+ const { longContext } = model.cost;
225
+ model.cost = {
226
+ ...model.cost,
227
+ cacheRead: model.cost.input,
228
+ ...(longContext && { longContext: { ...longContext, cacheRead: longContext.input } }),
229
+ };
230
+ }
213
231
  if (catalog.timeBased !== undefined) {
214
232
  model.cost = { ...model.cost, timeBased: materializeTimeBasedCost(catalog.timeBased) };
215
233
  }
@@ -321,6 +321,16 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
321
321
  "context-window-floor": { key: "contextWindowFloor", set: "catalog", shape: "scalar" },
322
322
  "cost-patch": { key: "costPatch", set: "catalog", shape: "object" },
323
323
  "cost-fallback": { key: "costFallback", set: "catalog", shape: "object" },
324
+ /**
325
+ * The host bills cache-hit input tokens at the full input rate (no cache
326
+ * discount), so the built row's `cacheRead` tracks its live `input` price.
327
+ */
328
+ "cache-read-at-input-rate": {
329
+ key: "cacheReadAtInputRate",
330
+ set: "catalog",
331
+ shape: "scalar",
332
+ values: [true, false],
333
+ },
324
334
  "delegation-bias": { key: "delegationBias", set: "catalog", shape: "scalar", values: DELEGATION_BIASES },
325
335
  "discovery-api": { key: "discoveryApi", set: "catalog", shape: "scalar" },
326
336
  "edit-prompt-variant": { key: "editPromptVariant", set: "catalog", shape: "scalar", values: ["full", "compact"] },
@@ -331,10 +341,11 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
331
341
  key: "webSearch",
332
342
  set: "catalog",
333
343
  shape: "scalar",
334
- values: ["gemini", "anthropic", "codex", "xai", "openrouter"],
344
+ values: ["gemini", "anthropic", "codex", "xai", "openrouter", "openai"],
335
345
  },
336
346
  "limits-patch": { key: "limitsPatch", set: "catalog", shape: "object" },
337
347
  "long-context-cost": { key: "longContext", set: "catalog", shape: "object" },
348
+ "prompt-cache": { key: "promptCache", set: "catalog", shape: "object" },
338
349
  "long-usage-limit-fallback": { key: "longUsageLimitFallback", set: "catalog", shape: "scalar" },
339
350
  "max-context-window": { key: "maxContextWindow", set: "catalog", shape: "scalar" },
340
351
  "requires-cursor-tool-schema-projection": {
@@ -6,6 +6,14 @@ provider "anthropic" {
6
6
  discovery label="Anthropic"
7
7
  web-search "anthropic"
8
8
 
9
+ // Prompt-cache entry lifetimes per retention tier, in seconds; feeds the
10
+ // coding agent's cache warmer. 5m writes for pay-per-token keys, 1h for
11
+ // retention-tier "long" requests.
12
+ prompt-cache {
13
+ short 300
14
+ long 3600
15
+ }
16
+
9
17
  // Curated Anthropic models that are live or limited-availability on the
10
18
  // first-party `/v1/models` endpoint but that stencil.so has not catalogued
11
19
  // yet. Seeded so the bundled catalog is never gated on stencil.so's update
@@ -10,6 +10,9 @@ provider "cerebras" {
10
10
  // Replaces the Cerebras provider branches in the completions baseline.
11
11
  supports-usage-in-streaming #false
12
12
  tool-strict-mode "all_strict"
13
+ // Prompt caching carries no discount: cached input tokens bill at the
14
+ // standard input rate (https://inference-docs.cerebras.ai/capabilities/prompt-caching).
15
+ cache-read-at-input-rate #true
13
16
  // Cerebras serves Gemma 4 with vision enabled; its /v1/models rows carry
14
17
  // no modality metadata.
15
18
  models "gemma-4-31b" {
@@ -3,6 +3,12 @@
3
3
  provider "openai" {
4
4
  default-model "gpt-5.5"
5
5
  env "OPENAI_API_KEY"
6
+ // Responses web search is documented for GPT-5.5 and GPT-6 Astra, and has
7
+ // been live-verified for GPT-6 Luna and GPT-5.6 Luna. Keep this capability
8
+ // model-scoped so realtime and other unverified OpenAI models stay excluded.
9
+ models "gpt-5.5" "gpt-6-astra" "gpt-6-luna" "gpt-5.6-luna" {
10
+ web-search "openai"
11
+ }
6
12
  kind-apis {
7
13
  embedding "openai-embeddings"
8
14
  image "openai-responses"