@oh-my-pi/pi-catalog 17.3.4 → 17.3.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 CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [17.3.5] - 2026-08-16
6
+
7
+ ### Added
8
+
9
+ - Added support for GLM-5.3 on the z.AI provider, featuring a unified low/high/max reasoning-effort ladder across all hosts, mandatory thinking mode, 1M context, and default-model status for the z.AI provider.
10
+
11
+ ### Changed
12
+
13
+ - Switched the paid xAI provider (xai / XAI_API_KEY) from Chat Completions to the OpenAI Responses API, aligning it with SuperGrok (xai-oauth) for prompt-cache affinity, reasoning-effort handling, and encrypted-reasoning replay.
14
+ - Changed the paid xAI (XAI_API_KEY) default model to grok-4.5.
15
+ - Changed the SuperGrok (xai-oauth) default model to grok-4.5.
16
+ - Improved reasoning continuity for xAI models by requesting and replaying encrypted reasoning content across multi-turn Responses API calls.
17
+
18
+ ### Fixed
19
+
20
+ - Fixed Codex Daybreak Blue and Red model discovery reporting zero token prices, which incorrectly labeled the models as free in the model picker.
21
+ - Fixed Baseten's moonshotai/Kimi-K3 catalog metadata so its low/high/max thinking levels are available.
22
+ - Fixed opencode-go/deepseek-v4-flash Responses requests sending forced named tool_choice selectors that are rejected while thinking mode is active.
23
+
5
24
  ## [17.3.4] - 2026-08-14
6
25
 
7
26
  ### Added
@@ -1,4 +1,6 @@
1
1
  import type { ModelSpec, OpenAICompat, ResolvedOpenAICompat, ResolvedOpenAIResponsesCompat, ResolvedOpenRouterCompat } from "../types.js";
2
+ /** Wire effort remap for first-party xAI Responses. */
3
+ export declare function xaiResponsesReasoningEffortMap(modelId: string): NonNullable<OpenAICompat["reasoningEffortMap"]>;
2
4
  /**
3
5
  * Build the resolved chat-completions compat record for a model spec.
4
6
  * Provider takes precedence over URL-based detection since it's explicitly configured.
@@ -75,7 +75,7 @@ export declare const KNOWN_HOSTS: {
75
75
  readonly urlMarkers: readonly ["xiaomimimo.com"];
76
76
  };
77
77
  readonly xai: {
78
- readonly providers: readonly ["xai"];
78
+ readonly providers: readonly ["xai", "xai-oauth"];
79
79
  readonly urlMarkers: readonly ["api.x.ai"];
80
80
  };
81
81
  readonly mistral: {
@@ -55,6 +55,20 @@ export declare const isGrokModelId: (modelId: string) => boolean;
55
55
  * param, so callers must omit reasoning effort for them.
56
56
  */
57
57
  export declare const isGrokReasoningEffortCapable: (modelId: string) => boolean;
58
+ /**
59
+ * `grok-4.20-multi-agent*` uses `reasoning.effort` to pick agent count
60
+ * (`xhigh` is the 16-agent mode). Other first-party Grok effort SKUs stay on
61
+ * `low|medium|high` unless {@link isGrokXHighEffortCapable} (currently
62
+ * `grok-4.6*` plus multi-agent).
63
+ * https://docs.x.ai/developers/model-capabilities/text/reasoning
64
+ */
65
+ export declare const isGrokMultiAgentModelId: (modelId: string) => boolean;
66
+ /**
67
+ * First-party Grok SKUs whose Responses wire accepts `reasoning.effort: "xhigh"`.
68
+ * `grok-4.6*` documents xhigh as a reasoning depth; multi-agent uses it as
69
+ * 16-agent mode. `grok-4.5` / `grok-4.3` / `grok-3-mini` do not.
70
+ */
71
+ export declare const isGrokXHighEffortCapable: (modelId: string) => boolean;
58
72
  /**
59
73
  * MiniMax M2-generation family (M2, M2.1, M2.5, M2.7, including `-highspeed`/
60
74
  * `-lightning`/`-her`/`-turbo` variants, dotless aliases like `minimax-m21`,
@@ -118,6 +132,15 @@ export declare const isOpenAISamplingRestrictedModelId: (modelId: string) => boo
118
132
  export declare const isReasoningGlmModelId: (modelId: string) => boolean;
119
133
  /** GLM-5.2+ coding SKUs accept `reasoning_effort` in addition to binary thinking. */
120
134
  export declare const isGlm52ReasoningEffortModelId: (modelId: string) => boolean;
