@oh-my-pi/pi-catalog 18.3.0 → 18.3.2

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,18 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.3.1] - 2026-09-25
6
+
7
+ ### Added
8
+
9
+ - Added compatibility flags for models that stop output at the context-window limit and models that support steering, including defaults for Claude 4.5+ and GPT-6+ models.
10
+
11
+ ### Fixed
12
+
13
+ - Fixed forced-tool requests for Claude Opus 5.5 so tool selection falls back gracefully when necessary.
14
+ - Added the provider-advertised `xhigh` reasoning level for Yolo-Auto Qwen3.8 models.
15
+ - Fixed Devin Fusion pairing requests failing with `no API providers are available` by routing them through the lead model with the lead's limits and pricing; pairings without an available lead are no longer listed ([#13000](https://github.com/can1357/oh-my-pi/pull/13000) by [@DarkPhilosophy](https://github.com/DarkPhilosophy)).
16
+
5
17
  ## [18.3.0] - 2026-09-24
6
18
 
7
19
  ### Added
@@ -78,8 +78,8 @@ below.
78
78
  uutils coreutils (https://github.com/uutils/coreutils), MIT
79
79
  --------------------------------------------------------------------------------
80
80
  Covers: base32, base64, basename, cat, cksum (shared checksum machinery),
81
- b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm, cut,
82
- date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
81
+ b2sum, md5sum, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, comm, cp,
82
+ cut, date, dirname, head, hostname, ln, ls, mkdir, mktemp, mv, nproc, paste,
83
83
  printenv, readlink, realpath, rm, seq, sort, stat, tac, tail, tee, touch, tr,
84
84
  truncate, uname, uniq, wc, whoami, yes.
85
85
 
@@ -0,0 +1,7 @@
1
+ import type { Model } from "../types.js";
2
+ /**
3
+ * Model ids on which a refusal's Anthropic fallback-credit token may be
4
+ * redeemed, authored on the `fallback-credit-targets` catalog axis. Empty when
5
+ * no rule assigns targets (the model cannot redeem credit on any fallback).
6
+ */
7
+ export declare function fallbackCreditTargets(model: Model): readonly string[];
@@ -1,3 +1,8 @@
1
1
  import type { Model } from "../types.js";
2
+ /**
3
+ * Whether the host truncates generation at the context window rather than
4
+ * rejecting prompt + output cap overflow; the output fitter skips these models.
5
+ */
6
+ export declare function stopsOutputAtContextWindow(model: Model): boolean;
2
7
  /** Whether discovery and transport policy allow preserving a caller's output cap. */
3
8
  export declare function supportsOutputTokenLimit(model: Model): boolean;
@@ -0,0 +1,7 @@
1
+ import type { Model } from "../types.js";
2
+ /**
3
+ * Ordered model ids for Anthropic's server-side refusal `fallbacks` chain,
4
+ * authored on the `server-side-fallback-models` catalog axis. Empty when no
5
+ * rule assigns a chain (the model or host does not support the feature).
6
+ */
7
+ export declare function serverSideFallbackModels(model: Model): readonly string[];
@@ -401,6 +401,13 @@ export interface OpenAICompat {
401
401
  * sent as the top-level `reasoning.effort`.
402
402
  */
403
403
  supportsConfigurationUpdate?: boolean;
404
+ /**
405
+ * Whether the Responses WebSocket accepts `response.steer`, which queues user
406
+ * input into the in-flight response (GPT-6 family). Default: rule-detected.
407
+ * Set `false` for proxies that reject the event; steering then waits for the
408
+ * next request boundary.
409
+ */
410
+ supportsSteering?: boolean;
404
411
  /** Whether streamed reasoning deltas for the same field may repeat the full cumulative text snapshot. Default: false. */
405
412
  reasoningDeltasMayBeCumulative?: boolean;
406
413
  /** Strip leaked DeepSeek chat-template special tokens from visible content deltas. Default: auto-detected. */
@@ -727,7 +734,7 @@ export interface ResolvedOpenAISharedCompat {
727
734
  * `buildModel`; request handlers read fields and never detect, resolve, or
728
735
  * allocate.
729
736
  */
730
- export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
737
+ export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsReasoningSummary" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "disableReasoningWithTools" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "qwenTemplateReasoningEffort" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "clampOutputToModelMax" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "streamRevision" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "supportsConfigurationUpdate" | "supportsSteering" | "stripImageInput" | "thinkingLoopGuard" | "whenThinking">> & {
731
738
  vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
732
739
  extraBody?: OpenAICompat["extraBody"];
733
740
  cacheControlFormat?: OpenAICompat["cacheControlFormat"];
@@ -761,6 +768,11 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
761
768
  * the item type with 400.
762
769
  */
763
770
  supportsConfigurationUpdate: boolean;
771
+ /**
772
+ * Whether the WebSocket transport may send `response.steer` to deliver user
773
+ * input into the in-flight response. Rule-owned: GPT-6 family.
774
+ */
775
+ supportsSteering: boolean;
764
776
  /** Inject the `# Juice: 0 !important` developer item when reasoning is forced off (gpt-5.6+). */
765
777
  requiresReasoningOffJuiceInstruction: boolean;
766
778
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-catalog",
3
- "version": "18.3.0",
3
+ "version": "18.3.2",
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.0",
97
- "@oh-my-pi/pi-utils": "18.3.0"
96
+ "@oh-my-pi/omptype": "18.3.2",
97
+ "@oh-my-pi/pi-utils": "18.3.2"
98
98
  },
99
99
  "devDependencies": {
100
100
  "@bgotink/kdl": "0.4.0",
101
- "@oh-my-pi/pi-ai": "18.3.0",
101
+ "@oh-my-pi/pi-ai": "18.3.2",
102
102
  "@types/bun": "^1.3.14"
103
103
  },
104
104
  "engines": {
@@ -139,6 +139,7 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
139
139
  "requires-reasoning-off-juice-instruction": wire("requiresReasoningOffJuiceInstruction", ["openai-responses"]),
140
140
  "supports-all-turns-reasoning-context": wire("supportsAllTurnsReasoningContext", ["openai-responses"]),
141
141
  "supports-configuration-update": wire("supportsConfigurationUpdate", ["openai-responses"]),
142
+ "supports-steering": wire("supportsSteering", ["openai-responses"]),
142
143
  "strip-deepseek-special-tokens": wire("stripDeepseekSpecialTokens", OAI),
143
144
  "stream-markup-healing-pattern": wire("streamMarkupHealingPattern", OAI, "scalar", [
144
145
  "kimi",
@@ -303,6 +304,18 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
303
304
  shape: "scalar",
304
305
  values: [true, false],
305
306
  },
307
+ /**
308
+ * The host accepts a prompt plus `max_tokens` beyond the context window and
309
+ * ends generation at the window (Anthropic `model_context_window_exceeded`)
310
+ * instead of rejecting the request, so callers must not lower the output cap
311
+ * to fit the window.
312
+ */
313
+ "stops-output-at-context-window": {
314
+ key: "stopsOutputAtContextWindow",
315
+ set: "catalog",
316
+ shape: "scalar",
317
+ values: [true, false],
318
+ },
306
319
  "clamp-context-override": { key: "clampContextOverride", set: "catalog", shape: "scalar" },
307
320
  "context-promotion-target": { key: "contextPromotionTarget", set: "catalog", shape: "scalar" },
308
321
  "context-window-floor": { key: "contextWindowFloor", set: "catalog", shape: "scalar" },
@@ -335,6 +348,18 @@ export const AXES: Readonly<Record<string, AxisDef>> = {
335
348
  shape: "scalar",
336
349
  },
337
350
  "supports-assistant-prefill": { key: "supportsAssistantPrefill", set: "catalog", shape: "scalar" },
351
+ /**
352
+ * Ordered Anthropic model ids forwarded as the server-side `fallbacks`
353
+ * chain when the user opts in. Each must appear in the requested model's
354
+ * `allowed_fallback_models` (GET /v1/models/{id}); anything else is a 400.
355
+ */
356
+ "server-side-fallback-models": { key: "serverSideFallbackModels", set: "catalog", shape: "array" },
357
+ /**
358
+ * Anthropic model ids a refusal's `fallback_credit_token` may be redeemed
359
+ * on (the refused model's permitted fallback targets). Unordered; a retry
360
+ * on any other model cannot redeem the credit.
361
+ */
362
+ "fallback-credit-targets": { key: "fallbackCreditTargets", set: "catalog", shape: "array" },
338
363
  priority: { key: "priority", set: "catalog", shape: "scalar" },
339
364
  "service-tier-cost": { key: "serviceTierCost", set: "catalog", shape: "object" },
340
365
  "time-based-cost": { key: "timeBased", set: "catalog", shape: "object" },
@@ -0,0 +1,13 @@
1
+ import type { Model } from "../types";
2
+ import { resolveCatalogPolicy } from "./catalog-policy";
3
+
4
+ /**
5
+ * Model ids on which a refusal's Anthropic fallback-credit token may be
6
+ * redeemed, authored on the `fallback-credit-targets` catalog axis. Empty when
7
+ * no rule assigns targets (the model cannot redeem credit on any fallback).
8
+ */
9
+ export function fallbackCreditTargets(model: Model): readonly string[] {
10
+ const value = resolveCatalogPolicy(model).fallbackCreditTargets;
11
+ if (!Array.isArray(value)) return [];
12
+ return value.filter((entry): entry is string => typeof entry === "string");
13
+ }
@@ -1,6 +1,14 @@
1
1
  import type { Model } from "../types";
2
2
  import { resolveCatalogPolicy } from "./catalog-policy";
3
3
 
4
+ /**
5
+ * Whether the host truncates generation at the context window rather than
6
+ * rejecting prompt + output cap overflow; the output fitter skips these models.
7
+ */
8
+ export function stopsOutputAtContextWindow(model: Model): boolean {
9
+ return resolveCatalogPolicy(model).stopsOutputAtContextWindow === true;
10
+ }
11
+
4
12
  /** Whether discovery and transport policy allow preserving a caller's output cap. */
5
13
  export function supportsOutputTokenLimit(model: Model): boolean {
6
14
  const policy = resolveCatalogPolicy(model);
@@ -726,6 +726,7 @@ function resolveOpenAIResponsesPolicy(
726
726
  supportsReasoningSummary: !isXaiHost,
727
727
  supportsAllTurnsReasoningContext: false,
728
728
  supportsConfigurationUpdate: false,
729
+ supportsSteering: false,
729
730
  requiresReasoningOffJuiceInstruction: false,
730
731
  stripImageInput: false,
731
732
  thinkingLoopGuard: undefined,
@@ -832,6 +833,7 @@ function pickResponsesOnly(compat: ResolvedOpenAIResponsesCompat): ResponsesOnly
832
833
  supportsObfuscationOptOut: compat.supportsObfuscationOptOut,
833
834
  supportsAllTurnsReasoningContext: compat.supportsAllTurnsReasoningContext,
834
835
  supportsConfigurationUpdate: compat.supportsConfigurationUpdate,
836
+ supportsSteering: compat.supportsSteering,
835
837
  officialEndpoint: compat.officialEndpoint,
836
838
  harmonyLeakMitigation: compat.harmonyLeakMitigation,
837
839
  cacheControlFormat: compat.cacheControlFormat,
@@ -36,6 +36,31 @@ class "anthropic" {
36
36
  supports-server-compaction #true
37
37
  }
38
38
  }
39
+ // Sonnet 4.5 and newer end generation with `model_context_window_exceeded`
40
+ // when prompt + max_tokens overruns the window, instead of a 400, so the
41
+ // full output cap can be requested without sizing the prompt. Verified for
42
+ // the Claude API only:
43
+ // https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#model-context-window-exceeded
44
+ on "anthropic" {
45
+ revision ">=4.5" {
46
+ stops-output-at-context-window #true
47
+ }
48
+ }
49
+ // Opus 5.5 rejects forced tool selection the way Fable/Mythos do — a
50
+ // `tool_choice` of `tool` or `any` fails the request with 400
51
+ // `invalid_request_error`: `tool_choice: type "tool" and "any" are not
52
+ // supported for this model`. The transport downgrades the selector to
53
+ // `auto` so the tool stays offered instead of the turn dying.
54
+ //
55
+ // Upper-bounded on purpose: separator-collapsed ids parse their revision
56
+ // as a whole number (`claude-opus-45` is Opus 4.5, revision 45), so an
57
+ // open `>=5.5` would silently catch them, and a later Opus generation has
58
+ // to be re-verified against the API before it inherits the restriction.
59
+ family "opus" {
60
+ revision ">=5.5 <6" {
61
+ supports-forced-tool-choice #false
62
+ }
63
+ }
39
64
  on "anthropic" "cloudflare-ai-gateway" "google-vertex" {
40
65
  family "fable" {
41
66
  revision ">=5" {
@@ -37,8 +37,11 @@ class "openai" {
37
37
  revision "=5.6" {
38
38
  delegation-bias "gated"
39
39
  }
40
+ // GPT-6 accepts `response.steer` over the Responses WebSocket: user input
41
+ // joins the in-flight response instead of waiting for the next request.
40
42
  revision ">=6" {
41
43
  delegation-bias "restrained"
44
+ supports-steering #true
42
45
  }
43
46
  // GPT-6 Astra changes reasoning effort mid-conversation through a
44
47
  // `configuration_update` input item so the request-level effort (and the
@@ -58,6 +58,21 @@ provider "anthropic" {
58
58
  revision ">=3.7 <4.6" {
59
59
  thinking-efforts "minimal" "low" "medium" "high" "xhigh"
60
60
  }
61
+ // Server-side refusal fallback chain (opt-in via
62
+ // `providers.anthropic.serverSideFallback`). Targets must be in the
63
+ // model's `allowed_fallback_models` on GET /v1/models/{id}; Fable 5 and
64
+ // 5.1 publish ["claude-opus-4-8", "claude-opus-5"] (2026-09-24).
65
+ // `claude-opus-5-5` is rejected with a 400 (#13059).
66
+ family "fable" {
67
+ server-side-fallback-models "claude-opus-5"
68
+ // Fallback-credit redemption targets: the refused model's permitted
69
+ // fallback targets. Fable 5 and 5.1 → Opus 4.8 and Opus 5
70
+ // (https://platform.claude.com/docs/en/build-with-claude/fallback-credit).
71
+ fallback-credit-targets "claude-opus-4-8" "claude-opus-5"
72
+ }
73
+ family "mythos" {
74
+ server-side-fallback-models "claude-opus-5"
75
+ }
61
76
  }
62
77
  // residue: taxonomy ranks and exact globs do not isolate these models.
63
78
  models "*20240229" "claude-3-7-sonnet-20250219" {
@@ -37,7 +37,7 @@ provider "yolo-auto" {
37
37
  cost input=0 output=0 cache-read=0 cache-write=0
38
38
  limits context=262144 max-tokens=131072
39
39
  thinking-mode "effort"
40
- thinking-efforts "minimal" "low" "medium" "high"
40
+ thinking-efforts "minimal" "low" "medium" "high" "xhigh"
41
41
  supports-developer-role #false
42
42
  supports-store #false
43
43
  supports-reasoning-effort #true
@@ -50,7 +50,7 @@ provider "yolo-auto" {
50
50
  cost input=0 output=0 cache-read=0 cache-write=0
51
51
  limits context=262144 max-tokens=131072
52
52
  thinking-mode "effort"
53
- thinking-efforts "minimal" "low" "medium" "high"
53
+ thinking-efforts "minimal" "low" "medium" "high" "xhigh"
54
54
  supports-developer-role #false
55
55
  supports-store #false
56
56
  supports-reasoning-effort #true
@@ -61,6 +61,12 @@ provider "yolo-auto" {
61
61
 
62
62
  supports-developer-role #false
63
63
  supports-store #false
64
+ // Live /v1/models advertises `thinking: minimal..xhigh` for the Qwen3.8
65
+ // rows; the cascade rule carries it into the regenerated bundle, whose
66
+ // thinking re-bake ignores seed-level ladders.
67
+ models "qwen3.8-flash" "yolo" "qwen3.8-27b" {
68
+ thinking-efforts "minimal" "low" "medium" "high" "xhigh"
69
+ }
64
70
  models "deepseek-flash-v4" {
65
71
  disable-reasoning-on-tool-choice #true
66
72
  max-tokens-field "max_completion_tokens"