@oh-my-pi/pi-catalog 17.0.1 → 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,18 @@
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
+
5
17
  ## [17.0.1] - 2026-07-16
6
18
 
7
19
  ### Added
@@ -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-…`,
@@ -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
  /**
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.1",
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.1",
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.1",
42
+ "@oh-my-pi/pi-ai": "17.0.2",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
@@ -15,6 +15,7 @@ import {
15
15
  isDeepseekModelIdOrName,
16
16
  isGlm52ReasoningEffortModelId,
17
17
  isGrokReasoningEffortCapable,
18
+ isKimiK3ModelId,
18
19
  isKimiK26ModelId,
19
20
  isKimiModelId,
20
21
  isMimoModelIdOrName,
@@ -247,6 +248,11 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
247
248
  const isKimiModel = isKimiModelId(spec.id);
248
249
  const isMoonshotNative = modelMatchesHost(hostModel, "moonshotNative");
249
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);
250
256
  const requiresEnabledThinking = isMoonshotKimi && matchesKimiK27CodeFamily(spec);
251
257
  const usesMoonshotKimiPreservedThinking = isMoonshotKimi && isKimiK26ModelId(spec.id);
252
258
  const isAnthropicModel =
@@ -364,7 +370,10 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
364
370
  ? ALIBABA_CODING_PLAN_STREAM_IDLE_TIMEOUT_MS
365
371
  : isXiaomiMimo
366
372
  ? XIAOMI_MIMO_STREAM_IDLE_TIMEOUT_MS
367
- : spec.reasoning && (isKimiK26ModelId(spec.id) || (isMoonshotKimi && matchesKimiK27CodeFamily(spec)))
373
+ : spec.reasoning &&
374
+ (isKimiK26ModelId(spec.id) ||
375
+ isMoonshotKimiK3 ||
376
+ (isMoonshotKimi && matchesKimiK27CodeFamily(spec)))
368
377
  ? KIMI_REASONING_STREAM_IDLE_TIMEOUT_MS
369
378
  : spec.reasoning && isDirectDeepseekApi
370
379
  ? DEEPSEEK_REASONING_STREAM_IDLE_TIMEOUT_MS
@@ -385,7 +394,7 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
385
394
  ? "openrouter"
386
395
  : "raw";
387
396
  const thinkingFormat: ResolvedOpenAISharedCompat["thinkingFormat"] =
388
- isZai || isZhipu || isMoonshotKimi || isXiaomiMimo
397
+ (isMoonshotKimi && !isMoonshotKimiK3) || isZai || isZhipu || isXiaomiMimo
389
398
  ? "zai"
390
399
  : isOpenRouter
391
400
  ? "openrouter"
@@ -426,7 +435,12 @@ export function buildOpenAICompat(spec: ModelSpec<"openai-completions">): Resolv
426
435
  // every call since the family can otherwise emit very long reasoning traces
427
436
  // before the final answer.
428
437
  alwaysSendMaxTokens: isKimiModel,
429
- 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,
430
444
  disableReasoningOnToolChoice: isDeepseekFamily && Boolean(spec.reasoning) && !isOpenRouter,
431
445
  supportsToolChoice: !isDirectDeepseekReasoning,
432
446
  supportsForcedToolChoice: !requiresEnabledThinking,
@@ -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-…`,