@oh-my-pi/pi-catalog 17.0.0 → 17.0.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,46 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [17.0.2] - 2026-07-17
6
+
7
+ ### Changed
8
+
9
+ - Increased the maximum output tokens (maxTokens) from 32,768 to 65,536 for Kimi K2.7-Code models on Fireworks.
10
+
11
+ ### Fixed
12
+
13
+ - Fixed a regression where the context window for openai-codex GPT-5.6 models (Luna, Sol, Terra) incorrectly fell back to 272,000 instead of preserving its 372,000 capacity.
14
+ - Fixed Umans PAYG models incorrectly displaying as "Free" in /models by correctly sourcing their published per-token rates.
15
+ - Fixed native moonshot/kimi-k3 capabilities and pricing, ensuring it correctly reflects its official pricing, 1M context window, image input support, reasoning capabilities, and 128k output token limit.
16
+
17
+ ## [17.0.1] - 2026-07-16
18
+
19
+ ### Added
20
+
21
+ - Added GPT-5.6 Luna, Sol, and Terra entries for Amazon Bedrock, Azure, and Cloudflare
22
+ - Added KAT-Coder Air/Pro V2.5 entries across Kilo, OpenRouter, NanoGPT, and Vercel
23
+ - Added Inkling model entries for Baseten and Vercel AI Gateway
24
+ - Added Umans DeepSeek V4 Pro DSpark as an experimental model listing
25
+ - Added Claude Opus 4.7 Fast and 4.8 Fast on Vercel AI Gateway
26
+ - Added Workers AI GLM-5.2, Muse Spark 1.1, Stealth GPT-5.6 Sol, and nano-gpt-help entries
27
+
28
+ ### Changed
29
+
30
+ - Added image input and reasoning support to several existing Codeium and Kilo GPT-5.6 models
31
+ - Enabled image input and reasoning for Gemini Flash Latest and Grok 4.5
32
+ - Renamed many model labels for consistency, including Claude, Grok, DeepSeek, GLM, and Gemi­ni names
33
+ - Updated pricing for many existing models, including input, output, and cache cost values
34
+ - Updated context window and max token limits for many catalog models across providers
35
+
36
+ ### Fixed
37
+
38
+ - Fixed Z.AI (GLM) coding-plan token costs all showing as "Free" in `/models`: the `zai` provider descriptor sourced the models.dev `zai-coding-plan` key (all-$0 subscription rates) instead of the `zai` pay-as-you-go key, which carries the real per-token rates for the identical GLM ids ([#5598](https://github.com/can1357/oh-my-pi/issues/5598)).
39
+ - Fixed custom Anthropic endpoints receiving the first-party-only `eager_input_streaming` tool field by default ([#5572](https://github.com/can1357/oh-my-pi/issues/5572)).
40
+ - Added resolved OpenAI sampling-parameter compatibility metadata for o-series and GPT-5+ models.
41
+ - Fixed GitHub Copilot `mai-code-1-flash-picker` (and other `mai-*` models) to route through the `/responses` endpoint instead of `/chat/completions`, which rejected them with `400 unsupported_api_for_model` ([#5612](https://github.com/can1357/oh-my-pi/issues/5612)).
42
+ - Extended the reasoning `streamIdleTimeoutMs` floor (300s) to native Kimi K2.7 Code (`kimi-k2.7-code` / `kimi-k2.7-code-highspeed`), which previously fell through to the 120s default and aborted on long reasoning turns ([#4836](https://github.com/can1357/oh-my-pi/issues/4836)).
43
+ - Fixed GLM-5.x coding-plan streams via the OpenCode Go/Zen gateways (`opencode.ai/zen/…`) timing out with `OpenAI completions stream stalled while waiting for the next event` during slow plan-writing/reasoning phases. The 600s idle-timeout floor for GLM coding-plan SKUs was gated to the native Z.AI/Zhipu hosts only, so OpenCode-fronted GLM fell back to the 120s default watchdog. ([#4758](https://github.com/can1357/oh-my-pi/issues/4758))
44
+
5
45
  ## [16.5.2] - 2026-07-14
6
46
 
7
47
  ### Fixed
@@ -10,6 +10,13 @@
10
10
  export declare const isKimiModelId: (modelId: string) => boolean;
11
11
  /** Kimi K2.6 specifically, including router ids that spell the version `k2p6`. */
12
12
  export declare const isKimiK26ModelId: (modelId: string) => boolean;
13
+ /**
14
+ * Kimi K3 in any namespace form (`kimi-k3`, `kimi-k3.1`, `kimi-k3-turbo`,
15
+ * `moonshotai/kimi-k3`). K3 always reasons and drives thinking via OpenAI-style
16
+ * `reasoning_effort: "max"`, not the K2.x binary `thinking: { type }` block —
17
+ * see the moonshot discovery mapper and `buildOpenAICompat`.
18
+ */
19
+ export declare const isKimiK3ModelId: (modelId: string) => boolean;
13
20
  /**
14
21
  * Claude ids in any namespace form: bare (`claude-*`), path-namespaced
15
22
  * (`anthropic/claude.x`), or dot-prefixed (`us.anthropic.claude-…`,
@@ -76,6 +83,18 @@ export declare const supportsAllTurnsReasoningContext: (modelId: string) => bool
76
83
  * the human-readable summary stream.
77
84
  */
78
85
  export declare const supportsCodexReasoningSummary: (modelId: string) => boolean;
86
+ /**
87
+ * OpenAI proprietary models whose serving path rejects explicit sampling
88
+ * parameters (`temperature`, `top_p`, `top_k`, …) with
89
+ * `400 Unsupported parameter: 'temperature' is not supported with this model`.
90
+ * Covers the o-series and the entire gpt-5+ generation — base, `mini`, `nano`,
91
+ * `codex*`, the `luna`/`sol`/`terra` SKUs, and the `-chat-latest` variants,
92
+ * since even the non-reasoning gpt-5 chat models reject sampling params (see
93
+ * litellm#13781). Holds regardless of which OpenAI-serving host proxies the
94
+ * model (official, Azure, GitHub Copilot). Version floor (not an allowlist) so
95
+ * 6.x inherits automatically. Issue #5606.
96
+ */
97
+ export declare const isOpenAISamplingRestrictedModelId: (modelId: string) => boolean;
79
98
  /**
80
99
  * Reasoning-capable GLM coding SKUs: glm-4.5 and up on the base / `-air` /
81
100
  * `-turbo` lines. Excludes the vision (`…v`) shape, the non-reasoning
@@ -181,10 +181,26 @@ export declare function zhipuCodingPlanModelManagerOptions(config?: ZhipuCodingP
181
181
  */
182
182
  export declare const FIREWORKS_KIMI_MAX_TOKENS = 32768;
183
183
  /**
184
- * Returns true for any Kimi K2.x public model id served by Fireworks-backed
185
- * providers (`fireworks` direct, `firepass` router). Matches both the public
186
- * catalog id (`kimi-k2.5`, `kimi-k2.6`, `kimi-k2.6-turbo`) and the canonical
187
- * Fireworks wire id (`accounts/fireworks/{models,routers}/kimi-k2…`).
184
+ * Fireworks' output ceiling for Kimi K2.7-Code specifically. Its `/v1/models`
185
+ * generic `max_completion_tokens` is 65,536 and Fireworks serves it in full —
186
+ * verified with a single completion emitting 58,971 output tokens and
187
+ * `max_tokens: 200000` accepted without error. Unlike the older K2.5/K2.6
188
+ * family (see {@link FIREWORKS_KIMI_MAX_TOKENS}), K2.7-Code is not clamped to
189
+ * 32,768; that ceiling only truncated it.
190
+ */
191
+ export declare const FIREWORKS_KIMI_K27_CODE_MAX_TOKENS = 65536;
192
+ /**
193
+ * Returns true for the Kimi K2.5 / K2.6 family served by Fireworks-backed
194
+ * providers (`fireworks` direct, `firepass` router) that share the 32,768
195
+ * `maxTokens` ceiling. Matches both the public catalog id (`kimi-k2.5`,
196
+ * `kimi-k2.6`, `kimi-k2.6-turbo`) and the canonical Fireworks wire id
197
+ * (`accounts/fireworks/{models,routers}/kimi-k2…`).
198
+ *
199
+ * K2.7-Code (incl. `-fast` / `-highspeed`) is deliberately excluded: unlike the
200
+ * earlier K2 family it serves its full context on Fireworks — verified with a
201
+ * single completion emitting 58,971 output tokens and `max_tokens: 200000`
202
+ * accepted without error — so the 32,768 cap would only truncate it. It inherits
203
+ * Fireworks' reported `max_completion_tokens` (65,536) instead.
188
204
  */
189
205
  export declare function isFireworksKimiK2ModelId(modelId: string): boolean;
190
206
  /**
@@ -289,6 +289,15 @@ export interface OpenAICompat {
289
289
  toolStrictMode?: "all_strict" | "none";
290
290
  /** Whether request shaping may send reasoning params at all. Default: auto-detected (disabled for GitHub Copilot chat-completions). */
291
291
  supportsReasoningParams?: boolean;
292
+ /**
293
+ * Whether the endpoint accepts explicit sampling parameters (`temperature`,
294
+ * `top_p`, `top_k`, `min_p`, penalties). OpenAI proprietary reasoning models
295
+ * (o-series, gpt-5+) reject them with `400 Unsupported parameter:
296
+ * 'temperature' is not supported with this model` on every serving host
297
+ * (official, Azure, GitHub Copilot). When unset, auto-detected from the
298
+ * model id. Default: true. Issue #5606.
299
+ */
300
+ supportsSamplingParams?: boolean;
292
301
  /** 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). */
293
302
  alwaysSendMaxTokens?: boolean;
294
303
  /** Whether Responses-API tool-call/result history must be strictly paired. Default: auto-detected (Azure OpenAI, GitHub Copilot). */
@@ -333,7 +342,7 @@ export interface AnthropicCompat {
333
342
  * tags: 'disabled', 'enabled'`.
334
343
  */
335
344
  disableAdaptiveThinking?: boolean;
336
- /** Whether tools may include Anthropic's per-tool eager_input_streaming flag. Default: true. */
345
+ /** Whether tools may include Anthropic's per-tool eager_input_streaming flag. Default: true for the canonical Anthropic API. */
337
346
  supportsEagerToolInputStreaming?: boolean;
338
347
  /** Whether long prompt-cache retention (`ttl: "1h"`) is supported. Default: true for canonical Anthropic API. */
339
348
  supportsLongCacheRetention?: boolean;
@@ -421,6 +430,7 @@ export interface ResolvedOpenAISharedCompat {
421
430
  supportsReasoningEffort: boolean;
422
431
  reasoningEffortMap: Partial<Record<Effort, string>>;
423
432
  supportsReasoningParams: boolean;
433
+ supportsSamplingParams: boolean;
424
434
  thinkingFormat: OpenAIReasoningFormat;
425
435
  reasoningDisableMode: OpenAIReasoningDisableMode;
426
436
  omitReasoningEffort: boolean;
@@ -464,7 +474,7 @@ export interface ResolvedOpenAISharedCompat {
464
474
  * `buildModel`; request handlers read fields and never detect, resolve, or
465
475
  * allocate.
466
476
  */
467
- export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "thinkingFormat" | "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" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
477
+ export type ResolvedOpenAICompat = ResolvedOpenAISharedCompat & Required<Omit<OpenAICompat, "supportsDeveloperRole" | "supportsReasoningEffort" | "reasoningEffortMap" | "supportsReasoningParams" | "supportsSamplingParams" | "thinkingFormat" | "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" | "openRouterRouting" | "isOpenRouterHost" | "supportsStrictMode" | "supportsLongPromptCacheRetention" | "alwaysSendMaxTokens" | "wireModelIdMode" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode" | "toolSchemaFlavor" | "streamIdleTimeoutMs" | "cacheControlFormat" | "thinkingKeep" | "strictResponsesPairing" | "supportsImageDetailOriginal" | "enableGeminiThinkingLoopGuard" | "whenThinking">> & {
468
478
  vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
469
479
  extraBody?: OpenAICompat["extraBody"];
470
480
  cacheControlFormat?: OpenAICompat["cacheControlFormat"];
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.0.0",
4
+ "version": "17.0.2",
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",
@@ -34,12 +34,12 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@bufbuild/protobuf": "^2.12.1",
37
- "@oh-my-pi/pi-utils": "17.0.0",
37
+ "@oh-my-pi/pi-utils": "17.0.2",
38
38
  "arktype": "2.2.3",
39
39
  "zod": "^4"
40
40
  },
41
41
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "17.0.0",
42
+ "@oh-my-pi/pi-ai": "17.0.2",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
@@ -109,7 +109,7 @@ export function buildAnthropicCompat(spec: ModelSpec<"anthropic-messages">): Res
109
109
  signingEndpoint,
110
110
  disableStrictTools: isAzure,
111
111
  disableAdaptiveThinking: false,
112
- supportsEagerToolInputStreaming: !isCopilot,
112
+ supportsEagerToolInputStreaming: official,
113
113
  // Long cache retention is only sent to the official API by default;
114
114
  // proxies opt in explicitly via `compat.supportsLongCacheRetention: true`.
115
115
  supportsLongCacheRetention: official,
@@ -15,9 +15,11 @@ import {
15
15
  isDeepseekModelIdOrName,
16
16
  isGlm52ReasoningEffortModelId,
17
17
  isGrokReasoningEffortCapable,
18
+ isKimiK3ModelId,
18
19
  isKimiK26ModelId,
19
20
  isKimiModelId,
20
21
  isMimoModelIdOrName,
22
+ isOpenAISamplingRestrictedModelId,
21
23
  isQwenModelId,
22
24
  modelFamilyToken,
23
25
  } from "../identity/family";
@@ -37,8 +39,8 @@ const GLM_CODING_PLAN_MODEL_PATTERN = /(^|\/)glm-5(?:[.-]|$)/i;
37
39
  const GLM_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS = 600_000;
38
40
  /** Direct DeepSeek reasoning models stall between thinking and answer phases. */
39
41
  const DEEPSEEK_REASONING_STREAM_IDLE_TIMEOUT_MS = 300_000;
40
- /** Kimi K2.6 can spend several minutes reasoning before the first visible token. */
41
- const KIMI_K26_REASONING_STREAM_IDLE_TIMEOUT_MS = 300_000;
42
+ /** Kimi K2.6 and native K2.7 Code can spend several minutes reasoning before the first visible token. */
43
+ const KIMI_REASONING_STREAM_IDLE_TIMEOUT_MS = 300_000;
42
44
  /**
43
45
  * Native Kimi K2.7 Code requires `thinking.type: "enabled"` and rejects
44
46
  * disabled thinking. Match the public id, its Fast variant, and the
@@ -246,6 +248,11 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
246
248
  const isKimiModel = isKimiModelId(spec.id);
247
249
  const isMoonshotNative = modelMatchesHost(hostModel, "moonshotNative");
248
250
  const isMoonshotKimi = isKimiModel && isMoonshotNative;
251
+ // Kimi K3 (native) always reasons via OpenAI-style `reasoning_effort: "max"`
252
+ // and does NOT accept the K2.x binary `thinking: { type }` block, so it must
253
+ // stay on the "openai" thinking dialect even though it is a Moonshot-native
254
+ // Kimi model (#5756).
255
+ const isMoonshotKimiK3 = isMoonshotKimi && isKimiK3ModelId(spec.id);
249
256
  const requiresEnabledThinking = isMoonshotKimi && matchesKimiK27CodeFamily(spec);
250
257
  const usesMoonshotKimiPreservedThinking = isMoonshotKimi && isKimiK26ModelId(spec.id);
251
258
  const isAnthropicModel =
@@ -357,14 +364,17 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
357
364
  // for minutes while reasoning or cold-loading weights; widen the idle
358
365
  // timeout so warm-ups stop aborting and retrying.
359
366
  const streamIdleTimeoutMs =
360
- GLM_CODING_PLAN_MODEL_PATTERN.test(spec.id) && (isZai || isZhipu)
367
+ GLM_CODING_PLAN_MODEL_PATTERN.test(spec.id) && (isZai || isZhipu || isOpenCodeHost)
361
368
  ? GLM_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS
362
369
  : provider === "alibaba-coding-plan"
363
370
  ? ALIBABA_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS
364
371
  : isXiaomiMimo
365
372
  ? XIAOMI_MIMO_STREAM_IDLE_TIMEOUT_MS
366
- : spec.reasoning && isKimiK26ModelId(spec.id)
367
- ? KIMI_K26_REASONING_STREAM_IDLE_TIMEOUT_MS
373
+ : spec.reasoning &&
374
+ (isKimiK26ModelId(spec.id) ||
375
+ isMoonshotKimiK3 ||
376
+ (isMoonshotKimi && matchesKimiK27CodeFamily(spec)))
377
+ ? KIMI_REASONING_STREAM_IDLE_TIMEOUT_MS
368
378
  : spec.reasoning && isDirectDeepseekApi
369
379
  ? DEEPSEEK_REASONING_STREAM_IDLE_TIMEOUT_MS
370
380
  : isLocalOpenAICompatBackend
@@ -384,7 +394,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
384
394
  ? "openrouter"
385
395
  : "raw";
386
396
  const thinkingFormat: ResolvedOpenAISharedCompat["thinkingFormat"] =
387
- isZai || isZhipu || isMoonshotKimi || isXiaomiMimo
397
+ (isMoonshotKimi && !isMoonshotKimiK3) || isZai || isZhipu || isXiaomiMimo
388
398
  ? "zai"
389
399
  : isOpenRouter
390
400
  ? "openrouter"
@@ -409,6 +419,9 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
409
419
  supportsReasoningEffort: !isGrok && !isXiaomiMimo && (!(isZai || isZhipu) || supportsZaiReasoningEffort),
410
420
  // GitHub Copilot's chat-completions endpoint rejects reasoning params wholesale.
411
421
  supportsReasoningParams: provider !== "github-copilot",
422
+ // OpenAI proprietary reasoning models (o-series, gpt-5+) reject explicit
423
+ // temperature/top_p/… with a 400 on every serving host (#5606).
424
+ supportsSamplingParams: !isOpenAISamplingRestrictedModelId(spec.id),
412
425
  reasoningEffortMap: isMimoReasoningEffortModel ? MIMO_REASONING_EFFORT_MAP : {},
413
426
  supportsUsageInStreaming: !isCerebras,
414
427
  // pi-ai's thinking-loop guard is gemini-only; default the flag from the
@@ -422,7 +435,12 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
422
435
  // every call since the family can otherwise emit very long reasoning traces
423
436
  // before the final answer.
424
437
  alwaysSendMaxTokens: isKimiModel,
425
- disableReasoningOnForcedToolChoice: isKimiModel || isAnthropicModel,
438
+ // Native Kimi K3 always reasons via `reasoning_effort: "max"` (never the
439
+ // K2.x binary `thinking` block that #827's forced-tool-choice conflict is
440
+ // about), so suppressing its effort would strip the mandatory `max` from
441
+ // normal forced-tool turns (e.g. plan-mode `toolChoice: "required"`) and
442
+ // leave K3 in an unsupported mode (#5758 review).
443
+ disableReasoningOnForcedToolChoice: (isKimiModel && !isMoonshotKimiK3) || isAnthropicModel,
426
444
  disableReasoningOnToolChoice: isDeepseekFamily && Boolean(spec.reasoning) && !isOpenRouter,
427
445
  supportsToolChoice: !isDirectDeepseekReasoning,
428
446
  supportsForcedToolChoice: !requiresEnabledThinking,
@@ -604,6 +622,9 @@ export function buildOpenAIResponsesCompat(spec: OpenAIResponsesSpecLike): Resol
604
622
  spec.provider !== "xai-oauth" && !modelMatchesHost({ provider: spec.provider, baseUrl }, "githubCopilot"),
605
623
  reasoningEffortMap: {},
606
624
  supportsReasoningParams: true,
625
+ // OpenAI proprietary reasoning models (o-series, gpt-5+) reject explicit
626
+ // temperature/top_p/… with a 400 on every serving host (#5606).
627
+ supportsSamplingParams: !isOpenAISamplingRestrictedModelId(id),
607
628
  thinkingFormat,
608
629
  reasoningDisableMode: resolveReasoningDisableMode(thinkingFormat),
609
630
  omitReasoningEffort: false,
@@ -1,4 +1,5 @@
1
1
  import { type } from "arktype";
2
+ import { parseKnownModel, semverEqual } from "../identity/classify";
2
3
  import type { ModelSpec } from "../types";
3
4
  import { discoveryFetch } from "../utils";
4
5
  import { CODEX_BASE_URL, CODEX_CLIENT_VERSION, OPENAI_HEADER_VALUES, OPENAI_HEADERS } from "../wire/codex";
@@ -6,6 +7,14 @@ import { CODEX_BASE_URL, CODEX_CLIENT_VERSION, OPENAI_HEADER_VALUES, OPENAI_HEAD
6
7
  const DEFAULT_MODEL_LIST_PATHS = ["/codex/models", "/models"] as const;
7
8
  const DEFAULT_CONTEXT_WINDOW = 272_000;
8
9
  const DEFAULT_MAX_TOKENS = 128_000;
10
+ /**
11
+ * GPT-5.6 luna/sol/terra hard context capacity. Codex discovery omits
12
+ * `context_window` for these SKUs, so the generic {@link DEFAULT_CONTEXT_WINDOW}
13
+ * (272000) would understate the real window — OpenAI's Codex model registry
14
+ * declares context_window = max_context_window = 372000 (#5705). Used as the
15
+ * fallback only when upstream reports no value.
16
+ */
17
+ const GPT_5_6_CONTEXT_WINDOW = 372_000;
9
18
  const CODEX_REMOTE_COMPACTION = {
10
19
  enabled: true,
11
20
  api: "openai-codex-responses",
@@ -214,7 +223,14 @@ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCo
214
223
  }
215
224
 
216
225
  const name = toNonEmptyString(payload.display_name) ?? slug;
217
- const contextWindow = toPositiveInt(payload.context_window) ?? DEFAULT_CONTEXT_WINDOW;
226
+ // Codex discovery omits `context_window` for GPT-5.6 luna/sol/terra; the
227
+ // generic 272000 fallback understates their real 372000 window (#5705).
228
+ const parsed = parseKnownModel(slug);
229
+ const fallbackContextWindow =
230
+ parsed.family === "openai" && semverEqual(parsed.version, "5.6")
231
+ ? GPT_5_6_CONTEXT_WINDOW
232
+ : DEFAULT_CONTEXT_WINDOW;
233
+ const contextWindow = toPositiveInt(payload.context_window) ?? fallbackContextWindow;
218
234
  const maxTokens = Math.min(DEFAULT_MAX_TOKENS, contextWindow);
219
235
  const reasoning = supportsReasoning(payload.default_reasoning_level, payload.supported_reasoning_levels);
220
236
  const input = normalizeInputModalities(payload.input_modalities);
@@ -41,6 +41,16 @@ export const isKimiK26ModelId = memo((modelId: string): boolean => {
41
41
  return /(^|\/)kimi-k2(?:\.6|p6)(?:[-:]|$)/i.test(modelId);
42
42
  });
43
43
 
44
+ /**
45
+ * Kimi K3 in any namespace form (`kimi-k3`, `kimi-k3.1`, `kimi-k3-turbo`,
46
+ * `moonshotai/kimi-k3`). K3 always reasons and drives thinking via OpenAI-style
47
+ * `reasoning_effort: "max"`, not the K2.x binary `thinking: { type }` block —
48
+ * see the moonshot discovery mapper and `buildOpenAICompat`.
49
+ */
50
+ export const isKimiK3ModelId = memo((modelId: string): boolean => {
51
+ return /(^|\/)kimi-k3(?:\.\d+)?(?:[-.:_]|$)/i.test(modelId);
52
+ });
53
+
44
54
  /**
45
55
  * Claude ids in any namespace form: bare (`claude-*`), path-namespaced
46
56
  * (`anthropic/claude.x`), or dot-prefixed (`us.anthropic.claude-…`,
@@ -163,6 +173,32 @@ export const supportsAllTurnsReasoningContext = isOpenAIWireGen54Plus;
163
173
  */
164
174
  export const supportsCodexReasoningSummary = isOpenAIWireGen54Plus;
165
175
 
176
+ /** OpenAI proprietary reasoning families keyed off the parsed gpt version (gpt-5+). */
177
+ const isOpenAIWireGen5Plus = memo((modelId: string): boolean => {
178
+ const parsed = parseOpenAIModel(bareModelId(modelId));
179
+ if (!parsed) return false;
180
+ return semverGte(parsed.version, "5");
181
+ });
182
+
183
+ /** o-series reasoning ids (`o1`, `o1-pro`, `o3`, `o3-mini`, `o4-mini`, `openai/o3`, …). */
184
+ const O_SERIES_REASONING_RE = /(^|\/)o[134](?:[-.]|$)/i;
185
+
186
+ /**
187
+ * OpenAI proprietary models whose serving path rejects explicit sampling
188
+ * parameters (`temperature`, `top_p`, `top_k`, …) with
189
+ * `400 Unsupported parameter: 'temperature' is not supported with this model`.
190
+ * Covers the o-series and the entire gpt-5+ generation — base, `mini`, `nano`,
191
+ * `codex*`, the `luna`/`sol`/`terra` SKUs, and the `-chat-latest` variants,
192
+ * since even the non-reasoning gpt-5 chat models reject sampling params (see
193
+ * litellm#13781). Holds regardless of which OpenAI-serving host proxies the
194
+ * model (official, Azure, GitHub Copilot). Version floor (not an allowlist) so
195
+ * 6.x inherits automatically. Issue #5606.
196
+ */
197
+ export const isOpenAISamplingRestrictedModelId = memo((modelId: string): boolean => {
198
+ const bare = bareModelId(modelId);
199
+ return isOpenAIWireGen5Plus(modelId) || O_SERIES_REASONING_RE.test(bare);
200
+ });
201
+
166
202
  /**
167
203
  * Reasoning-capable GLM coding SKUs: glm-4.5 and up on the base / `-air` /
168
204
  * `-turbo` lines. Excludes the vision (`…v`) shape, the non-reasoning