@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 +19 -0
- package/dist/types/compat/openai.d.ts +2 -0
- package/dist/types/hosts.d.ts +1 -1
- package/dist/types/identity/family.d.ts +23 -0
- package/dist/types/openai-pricing.d.ts +17 -0
- package/dist/types/provider-models/descriptors.d.ts +4 -4
- package/dist/types/provider-models/openai-compat.d.ts +17 -1
- package/dist/types/types.d.ts +15 -1
- package/package.json +4 -4
- package/src/compat/openai.ts +54 -11
- package/src/discovery/codex.ts +3 -1
- package/src/hosts.ts +1 -1
- package/src/identity/family.ts +47 -1
- package/src/model-thinking.ts +20 -2
- package/src/models.json +2834 -810
- package/src/openai-pricing.ts +29 -0
- package/src/provider-models/descriptors.ts +3 -3
- package/src/provider-models/openai-compat.ts +103 -48
- package/src/types.ts +15 -0
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.
|
package/dist/types/hosts.d.ts
CHANGED
|
@@ -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
|
|
436
|
+
readonly defaultModel: "grok-4.5";
|
|
437
437
|
readonly envVars: readonly ["XAI_API_KEY"];
|
|
438
|
-
readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-
|
|
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.
|
|
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.
|
|
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-
|
|
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
|
*
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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
|
+
"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.
|
|
39
|
-
"@oh-my-pi/pi-utils": "17.3.
|
|
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.
|
|
42
|
+
"@oh-my-pi/pi-ai": "17.3.5",
|
|
43
43
|
"@types/bun": "^1.3.14"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
package/src/compat/openai.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
699
|
-
// Every other host preserves
|
|
700
|
-
// on `original`). Detect
|
|
701
|
-
//
|
|
702
|
-
//
|
|
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
|
-
|
|
705
|
-
|
|
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
|
-
|
|
714
|
-
|
|
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:
|
|
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
|
}
|
package/src/discovery/codex.ts
CHANGED
|
@@ -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"] },
|
package/src/identity/family.ts
CHANGED
|
@@ -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 = [
|
|
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;
|
package/src/model-thinking.ts
CHANGED
|
@@ -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 =
|
|
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;
|