@oh-my-pi/pi-catalog 18.1.1 → 18.1.3

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,36 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.1.3] - 2026-09-02
6
+
7
+ ### Added
8
+
9
+ - Added support for Claude Fable 5.1
10
+
11
+ ### Changed
12
+
13
+ - Updated pricing and context limits for various Claude models
14
+
15
+ ### Fixed
16
+
17
+ - Claude Sonnet 5 no longer advertises unsupported mid-conversation system messages.
18
+ - Custom GLM 5.2 models on `alibaba-coding-plan` (and other blanket-GLM hosts) no longer crash startup with `AmbiguousOverlapError` ([#10553](https://github.com/can1357/oh-my-pi/issues/10553)).
19
+ - Gemini 3.7 Flash no longer offers the `minimal` thinking effort on direct google-level hosts (`google`, `google-vertex`, `opencode-zen`), which reject `thinkingLevel: MINIMAL` with a 400; budget and reasoning-effort resellers keep the tier ([#10543](https://github.com/can1357/oh-my-pi/issues/10543)).
20
+ - Fixed Alibaba Token Plan discovery for `qwen3.8-flash` to include its context limits, reasoning support, and image input.
21
+ - Z.AI GLM-5.3-Flash now uses the native API instead of failing through the unsupported Anthropic-compatible route ([#10539](https://github.com/can1357/oh-my-pi/issues/10539)).
22
+
23
+ ## [18.1.2] - 2026-09-01
24
+
25
+ ### Added
26
+
27
+ - Added support for turn-scoped system messages, changing tools during a conversation, and setting effort on individual messages.
28
+ - Added support for Claude Fable 5.1 models, with improved thinking-prefix handling across supported Claude models.
29
+ - Added DeepSeek V4 Flash Vision Exp, Mercury 2.5 Preview, and Xiaomi MiMo V2.5 Pro UltraSpeed models.
30
+
31
+ ### Changed
32
+
33
+ - Updated model pricing and context-window limits.
34
+
5
35
  ## [18.1.0] - 2026-09-01
6
36
 
7
37
  ### Added
@@ -502,7 +502,7 @@ export declare const CATALOG_PROVIDERS: readonly [{
502
502
  readonly id: "zai";
503
503
  readonly defaultModel: "glm-5.3";
504
504
  readonly envVars: readonly ["ZAI_API_KEY"];
505
- readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"anthropic-messages", unknown>;
505
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"anthropic-messages" | "openai-completions", unknown>;
506
506
  readonly catalogDiscovery: {
507
507
  readonly label: "zAI";
508
508
  };
@@ -673,6 +673,11 @@ export interface ModelsDevProviderDescriptor {
673
673
  }
674
674
  /** Generic mapper that converts models.dev data using provider descriptors. */
675
675
  export declare function mapModelsDevToModels(data: Record<string, unknown>, descriptors: readonly ModelsDevProviderDescriptor[]): ModelSpec<Api>[];
676
+ /** Resolves the transport and endpoint for one Z.AI model catalog entry. */
677
+ export declare function resolveZaiApi(modelId: string): {
678
+ api: "anthropic-messages" | "openai-completions";
679
+ baseUrl: string;
680
+ };
676
681
  /** All provider descriptors for models.dev data mapping in generate-models.ts. */
677
682
  export declare const MODELS_DEV_PROVIDER_DESCRIPTORS: readonly ModelsDevProviderDescriptor[];
678
683
  /** Providers whose bundled catalog can receive additive models.dev updates at runtime. */
@@ -70,4 +70,5 @@ export declare const DEVIN_STATIC_MODELS: readonly ModelSpec<"devin-agent">[];
70
70
  export declare function devinModelManagerOptions(config?: DevinModelManagerConfig): ModelManagerOptions<"devin-agent">;
71
71
  export interface ZaiModelManagerConfig {
72
72
  }
73
- export declare function zaiModelManagerOptions(_config?: ZaiModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
73
+ /** Creates model-manager options for Z.AI's mixed native and Anthropic transports. */
74
+ export declare function zaiModelManagerOptions(_config?: ZaiModelManagerConfig): ModelManagerOptions<"anthropic-messages" | "openai-completions">;
@@ -29,6 +29,11 @@ export interface ThinkingConfig {
29
29
  * 5). Also implies native interleaved thinking — no beta header needed.
30
30
  */
31
31
  supportsDisplay?: boolean;
32
+ /**
33
+ * Thinking signatures bind each block to its preceding conversation prefix.
34
+ * Requests that rewrite the prefix must opt into the provider's drop/error control.
35
+ */
36
+ prefixBinding?: boolean;
32
37
  /**
33
38
  * Per-effort upstream wire-id routing for collapsed effort-tier variants
34
39
  * (`compat/collapse.ts`). Keyed by pi effort; `"off"` applies when
@@ -437,12 +442,20 @@ export interface AnthropicCompat {
437
442
  supportsLongCacheRetention?: boolean;
438
443
  /**
439
444
  * Whether mid-conversation `role: "system"` messages are accepted in the
440
- * `messages` array (Claude Opus 4.8+ and Claude Fable/Mythos 5 on the
441
- * first-party Claude API and Claude Platform on AWS). When unset,
442
- * auto-detected from the model id and base URL. Not available on Bedrock,
443
- * Vertex AI, or Microsoft Foundry.
445
+ * `messages` array. When unset, auto-detected from model and deployment policy.
444
446
  */
445
447
  supportsMidConversationSystem?: boolean;
448
+ /** Whether turn-scoped system messages accept `clear_at`. */
449
+ supportsTurnScopedSystem?: boolean;
450
+ /** Whether tool availability can change through system-message tool references. */
451
+ supportsMidConversationToolChanges?: boolean;
452
+ /** Whether effort can change through a per-message `output_config`. */
453
+ supportsPerMessageEffort?: boolean;
454
+ /**
455
+ * Whether the endpoint accepts `thinking.block_binding` and reports
456
+ * `input_transformations` under the thinking-binding-controls beta.
457
+ */
458
+ supportsThinkingBindingControls?: boolean;
446
459
  /**
447
460
  * Whether the model accepts a forced `tool_choice` (`{ type: "any" }` or
448
461
  * `{ type: "tool", name }`). Claude Fable/Mythos 5 reject forced tool use
@@ -866,6 +879,8 @@ export interface Model<TApi extends Api = Api> {
866
879
  * inferring it from the transport API.
867
880
  */
868
881
  requiresGlyphTokenization?: boolean;
882
+ /** Whether this model requires Cursor's tool-schema combiner projection. */
883
+ requiresCursorToolSchemaProjection?: boolean;
869
884
  /**
870
885
  * Model id to send on the wire when it differs from `id`. Used by catalog
871
886
  * variants that present one upstream model under several local entries —
@@ -1020,7 +1035,7 @@ export interface Model<TApi extends Api = Api> {
1020
1035
  * vocabulary of `buildModel`. Identical to `Model` except `compat` carries the
1021
1036
  * sparse override shape and nothing is resolved yet.
1022
1037
  */
1023
- export interface ModelSpec<TApi extends Api = Api> extends Omit<Model<TApi>, "compat" | "identity" | "compatConfig" | "requiresGlyphTokenization" | "supportsComputerUseConfig"> {
1038
+ export interface ModelSpec<TApi extends Api = Api> extends Omit<Model<TApi>, "compat" | "identity" | "compatConfig" | "requiresGlyphTokenization" | "requiresCursorToolSchemaProjection" | "supportsComputerUseConfig"> {
1024
1039
  /** Sparse compatibility overrides; resolved into `Model.compat` by `buildModel`. */
1025
1040
  compat?: CompatConfigOf<TApi>;
1026
1041
  }
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.1.1",
4
+ "version": "18.1.3",
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.",
@@ -35,12 +35,12 @@
35
35
  "gen:proto": "bun scripts/generate-protocols.ts"
36
36
  },
37
37
  "dependencies": {
38
- "@oh-my-pi/omptype": "18.1.1",
39
- "@oh-my-pi/pi-utils": "18.1.1"
38
+ "@oh-my-pi/omptype": "18.1.3",
39
+ "@oh-my-pi/pi-utils": "18.1.3"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@bgotink/kdl": "0.4.0",
43
- "@oh-my-pi/pi-ai": "18.1.1",
43
+ "@oh-my-pi/pi-ai": "18.1.3",
44
44
  "@types/bun": "^1.3.14"
45
45
  },
46
46
  "engines": {
package/src/build.ts CHANGED
@@ -32,7 +32,8 @@ function isInputModalities(value: unknown): value is ("text" | "image")[] {
32
32
  * Applies resolved catalog-data axes onto the model: reviewed metadata
33
33
  * corrections (`cost-patch`, `limits-patch`, `long-context-cost`,
34
34
  * `context-window-floor`) overwrite upstream values; selection metadata
35
- * (`priority`, `apply-patch-tool-type`, `service-tier-cost`) is rule-owned;
35
+ * (`priority`, `apply-patch-tool-type`, `service-tier-cost`,
36
+ * `requires-cursor-tool-schema-projection`) is rule-owned;
36
37
  * `context-promotion-target` fills only when the spec left it unset.
37
38
  */
38
39
  function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog: Record<string, unknown>): void {
@@ -51,6 +52,12 @@ function applyCatalogAssignments<TApi extends Api>(model: Model<TApi>, catalog:
51
52
  if (applyPatchToolType === "freeform" || applyPatchToolType === "function") {
52
53
  model.applyPatchToolType = applyPatchToolType;
53
54
  }
55
+ const requiresCursorToolSchemaProjection = catalog.requiresCursorToolSchemaProjection;
56
+ if (requiresCursorToolSchemaProjection === true) {
57
+ model.requiresCursorToolSchemaProjection = true;
58
+ } else {
59
+ delete model.requiresCursorToolSchemaProjection;
60
+ }
54
61
  const contextPromotionTarget = catalog.contextPromotionTarget;
55
62
  if (typeof contextPromotionTarget === "string" && model.contextPromotionTarget === undefined) {
56
63
  model.contextPromotionTarget = contextPromotionTarget;
@@ -193,6 +193,10 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
193
193
  "supports-eager-tool-input-streaming": wire("supportsEagerToolInputStreaming", ["anthropic"]),
194
194
  "supports-long-cache-retention": wire("supportsLongCacheRetention", ["anthropic"]),
195
195
  "supports-mid-conversation-system": wire("supportsMidConversationSystem", ["anthropic"]),
196
+ "supports-mid-conversation-tool-changes": wire("supportsMidConversationToolChanges", ["anthropic"]),
197
+ "supports-per-message-effort": wire("supportsPerMessageEffort", ["anthropic"]),
198
+ "supports-thinking-binding-controls": wire("supportsThinkingBindingControls", ["anthropic"]),
199
+ "supports-turn-scoped-system": wire("supportsTurnScopedSystem", ["anthropic"]),
196
200
 
197
201
  // ── wire: bedrock-converse-stream ──
198
202
  "prompt-cache-maximum-checkpoints": wire("promptCacheMaximumCheckpoints", ["bedrock"]),
@@ -239,6 +243,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
239
243
  values: THINKING_MODES,
240
244
  },
241
245
  "thinking-requires-effort": { key: "requiresEffort", set: "thinking", shape: "scalar" },
246
+ "thinking-prefix-binding": { key: "prefixBinding", set: "thinking", shape: "scalar" },
242
247
  "thinking-suppress-when-off": { key: "suppressWhenOff", set: "thinking", shape: "scalar" },
243
248
  "thinking-supports-display": { key: "supportsDisplay", set: "thinking", shape: "scalar" },
244
249
 
@@ -257,6 +262,11 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
257
262
  "limits-patch": { key: "limitsPatch", set: "catalog", shape: "object" },
258
263
  "long-context-cost": { key: "longContext", set: "catalog", shape: "object" },
259
264
  "long-usage-limit-fallback": { key: "longUsageLimitFallback", set: "catalog", shape: "scalar" },
265
+ "requires-cursor-tool-schema-projection": {
266
+ key: "requiresCursorToolSchemaProjection",
267
+ set: "catalog",
268
+ shape: "scalar",
269
+ },
260
270
  priority: { key: "priority", set: "catalog", shape: "scalar" },
261
271
  "service-tier-cost": { key: "serviceTierCost", set: "catalog", shape: "object" },
262
272
  };
@@ -846,7 +846,11 @@ function resolveAnthropicPolicy(
846
846
  allowAnthropicHeaderOverrides: false,
847
847
  supportsEagerToolInputStreaming: official,
848
848
  supportsLongCacheRetention: official,
849
- supportsMidConversationSystem: official && facts.anthropicAdaptiveGenAtLeast("4.8"),
849
+ supportsMidConversationSystem: official && !facts.family("sonnet") && facts.anthropicAdaptiveGenAtLeast("4.8"),
850
+ supportsTurnScopedSystem: false,
851
+ supportsMidConversationToolChanges: false,
852
+ supportsPerMessageEffort: false,
853
+ supportsThinkingBindingControls: false,
850
854
  supportsForcedToolChoice: !requiresThinkingEnabled && !facts.family("fable", "mythos"),
851
855
  supportsSamplingParams: !facts.anthropicAdaptiveGenAtLeast("4.7"),
852
856
  requiresToolResultId: false,
@@ -1012,6 +1016,7 @@ interface RuleThinking {
1012
1016
  requiresEffort?: boolean;
1013
1017
  suppressWhenOff?: boolean;
1014
1018
  supportsDisplay?: boolean;
1019
+ prefixBinding?: boolean;
1015
1020
  }
1016
1021
 
1017
1022
  function readRuleThinking(axes: ResolvedAxes): RuleThinking {
@@ -1030,6 +1035,7 @@ function readRuleThinking(axes: ResolvedAxes): RuleThinking {
1030
1035
  if (typeof raw.requiresEffort === "boolean") out.requiresEffort = raw.requiresEffort;
1031
1036
  if (typeof raw.suppressWhenOff === "boolean") out.suppressWhenOff = raw.suppressWhenOff;
1032
1037
  if (typeof raw.supportsDisplay === "boolean") out.supportsDisplay = raw.supportsDisplay;
1038
+ if (typeof raw.prefixBinding === "boolean") out.prefixBinding = raw.prefixBinding;
1033
1039
  return out;
1034
1040
  }
1035
1041
 
@@ -1085,6 +1091,7 @@ function resolveThinkingPolicy<TApi extends Api>(
1085
1091
  if (rule.effortBudgets !== undefined) config.effortBudgets = rule.effortBudgets;
1086
1092
  const supportsDisplay = rule.supportsDisplay ?? defaultSupportsDisplay(spec, facts);
1087
1093
  if (supportsDisplay) config.supportsDisplay = true;
1094
+ if (rule.prefixBinding) config.prefixBinding = true;
1088
1095
  const requiresEffort =
1089
1096
  rule.requiresEffort ?? (impliesMandatoryReasoning(facts, spec.id) || isQwenTemplateReasoningEffortCompat(compat));
1090
1097
  if (requiresEffort) config.requiresEffort = true;
@@ -1142,7 +1149,8 @@ function fillExplicitThinking<TApi extends Api>(
1142
1149
  (rule.requiresEffort ??
1143
1150
  (impliesMandatoryReasoning(facts, spec.id) || isQwenTemplateReasoningEffortCompat(compat)));
1144
1151
  const needsDefaultLevel = thinking.defaultLevel === undefined && rule.defaultLevel !== undefined;
1145
- if (effortMap === undefined && !needsDisplay && !needsRequiresEffort && !needsDefaultLevel) {
1152
+ const needsPrefixBinding = thinking.prefixBinding === undefined && rule.prefixBinding === true;
1153
+ if (effortMap === undefined && !needsDisplay && !needsRequiresEffort && !needsDefaultLevel && !needsPrefixBinding) {
1146
1154
  return thinking;
1147
1155
  }
1148
1156
  const filled: ThinkingConfig = { ...thinking };
@@ -1150,6 +1158,7 @@ function fillExplicitThinking<TApi extends Api>(
1150
1158
  if (needsDisplay) filled.supportsDisplay = true;
1151
1159
  if (needsDefaultLevel && rule.defaultLevel !== undefined) filled.defaultLevel = rule.defaultLevel;
1152
1160
  if (needsRequiresEffort) filled.requiresEffort = true;
1161
+ if (needsPrefixBinding) filled.prefixBinding = true;
1153
1162
  return filled;
1154
1163
  }
1155
1164
 
@@ -1,6 +1,49 @@
1
1
  // Model-lineage compat for "anthropic"; regenerated from the frozen census using class taxonomy selectors.
2
2
 
3
3
  class "anthropic" {
4
+ family "fable" {
5
+ revision ">=5.1" {
6
+ // Fable 5.1+ binds signed thinking to the exact preceding conversation.
7
+ thinking-prefix-binding #true
8
+ }
9
+ }
10
+ on "anthropic" "cloudflare-ai-gateway" "google-vertex" {
11
+ family "fable" {
12
+ revision ">=5" {
13
+ supports-mid-conversation-system #true
14
+ supports-mid-conversation-tool-changes #true
15
+ supports-turn-scoped-system #true
16
+ }
17
+ revision ">=5.1" {
18
+ supports-per-message-effort #true
19
+ }
20
+ }
21
+ family "mythos" {
22
+ revision ">=5" {
23
+ supports-mid-conversation-system #true
24
+ supports-mid-conversation-tool-changes #true
25
+ supports-turn-scoped-system #true
26
+ }
27
+ revision ">=5.1" {
28
+ supports-per-message-effort #true
29
+ }
30
+ }
31
+ family "fable" {
32
+ revision ">=5.1" {
33
+ supports-thinking-binding-controls #true
34
+ }
35
+ }
36
+ family "opus" {
37
+ revision ">=4.8" {
38
+ supports-mid-conversation-system #true
39
+ supports-mid-conversation-tool-changes #true
40
+ supports-turn-scoped-system #true
41
+ }
42
+ revision ">=5" {
43
+ supports-per-message-effort #true
44
+ }
45
+ }
46
+ }
4
47
  on "aimlapi" "gitlab-duo" "kilo" "nanogpt" "venice" {
5
48
  thinking-efforts "minimal" "low" "medium" "high" "xhigh"
6
49
  }
@@ -66,17 +66,32 @@ class "gemini" {
66
66
  }
67
67
  }
68
68
  }
69
+ // Gemini 3.7 Flash is the one Flash revision whose native thinkingLevel does
70
+ // not accept `minimal` (400 THINKING_LEVEL_MINIMAL). Only the direct
71
+ // google-level transports emit `thinkingLevel` on the wire, so the tier is
72
+ // dropped there; budget (anthropic-messages) and reasoning_effort resellers
73
+ // never send the rejected value and keep the four-tier ladder. The collapsed
74
+ // google-antigravity / google-gemini-cli variants remap minimal -> LOW and
75
+ // carry their own explicit ladder, so they are unaffected.
76
+ // https://ai.google.dev/gemini-api/docs/generate-content/thinking#thinking-levels
77
+ on "google" "google-vertex" "opencode-zen" {
78
+ family "flash" {
79
+ revision ">=3.7 <3.8" {
80
+ thinking-efforts "low" "medium" "high"
81
+ }
82
+ }
83
+ }
69
84
 
70
- // Gemini 3 tool calls require the sentinel signature on unsigned replay.
71
85
  revision ">=3" {
72
86
  // Replaces the Google multimodal function-response baseline.
73
87
  multimodal-function-response #true
74
- requires-skip-thought-signature #true
75
88
  // Replaces the Gemini 3+ mandatory-reasoning fallback.
76
89
  thinking-requires-effort #true
77
90
  }
91
+ // Only public-Gemini-compatible transports accept the bypass sentinel for unsigned calls.
78
92
  on "google" "opencode-zen" {
79
93
  revision ">=3" {
94
+ requires-skip-thought-signature #true
80
95
  supports-function-part-id #true
81
96
  }
82
97
  }
@@ -10,7 +10,10 @@ class "glm" {
10
10
  // GLM-5.2 exposes the default lower tiers plus a genuine max on generic
11
11
  // OpenAI-compatible hosts; the zai-dialect and Anthropic-route hosts
12
12
  // (Z.ai, Zhipu, Umans, Ollama Cloud, Baseten) serve only high/max.
13
- revision ">=5.2 <5.3" {
13
+ // priority breaks the intentional overlap with provider-level blanket GLM
14
+ // ladders authored for the pre-5.2 census (e.g. alibaba-coding-plan.kdl),
15
+ // so the 5.2 lineage ladder wins on generic hosts that lack a 5.2 residue.
16
+ revision ">=5.2 <5.3" priority=10 {
14
17
  thinking-efforts "minimal" "low" "medium" "high" "max"
15
18
  }
16
19
  on "zai" "zhipu-coding-plan" {
@@ -2,6 +2,11 @@
2
2
 
3
3
  provider "cursor" {
4
4
  thinking-mode "effort"
5
+ class "anthropic" {
6
+ family "fable" {
7
+ requires-cursor-tool-schema-projection #true
8
+ }
9
+ }
5
10
  // GetUsableModels advertises no input modalities or context windows.
6
11
  // K3 (including the bare `k3` alias Cursor serves) is natively
7
12
  // multimodal and 1M-context.
@@ -25,8 +25,12 @@ provider "zai" {
25
25
  }
26
26
  // GLM-5.3-Flash is the first mandatory-thinking flash SKU. Its exact
27
27
  // deployment keeps the Anthropic budget+effort wire mode instead of the
28
- // older optional-thinking flash family's budget-only mode.
28
+ // older optional-thinking flash family's budget-only mode. The SKU rides
29
+ // Z.AI's native OpenAI-completions endpoint, so clamp the sent max_tokens
30
+ // to the advertised 131K cap rather than the 64K OpenAI default (the
31
+ // axis is a no-op on the Anthropic route).
29
32
  models "glm-5.3-flash" {
30
33
  thinking-mode "anthropic-budget-effort"
34
+ clamp-output-to-model-max #true
31
35
  }
32
36
  }
@@ -158,6 +158,11 @@ behavior {
158
158
  api-routes provider="zenmux" default="openai-completions" {
159
159
  route "anthropic-messages" prefix="anthropic/"
160
160
  }
161
+ // GLM-5.3-Flash is available on Z.AI's native chat-completions API but
162
+ // not its Anthropic-compatible coding endpoint (#10539).
163
+ api-routes provider="zai" default="anthropic-messages" {
164
+ route "openai-completions" exact="glm-5.3-flash"
165
+ }
161
166
  // OpenCode Zen: models.dev declares these with `@ai-sdk/anthropic`, but the
162
167
  // gateway serves them only at /v1/chat/completions (#1617).
163
168
  api-routes provider="opencode-zen" {