@oh-my-pi/pi-catalog 18.0.3 → 18.0.4

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,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.0.4] - 2026-08-24
6
+
7
+ ### Fixed
8
+
9
+ - Fixed default reasoning effort for `cursor/cursor-grok-4.5` and `cursor/cursor-grok-4.6` so requests without an explicit effort setting default to `-medium` instead of `-low`, preventing rate limit rejections on Cursor's Start plan ([#9478](https://github.com/can1357/oh-my-pi/issues/9478)).
10
+ - Fixed aliased OpenCode Zen Ox Alpha models exposing incorrect effort levels, ensuring the gateway's native `low`, `high`, and `max` tiers are correctly mapped and reachable ([#9349](https://github.com/can1357/oh-my-pi/issues/9349)).
11
+ - Fixed missing rate card tier for public xAI and SuperGrok models with prompt lengths exceeding 200K tokens ([#9512](https://github.com/can1357/oh-my-pi/issues/9512)).
12
+
5
13
  ## [18.0.2] - 2026-08-23
6
14
 
7
15
  ### Fixed
@@ -67,4 +67,15 @@ export declare function resolveWireModelId<TApi extends Api>(model: ApiModel<TAp
67
67
  * thinking-off requests on `thinking.requiresEffort` models.
68
68
  */
69
69
  export declare function minimumSupportedEffort<TApi extends Api>(model: ApiModel<TApi>): Effort | undefined;
70
+ /**
71
+ * Clamp target for effort-less requests on `thinking.requiresEffort` models:
72
+ * the effort whose wire route equals the model's default wire id
73
+ * (`requestModelId`), so a collapsed row clamps to the tier it already
74
+ * advertises as its default rather than the numerically lowest supported tier
75
+ * (e.g. Cursor Grok 4.5/4.6 default to `medium`, the only tier the Start plan
76
+ * serves). Falls back to {@link minimumSupportedEffort} when no route matches
77
+ * the default id — families whose default already is the minimum, or that
78
+ * expose no routing, are unaffected.
79
+ */
80
+ export declare function defaultSupportedEffort<TApi extends Api>(model: ApiModel<TApi>): Effort | undefined;
70
81
  export {};
@@ -1,11 +1,14 @@
1
1
  import MODELS from "./models.json";
2
- import type { Api, KnownProvider, Model, Usage } from "./types.js";
2
+ import type { Api, KnownProvider, Model, ModelCost, Usage } from "./types.js";
3
3
  export type GeneratedProvider = keyof typeof MODELS;
4
4
  export declare function getBundledModel<TApi extends Api = Api>(provider: GeneratedProvider, modelId: string): Model<TApi>;
5
5
  export declare function getBundledProviders(): KnownProvider[];
6
6
  export declare function getBundledModels(provider: GeneratedProvider): Model<Api>[];
7
7
  /** Price a prompt as fully uncached input under its active context-length tier. */
8
- export declare function calculateUncachedInputCost(cost: Model["cost"], promptInputTokens: number): number;
8
+ export declare function calculateUncachedInputCost(cost: ModelCost, promptInputTokens: number): number;
9
+ /** Price one usage record from a token rate card, including active context tiers. */
10
+ export declare function calculateUsageCost(cost: ModelCost, usage: Usage): Usage["cost"];
11
+ /** Price one usage record from its model's token rate card. */
9
12
  export declare function calculateCost<TApi extends Api>(model: Model<TApi>, usage: Usage): Usage["cost"];
10
13
  /**
11
14
  * Check if two models are equal by comparing both their id and provider.
@@ -166,6 +166,11 @@ export interface XaiModelManagerConfig {
166
166
  baseUrl?: string;
167
167
  fetch?: FetchImpl;
168
168
  }
169
+ /**
170
+ * Applies xAI's long-context rate card and mirrors exact public-model prices
171
+ * onto matching SuperGrok catalog rows.
172
+ */
173
+ export declare function applyXaiCatalogPricing(models: readonly ModelSpec[]): ModelSpec[];
169
174
  export declare function xaiModelManagerOptions(config?: XaiModelManagerConfig): ModelManagerOptions<"openai-responses">;
170
175
  export interface XaiOAuthModelManagerConfig {
171
176
  apiKey?: string;
@@ -705,12 +705,15 @@ export interface TokenCost {
705
705
  cacheWrite: number;
706
706
  }
707
707
  /**
708
- * Rates applied to the full request when its prompt exceeds `inputThreshold`.
709
- * Prompt input is the sum of uncached, cached-read, cache-write, and
710
- * provider-orchestration input tokens.
708
+ * Rates applied to the full request when its prompt exceeds `inputThreshold`,
709
+ * or reaches it when `inputThresholdInclusive` is true. Prompt input is the
710
+ * sum of uncached, cached-read, cache-write, and provider-orchestration input
711
+ * tokens.
711
712
  */
712
713
  export interface LongContextTokenCost extends TokenCost {
713
714
  inputThreshold: number;
715
+ /** Whether the long-context tier starts exactly at `inputThreshold`. */
716
+ inputThresholdInclusive?: boolean;
714
717
  }
715
718
  /** Base token rates plus an optional long-context tier. */
716
719
  export interface ModelCost extends TokenCost {
@@ -21,6 +21,15 @@ export interface EffortVariantFamily {
21
21
  * when it equals the logical id).
22
22
  */
23
23
  members: readonly string[];
24
+ /**
25
+ * Preferred default wire id: overrides the member-order default for the
26
+ * collapsed spec's `requestModelId` when this member is live. Lets a
27
+ * mandatory-reasoning family advertise a canonical tier that is not its
28
+ * numeric floor (Cursor Grok 4.5/4.6 default to `-medium`, the only tier the
29
+ * Start plan serves; the `-low` floor is refused). Ignored when absent from
30
+ * the input or retired.
31
+ */
32
+ defaultMember?: string;
24
33
  /**
25
34
  * Wire ids upstream no longer serves (e.g. a deployment killed while
26
35
  * discovery still advertises it). Fresh collapsing never routes to them,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "18.0.3",
4
+ "version": "18.0.4",
5
5
  "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Stencil Labs, Inc.",
@@ -34,11 +34,11 @@
34
34
  "gen:proto": "bun scripts/generate-protocols.ts"
35
35
  },
36
36
  "dependencies": {
37
- "@oh-my-pi/omptype": "18.0.3",
38
- "@oh-my-pi/pi-utils": "18.0.3"
37
+ "@oh-my-pi/omptype": "18.0.4",
38
+ "@oh-my-pi/pi-utils": "18.0.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@oh-my-pi/pi-ai": "18.0.3",
41
+ "@oh-my-pi/pi-ai": "18.0.4",
42
42
  "@types/bun": "^1.3.14"
43
43
  },
44
44
  "engines": {
@@ -559,15 +559,19 @@ function isSakanaFuguReasoningModel<TApi extends Api>(spec: ModelSpec<TApi>): bo
559
559
  * `opencode-zen`) reason through the wire-exact `low`/`high`/`max` ladder with
560
560
  * mandatory thinking: the gateway rejects `minimal`/`medium`/`xhigh`
561
561
  * (`[1210] ... please use low, high, or max`), the same dialect it already
562
- * serves for GLM-5.3 and Kimi K3. Other hosts proxying an `ox-alpha` SKU
563
- * (Kilo, NanoGPT, Venice, OpenRouter) expose their own vocabularies and are
564
- * left untouched. See issue #9349.
562
+ * serves for GLM-5.3 and Kimi K3. The SKU also ships under unrelated aliased
563
+ * ids (`opencode-zen/x-preview-f-free`), so the stencil display name is
564
+ * matched as well. Other hosts proxying an `ox-alpha` SKU (Kilo, NanoGPT,
565
+ * Venice, OpenRouter) expose their own vocabularies and are left untouched.
566
+ * See issue #9349.
565
567
  */
566
568
  function isOpenCodeGatewayOxAlphaModel<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
567
- return (
568
- (spec.provider === "opencode-go" || spec.provider === "opencode-zen") &&
569
- /(?:^|\/)ox-alpha(?:-|$)/i.test(bareModelId(spec.id))
570
- );
569
+ if (spec.provider !== "opencode-go" && spec.provider !== "opencode-zen") return false;
570
+ if (/(?:^|\/)ox-alpha(?:-|$)/i.test(bareModelId(spec.id))) return true;
571
+ // Aliased gateway ids surface the same SKU under an unrelated id; the
572
+ // display name ("Ox Alpha …") is the stable cross-id signal. Anchored on
573
+ // both sides so "Box Alpha"/"Ox Alphabet" cannot false-positive.
574
+ return /\box[ _-]?alpha\b/i.test(spec.name ?? "");
571
575
  }
572
576
 
573
577
  function isDeepseekReasoningModel<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
@@ -923,3 +927,25 @@ export function minimumSupportedEffort<TApi extends Api>(model: ApiModel<TApi>):
923
927
  }
924
928
  return efforts[0];
925
929
  }
930
+
931
+ /**
932
+ * Clamp target for effort-less requests on `thinking.requiresEffort` models:
933
+ * the effort whose wire route equals the model's default wire id
934
+ * (`requestModelId`), so a collapsed row clamps to the tier it already
935
+ * advertises as its default rather than the numerically lowest supported tier
936
+ * (e.g. Cursor Grok 4.5/4.6 default to `medium`, the only tier the Start plan
937
+ * serves). Falls back to {@link minimumSupportedEffort} when no route matches
938
+ * the default id — families whose default already is the minimum, or that
939
+ * expose no routing, are unaffected.
940
+ */
941
+ export function defaultSupportedEffort<TApi extends Api>(model: ApiModel<TApi>): Effort | undefined {
942
+ const routing = model.thinking?.effortRouting;
943
+ const defaultWireId = model.requestModelId;
944
+ if (routing !== undefined && defaultWireId !== undefined) {
945
+ const efforts = model.thinking?.efforts;
946
+ for (const effort of THINKING_EFFORTS) {
947
+ if (efforts?.includes(effort) && routing[effort] === defaultWireId) return effort;
948
+ }
949
+ }
950
+ return minimumSupportedEffort(model);
951
+ }