135
+ /**
136
+ * GLM-5.3+ coding SKUs. Unlike GLM-5.2 (whose reasoning_effort dialect is
137
+ * host-specific), GLM-5.3+ exposes a uniform wire-exact `low`/`high`/`max`
138
+ * ladder on every host, and thinking can no longer be disabled —
139
+ * `thinking.type` must always be `enabled`. Matching the family keeps future
140
+ * bumps (`glm-5.4`, `glm-6`, …) covered while excluding the vision (`…v`)
141
+ * shape and the non-reasoning `-flash`/`-flashx`/`-preview` variants.
142
+ */
143
+ export declare const isGlm53ReasoningEffortModelId: (modelId: string) => boolean;
121
144
  /** GLM vision SKUs — the `v` that attaches to the version (`glm-4v`, `glm-4.5v`). */
122
145
  export declare const isGlmVisionModelId: (modelId: string) => boolean;
123
146
  /**
@@ -0,0 +1,17 @@
1
+ import type { TokenCost } from "./types.js";
2
+ /** Standard GPT-5.6 Sol rates used by the Daybreak Blue aliases. */
3
+ export declare const OPENAI_GPT_56_SOL_STANDARD_COST: {
4
+ readonly input: 5;
5
+ readonly output: 30;
6
+ readonly cacheRead: 0.5;
7
+ readonly cacheWrite: 6.25;
8
+ };
9
+ /** Standard GPT-5.6 Cyber rates used by the Daybreak Red aliases. */
10
+ export declare const OPENAI_GPT_56_CYBER_STANDARD_COST: {
11
+ readonly input: 12.5;
12
+ readonly output: 75;
13
+ readonly cacheRead: 1.25;
14
+ readonly cacheWrite: 15.625;
15
+ };
16
+ /** Resolve standard rates for Codex-prefixed Daybreak aliases. */
17
+ export declare function resolveOpenAIDaybreakStandardCost(modelId: string): TokenCost | undefined;
@@ -433,12 +433,12 @@ export declare const CATALOG_PROVIDERS: readonly [{
433
433
  };
434
434
  }, {
435
435
  readonly id: "xai";
436
- readonly defaultModel: "grok-4-fast-non-reasoning";
436
+ readonly defaultModel: "grok-4.5";
437
437
  readonly envVars: readonly ["XAI_API_KEY"];
438
- readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
438
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-responses", unknown>;
439
439
  }, {
440
440
  readonly id: "xai-oauth";
441
- readonly defaultModel: "grok-4.3";
441
+ readonly defaultModel: "grok-4.5";
442
442
  readonly envVars: readonly ["XAI_OAUTH_TOKEN", "XAI_API_KEY"];
443
443
  readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-responses", unknown>;
444
444
  readonly catalogDiscovery: {
@@ -470,7 +470,7 @@ export declare const CATALOG_PROVIDERS: readonly [{
470
470
  readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
471
471
  }, {
472
472
  readonly id: "zai";
473
- readonly defaultModel: "glm-5.2";
473
+ readonly defaultModel: "glm-5.3";
474
474
  readonly envVars: readonly ["ZAI_API_KEY"];
475
475
  readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"anthropic-messages", unknown>;
476
476
  readonly catalogDiscovery: {
@@ -61,6 +61,7 @@ export interface UmansModelManagerConfig {
61
61
  fetch?: FetchImpl;
62
62
  }
63
63
  export declare function umansModelManagerOptions(config?: UmansModelManagerConfig): ModelManagerOptions<"anthropic-messages">;
64
+ /** GPT-5.6 rates applied when a first-party request exceeds 272K input tokens. */
64
65
  export declare const OPENAI_GPT_56_LONG_CONTEXT_COSTS: {
65
66
  readonly luna: {
66
67
  readonly inputThreshold: 272000;
@@ -165,7 +166,7 @@ export interface XaiModelManagerConfig {
165
166
  baseUrl?: string;
166
167
  fetch?: FetchImpl;
167
168
  }
168
- export declare function xaiModelManagerOptions(config?: XaiModelManagerConfig): ModelManagerOptions<"openai-completions">;
169
+ export declare function xaiModelManagerOptions(config?: XaiModelManagerConfig): ModelManagerOptions<"openai-responses">;
169
170
  export interface XaiOAuthModelManagerConfig {
170
171
  apiKey?: string;
171
172
  baseUrl?: string;
@@ -194,6 +195,21 @@ interface XAICuratedModel {
194
195
  input?: ("text" | "image")[];
195
196
  }
196
197
  export declare const XAI_OAUTH_CURATED_MODELS: readonly XAICuratedModel[];
198
+ /**
199
+ * Bake first-party xAI Responses effort-dial metadata onto a catalog spec.
200
+ *
201
+ * models.dev marks many Grok SKUs as reasoners and the thinking rebake would
202
+ * otherwise emit a default `minimal/low/medium/high` dial. api.x.ai only
203
+ * accepts `reasoning.effort` for {@link isGrokReasoningEffortCapable} ids —
204
+ * off-allowlist reasoners (`grok-code-fast-1`, `grok-build-0.1`,
205
+ * `grok-4.20-0309-reasoning`, …) 400 if the param is sent. SuperGrok
206
+ * (`xai-oauth`) already curates this via {@link mergeCuratedIntoModel}; paid
207
+ * `xai` rows come from stencil.so and need the same wire facts in the exported
208
+ * `models.json` so direct catalog readers do not present an unsupported dial.
209
+ *
210
+ * Explicit `compat.supportsReasoningEffort` / `omitReasoningEffort` win.
211
+ */
212
+ export declare function applyXaiResponsesThinkingPolicy(model: ModelSpec<"openai-responses">): ModelSpec<"openai-responses">;
197
213
  /**
198
214
  * Render `XAI_OAUTH_CURATED_MODELS` as full `ModelSpec<"openai-responses">` entries.
199
215
  *
@@ -324,6 +324,13 @@ export interface OpenAICompat {
324
324
  * model id. Default: true. Issue #5606.
325
325
  */
326
326
  supportsSamplingParams?: boolean;
327
+ /**
328
+ * Whether presence/frequency penalties and stop sequences may be sent.
329
+ * First-party xAI `/v1/responses` rejects penalty fields for every model.
330
+ * xAI reasoning models also reject them (and `stop`) on chat completions.
331
+ * When unset, auto-detected. Default: true.
332
+ */
333
+ supportsPenaltyAndStopParams?: boolean;
327
334
  /** Always send a max-token field when the caller did not provide one. Default: auto-detected (Kimi-family models derive TPM limits from max_tokens). */
328
335
  alwaysSendMaxTokens?: boolean;
329
336
  /** Whether Responses-API tool-call/result history must be strictly paired. Default: auto-detected (Azure OpenAI, GitHub Copilot). */
@@ -532,6 +539,7 @@ export interface ResolvedOpenAISharedCompat {
532
539
  reasoningEffortMap: Partial<Record<Effort, string>>;
533
540
  supportsReasoningParams: boolean;
534
541
  supportsSamplingParams: boolean;
542
+ supportsPenaltyAndStopParams: boolean;
535
543
  thinkingFormat: OpenAIReasoningFormat;
536
544
  /** Kimi Code transport selected by live per-model protocol metadata. */
537
545
  kimiApiFormat?: OpenAICompat["kimiApiFormat"];
@@ -587,7 +595,7 @@ export interface ResolvedOpenAISharedCompat {
587
595
  * `buildModel`; request handlers read fields and never detect, resolve, or
588
596
  * allocate.
589
597
  */
590
- export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsSamplingParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "whenThinking">> & {
598
+ export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsSamplingParams" | "supportsPenaltyAndStopParams" | "thinkingFormat" | "kimiApiFormat" | "reasoningDisableMode" | "omitReasoningEffort" | "includeEncryptedReasoning" | "filterReasoningHistory" | "disableReasoningOnForcedToolChoice" | "disableReasoningOnToolChoice" | "supportsToolChoice" | "supportsForcedToolChoice" | "supportsNamedToolChoice" | "reasoningContentField" | "requiresReasoningContentForToolCalls" | "requiresReasoningContentForAllAssistantTurns" | "allowsSyntheticReasoningContentForToolCalls" | "replayReasoningContent" | "qwenPreserveThinking" | "requiresThinkingAsText" | "requiresMistralToolIds" | "requiresToolResultName" | "requiresAssistantAfterToolResult" | "requiresAssistantContentForToolCalls" | "stripDeepseekSpecialTokens" | "streamMarkupHealingPattern" | "reasoningDeltasMayBeCumulative" | "emptyLengthFinishIsContextError" | "usesOpenAIToolCallIdLimit" | "promptCacheSessionHeader" | "supportsPromptCacheBreakpoints" | "promptCacheBreakpointTtl" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamFirstEventTimeoutMs" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "whenThinking">> & {
591
599
  vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
592
600
  extraBody?: OpenAICompat["extraBody"];
593
601
  cacheControlFormat?: OpenAICompat["cacheControlFormat"];
@@ -606,6 +614,12 @@ export interface ResolvedOpenAIResponsesCompat extends ResolvedOpenAISharedCompa
606
614
  strictResponsesPairing: boolean;
607
615
  supportsImageDetailOriginal: boolean;
608
616
  supportsObfuscationOptOut: boolean;
617
+ /**
618
+ * Whether `reasoning.summary` may be sent. First-party xAI `/v1/responses`
619
+ * rejects the field; handlers pass `null` so the wire omits it instead of
620
+ * filling `"auto"`.
621
+ */
622
+ supportsReasoningSummary: boolean;
609
623
  streamIdleTimeoutMs?: number;
610
624
  vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
611
625
  /** The model sits behind Vercel AI Gateway's Responses endpoint. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "17.3.4",
4
+ "version": "17.3.5",
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": "Can Boluk",
@@ -35,11 +35,11 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@bufbuild/protobuf": "^2.12.1",
38
- "@oh-my-pi/omptype": "17.3.4",
39
- "@oh-my-pi/pi-utils": "17.3.4"
38
+ "@oh-my-pi/omptype": "17.3.5",
39
+ "@oh-my-pi/pi-utils": "17.3.5"
40
40
  },
41
41
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "17.3.4",
42
+ "@oh-my-pi/pi-ai": "17.3.5",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
@@ -16,6 +16,7 @@ import {
16
16
  isDeepseekModelIdOrName,
17
17
  isGlm52ReasoningEffortModelId,
18
18
  isGrokReasoningEffortCapable,
19
+ isGrokXHighEffortCapable,
19
20
  isKimiK3ModelId,
20
21
  isKimiK26ModelId,
21
22
  isKimiModelId,
@@ -177,6 +178,22 @@ const MIMO_REASONING_EFFORT_MAP: NonNullable<OpenAICompat["reasoningEffortMap"]>
177
178
  xhigh: "high",
178
179
  };
179
180
 
181
+ /** Shared `minimal → low` clamp. xhigh-capable Grok keeps `xhigh` unmapped. */
182
+ const XAI_RESPONSES_MINIMAL_EFFORT_MAP: NonNullable<OpenAICompat["reasoningEffortMap"]> = {
183
+ minimal: "low",
184
+ };
185
+ /** Grok 4.5 / 4.3 / 3-mini: leftover `xhigh`/`max` clamp to `high`. */
186
+ const XAI_RESPONSES_CLAMPED_EFFORT_MAP: NonNullable<OpenAICompat["reasoningEffortMap"]> = {
187
+ minimal: "low",
188
+ xhigh: "high",
189
+ max: "high",
190
+ };
191
+
192
+ /** Wire effort remap for first-party xAI Responses. */
193
+ export function xaiResponsesReasoningEffortMap(modelId: string): NonNullable<OpenAICompat["reasoningEffortMap"]> {
194
+ return isGrokXHighEffortCapable(modelId) ? XAI_RESPONSES_MINIMAL_EFFORT_MAP : XAI_RESPONSES_CLAMPED_EFFORT_MAP;
195
+ }
196
+
180
197
  function mergeModelReasoningEffortMap(
181
198
  compat: ResolvedOpenAISharedCompat,
182
199
  modelId: string,
@@ -471,6 +488,8 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
471
488
  // OpenAI proprietary reasoning models (o-series, gpt-5+) reject explicit
472
489
  // temperature/top_p/… with a 400 on every serving host (#5606).
473
490
  supportsSamplingParams: !isOpenAISamplingRestrictedModelId(spec.id),
491
+ // xAI reasoning models 400 on presence/frequency penalties and stop.
492
+ supportsPenaltyAndStopParams: !(isGrok && Boolean(spec.reasoning)),
474
493
  reasoningEffortMap: {},
475
494
  supportsUsageInStreaming: !isCerebras,
476
495
  // Kimi (including via OpenRouter and Fireworks router-form IDs such as
@@ -684,34 +703,46 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
684
703
  const isLocalServingBackend =
685
704
  (!PROXY_OPENAI_COMPAT_PROVIDERS.has(spec.provider) && LOCAL_OPENAI_COMPAT_PROVIDERS.has(spec.provider)) ||
686
705
  hasLocalLoopbackBaseUrl(baseUrl);
706
+ const isXaiHost = modelMatchesHost({ provider: spec.provider, baseUrl }, "xai");
687
707
 
688
708
  const compat: ResolvedOpenAIResponsesCompat = {
689
709
  supportsDeveloperRole: isAzure || isOpenAIUrl || hostMatchesUrl(baseUrl, "githubCopilot"),
690
710
  supportsStrictMode: isAzure || detectStrictModeSupport(spec.provider, baseUrl),
691
- supportsReasoningEffort: spec.provider !== "xai-oauth" || isGrokReasoningEffortCapable(id),
711
+ // Paid `xai` and SuperGrok `xai-oauth` share api.x.ai `/v1/responses`.
712
+ // Only the Grok effort-capable allowlist accepts `reasoning.effort`;
713
+ // other reasoners (grok-build, grok-code-fast-1, …) 400 if it is sent.
714
+ supportsReasoningEffort: !isXaiHost || isGrokReasoningEffortCapable(id),
692
715
  supportsLongPromptCacheRetention: isOpenAIUrl,
693
716
  supportsPromptCacheBreakpoints,
694
717
  promptCacheBreakpointTtl: supportsPromptCacheBreakpoints ? "30m" : undefined,
695
718
  // Azure OpenAI and GitHub Copilot Responses paths require tool results
696
719
  // to strictly match prior tool calls when building Responses inputs.
697
720
  strictResponsesPairing: isAzure || spec.provider === "github-copilot",
698
- // GitHub Copilot and xAI OAuth reject `detail: "original"` (400 / 422).
699
- // Every other host preserves native-resolution frames (snapcompact relies
700
- // on `original`). Detect Copilot by provider id or base-URL host so a
701
- // model pointed at the Copilot host under a different provider id still
702
- // clamps; xai-oauth is provider-id only (same host family as paid `xai`).
721
+ // GitHub Copilot and first-party xAI `/v1/responses` reject
722
+ // `detail: "original"` (400 / 422). Every other host preserves
723
+ // native-resolution frames (snapcompact relies on `original`). Detect
724
+ // Copilot by provider id or base-URL host so a model pointed at the
725
+ // Copilot host under a different provider id still clamps.
703
726
  supportsImageDetailOriginal:
704
- spec.provider !== "xai-oauth" && !modelMatchesHost({ provider: spec.provider, baseUrl }, "githubCopilot"),
705
- reasoningEffortMap: {},
727
+ !isXaiHost && !modelMatchesHost({ provider: spec.provider, baseUrl }, "githubCopilot"),
728
+ // api.x.ai rejects `reasoning.summary` (SuperGrok and paid key alike).
729
+ supportsReasoningSummary: !isXaiHost,
730
+ reasoningEffortMap: isXaiHost ? { ...xaiResponsesReasoningEffortMap(id) } : {},
706
731
  supportsReasoningParams: true,
707
732
  // OpenAI proprietary reasoning models (o-series, gpt-5+) reject explicit
708
733
  // temperature/top_p/… with a 400 on every serving host (#5606).
709
734
  supportsSamplingParams: !isOpenAISamplingRestrictedModelId(id),
735
+ // xAI `/v1/responses` rejects presence/frequency penalties for every
736
+ // model, not only reasoners (https://docs.x.ai/developers/rest-api-reference/inference/chat).
737
+ supportsPenaltyAndStopParams: !isXaiHost,
710
738
  thinkingFormat,
711
739
  reasoningDisableMode: resolveReasoningDisableMode(thinkingFormat),
712
740
  omitReasoningEffort: false,
713
- includeEncryptedReasoning: spec.provider !== "xai-oauth",
714
- filterReasoningHistory: spec.provider === "xai-oauth" || (isOpenRouter && isAnthropicModel),
741
+ // Ask xAI `/v1/responses` for `reasoning.encrypted_content` and replay
742
+ // those items on later turns. OpenRouter Anthropic still filters
743
+ // reasoning wrappers independently.
744
+ includeEncryptedReasoning: true,
745
+ filterReasoningHistory: isOpenRouter && isAnthropicModel,
715
746
  disableReasoningOnForcedToolChoice: isKimiModel,
716
747
  disableReasoningOnToolChoice: isDeepseekFamily && reasoningCapable && !isOpenRouter,
717
748
  supportsToolChoice: true,
@@ -752,13 +783,24 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
752
783
  MINIMAX_PROVIDER_OR_ID_PATTERN.test(spec.provider) || (id ? MINIMAX_PROVIDER_OR_ID_PATTERN.test(id) : false),
753
784
  emptyLengthFinishIsContextError: spec.provider === "ollama",
754
785
  usesOpenAIToolCallIdLimit: spec.provider === "openai",
755
- promptCacheSessionHeader: spec.provider === "xai-oauth" ? "x-grok-conv-id" : undefined,
786
+ promptCacheSessionHeader: isXaiHost ? "x-grok-conv-id" : undefined,
756
787
  streamFirstEventTimeoutMs: isLocalServingBackend ? 0 : spec.compat?.streamFirstEventTimeoutMs,
757
788
  streamIdleTimeoutMs: isLocalServingBackend
758
789
  ? LOCAL_OPENAI_COMPAT_STREAM_IDLE_TIMEOUT_MS
759
790
  : spec.compat?.streamIdleTimeoutMs,
760
791
  };
761
792
  applyCompatOverrides(compat, spec.compat);
793
+ if (isXaiHost) {
794
+ const canonical = xaiResponsesReasoningEffortMap(id);
795
+ compat.reasoningEffortMap = { ...compat.reasoningEffortMap, ...canonical };
796
+ // xhigh-capable Grok advertises unmapped `xhigh`; drop a stale clamp
797
+ // from previous snapshots so 4.6 / 16-agent mode is not rewritten to `high`.
798
+ for (const key of ["xhigh", "max"] as const) {
799
+ if (!(key in canonical)) {
800
+ delete compat.reasoningEffortMap[key];
801
+ }
802
+ }
803
+ }
762
804
  if (spec.compat?.reasoningDisableMode === undefined) {
763
805
  compat.reasoningDisableMode = resolveReasoningDisableMode(compat.thinkingFormat);
764
806
  }
@@ -776,6 +818,7 @@ function pickResponsesOnly(compat: ResolvedOpenAIResponsesCompat): ResponsesOnly
776
818
  strictResponsesPairing: compat.strictResponsesPairing,
777
819
  supportsImageDetailOriginal: compat.supportsImageDetailOriginal,
778
820
  supportsObfuscationOptOut: compat.supportsObfuscationOptOut,
821
+ supportsReasoningSummary: compat.supportsReasoningSummary,
779
822
  isVercelGatewayHost: compat.isVercelGatewayHost,
780
823
  } satisfies ResponsesOnlyCompat;
781
824
  }
@@ -1,5 +1,6 @@
1
1
  import { type } from "@oh-my-pi/omptype";
2
2
  import { parseKnownModel, semverEqual } from "../identity/classify";
3
+ import { resolveOpenAIDaybreakStandardCost } from "../openai-pricing";
3
4
  import type { FetchImpl, ModelSpec } from "../types";
4
5
  import { discoveryFetch } from "../utils";
5
6
  import { CODEX_BASE_URL, CODEX_CLIENT_VERSION, OPENAI_HEADER_VALUES, OPENAI_HEADERS } from "../wire/codex";
@@ -237,6 +238,7 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
237
238
  const preferWebsockets = toBoolean(payload.prefer_websockets) === true;
238
239
  const useResponsesLite = toBoolean(payload.use_responses_lite) === true;
239
240
  const priority = toFiniteNumber(payload.priority) ?? Number.MAX_SAFE_INTEGER;
241
+ const daybreakCost = resolveOpenAIDaybreakStandardCost(slug);
240
242
 
241
243
  return {
242
244
  priority,
@@ -248,7 +250,7 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
248
250
  baseUrl,
249
251
  reasoning,
250
252
  input,
251
- cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
253
+ cost: daybreakCost ? { ...daybreakCost } : { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
252
254
  remoteCompaction: CODEX_REMOTE_COMPACTION,
253
255
  contextWindow,
254
256
  maxTokens,
package/src/hosts.ts CHANGED
@@ -47,7 +47,7 @@ export const KNOWN_HOSTS = {
47
47
  },
48
48
  umans: { providers: ["umans"], urlMarkers: ["api.code.umans.ai"] },
49
49
  xiaomi: { providers: ["xiaomi"], providerPrefixes: ["xiaomi-token-plan-"], urlMarkers: ["xiaomimimo.com"] },
50
- xai: { providers: ["xai"], urlMarkers: ["api.x.ai"] },
50
+ xai: { providers: ["xai", "xai-oauth"], urlMarkers: ["api.x.ai"] },
51
51
  mistral: { providers: ["mistral"], urlMarkers: ["mistral.ai"] },
52
52
  together: { providers: ["together"], urlMarkers: ["api.together.xyz"] },
53
53
  baseten: { providers: ["baseten"], urlMarkers: ["baseten.co"] },
@@ -110,7 +110,13 @@ export const isGrokModelId = memo((modelId: string): boolean => {
110
110
  return /(?:^|[./_-])grok(?:[-.]|$)/i.test(modelId);
111
111
  });
112
112
 
113
- const GROK_EFFORT_CAPABLE_PREFIXES = ["grok-3-mini", "grok-4.20-multi-agent", "grok-4.3", "grok-4.5"] as const;
113
+ const GROK_EFFORT_CAPABLE_PREFIXES = [
114
+ "grok-3-mini",
115
+ "grok-4.20-multi-agent",
116
+ "grok-4.3",
117
+ "grok-4.5",
118
+ "grok-4.6",
119
+ ] as const;
114
120
 
115
121
  /**
116
122
  * Grok SKUs that expose the wire `reasoning.effort` dial. Other Grok reasoners
@@ -123,6 +129,27 @@ export const isGrokReasoningEffortCapable = memo((modelId: string): boolean => {
123
129
  return GROK_EFFORT_CAPABLE_PREFIXES.some(prefix => bare.startsWith(prefix));
124
130
  });
125
131
 
132
+ /**
133
+ * `grok-4.20-multi-agent*` uses `reasoning.effort` to pick agent count
134
+ * (`xhigh` is the 16-agent mode). Other first-party Grok effort SKUs stay on
135
+ * `low|medium|high` unless {@link isGrokXHighEffortCapable} (currently
136
+ * `grok-4.6*` plus multi-agent).
137
+ * https://docs.x.ai/developers/model-capabilities/text/reasoning
138
+ */
139
+ export const isGrokMultiAgentModelId = memo((modelId: string): boolean => {
140
+ return bareModelId(modelId).trim().toLowerCase().startsWith("grok-4.20-multi-agent");
141
+ });
142
+
143
+ /**
144
+ * First-party Grok SKUs whose Responses wire accepts `reasoning.effort: "xhigh"`.
145
+ * `grok-4.6*` documents xhigh as a reasoning depth; multi-agent uses it as
146
+ * 16-agent mode. `grok-4.5` / `grok-4.3` / `grok-3-mini` do not.
147
+ */
148
+ export const isGrokXHighEffortCapable = memo((modelId: string): boolean => {
149
+ if (isGrokMultiAgentModelId(modelId)) return true;
150
+ return bareModelId(modelId).trim().toLowerCase().startsWith("grok-4.6");
151
+ });
152
+
126
153
  /**
127
154
  * MiniMax M2-generation family (M2, M2.1, M2.5, M2.7, including `-highspeed`/
128
155
  * `-lightning`/`-her`/`-turbo` variants, dotless aliases like `minimax-m21`,
@@ -251,6 +278,25 @@ export const isGlm52ReasoningEffortModelId = memo((modelId: string): boolean =>
251
278
  return semverGte(glm.version, "5.2");
252
279
  });
253
280
 
281
+ /**
282
+ * GLM-5.3+ coding SKUs. Unlike GLM-5.2 (whose reasoning_effort dialect is
283
+ * host-specific), GLM-5.3+ exposes a uniform wire-exact `low`/`high`/`max`
284
+ * ladder on every host, and thinking can no longer be disabled —
285
+ * `thinking.type` must always be `enabled`. Matching the family keeps future
286
+ * bumps (`glm-5.4`, `glm-6`, …) covered while excluding the vision (`…v`)
287
+ * shape and the non-reasoning `-flash`/`-flashx`/`-preview` variants.
288
+ */
289
+ export const isGlm53ReasoningEffortModelId = memo((modelId: string): boolean => {
290
+ const glm = parseGlmModel(bareModelId(modelId));
291
+ if (!glm || glm.vision) {
292
+ return false;
293
+ }
294
+ if (glm.variant !== "base" && glm.variant !== "air" && glm.variant !== "turbo") {
295
+ return false;
296
+ }
297
+ return semverGte(glm.version, "5.3");
298
+ });
299
+
254
300
  /** GLM vision SKUs — the `v` that attaches to the version (`glm-4v`, `glm-4.5v`). */
255
301
  export const isGlmVisionModelId = memo((modelId: string): boolean => {
256
302
  return parseGlmModel(bareModelId(modelId))?.vision === true;
@@ -26,6 +26,8 @@ import {
26
26
  isDeepseekModelIdOrName,
27
27
  isDeepseekV4FlashModelId,
28
28
  isGlm52ReasoningEffortModelId,
29
+ isGlm53ReasoningEffortModelId,
30
+ isGrokXHighEffortCapable,
29
31
  isKimiK3ModelId,
30
32
  isMimoModelIdOrName,
31
33
  isMinimaxM2FamilyModelId,
@@ -178,7 +180,8 @@ function fillThinkingWireDefaults<TApi extends Api>(
178
180
  (spec.api === "anthropic-messages" || spec.api === "bedrock-converse-stream") &&
179
181
  supportsAdaptiveThinkingDisplay(spec.id);
180
182
  const needsRequiresEffort = thinking.requiresEffort === undefined && impliesMandatoryReasoning(parsed, spec.id);
181
- const needsDefaultLevel = thinking.defaultLevel === undefined && isKimiK3ModelId(spec.id);
183
+ const needsDefaultLevel =
184
+ thinking.defaultLevel === undefined && (isKimiK3ModelId(spec.id) || isGlm53ReasoningEffortModelId(spec.id));
182
185
  if (!effortsChanged && !shouldReplaceEffortMap && !needsDisplay && !needsRequiresEffort && !needsDefaultLevel) {
183
186
  return thinking;
184
187
  }
@@ -216,7 +219,7 @@ export function deriveThinking<TApi extends Api>(spec: ModelSpec<TApi>, compat:
216
219
  mode: inferThinkingControlMode(spec, parsed),
217
220
  efforts,
218
221
  };
219
- if (isKimiK3ModelId(spec.id)) {
222
+ if (isKimiK3ModelId(spec.id) || isGlm53ReasoningEffortModelId(spec.id)) {
220
223
  config.defaultLevel = Effort.Max;
221
224
  }
222
225
  const effortMap = inferEffortMap(spec, compat, config.mode, config.efforts);
@@ -312,6 +315,13 @@ function getModelDefinedEfforts<TApi extends Api>(
312
315
  spec: ModelSpec<TApi>,
313
316
  compat: CompatOf<TApi>,
314
317
  ): readonly Effort[] | undefined {
318
+ if (isGlm53ReasoningEffortModelId(spec.id)) {
319
+ // GLM-5.3+ exposes a uniform wire-exact low/high/max ladder on every
320
+ // host — unlike GLM-5.2, whose reasoning_effort dialect is
321
+ // host-specific. Thinking can no longer be disabled (handled by
322
+ // impliesMandatoryReasoning), and the default effort is `max`.
323
+ return LOW_HIGH_MAX_REASONING_EFFORTS;
324
+ }
315
325
  if (isGlm52ReasoningEffortModelId(spec.id)) {
316
326
  // GLM-5.2's reasoning_effort dialect is host-specific (verified against
317
327
  // live endpoints):
@@ -395,6 +405,11 @@ function getModelDefinedEfforts<TApi extends Api>(
395
405
  // Baseten's gpt-oss router mirrors its GLM route: high/max only.
396
406
  return HIGH_MAX_REASONING_EFFORTS;
397
407
  }
408
+ // First-party Grok: `grok-4.6*` and `grok-4.20-multi-agent*` advertise
409
+ // `xhigh`. Other effort-capable SKUs stay on `minimal/low/medium/high`.
410
+ if (modelMatchesHost({ provider: spec.provider, baseUrl: spec.baseUrl ?? "" }, "xai")) {
411
+ return isGrokXHighEffortCapable(spec.id) ? DEFAULT_REASONING_EFFORTS_WITH_XHIGH : DEFAULT_REASONING_EFFORTS;
412
+ }
398
413
  return isOpenAICompatReasoningApi(spec.api) &&
399
414
  (isMinimaxM2FamilyModelId(spec.id) ||
400
415
  isOpenAIGptOssModelId(spec.id) ||
@@ -579,6 +594,9 @@ function impliesMandatoryReasoning(parsed: ParsedModel, modelId: string): boolea
579
594
  if (parsed.kind === "pro" && semverGte(parsed.version, "2.5")) return true;
580
595
  }
581
596
  if (isKimiK3ModelId(modelId)) return true;
597
+ // GLM-5.3+ no longer supports disabling thinking — thinking.type must
598
+ // always be "enabled". Floor thinking-off requests to the lowest effort.
599
+ if (isGlm53ReasoningEffortModelId(modelId)) return true;
582
600
  if (isMinimaxM2FamilyModelId(modelId)) return true;
583
601
  if (OPENAI_O_SERIES_RE.test(bareModelId(modelId))) return true;
584
602
  return findThinkingVariantToken(modelId) !== undefined;