@oh-my-pi/pi-catalog 16.3.12 → 16.3.14

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,30 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.3.14] - 2026-07-09
6
+
7
+ ### Added
8
+
9
+ - Added support for GPT-5.6 (Luna, Sol, Terra) model variants
10
+ - Enabled expanded five-tier reasoning effort scale (minimal to xhigh) for GPT-5.6 models
11
+ - Added GPT-5.6 (Terra/Luna/Sol) support for the new `max` reasoning tier: on wire-effort APIs (OpenAI Responses, Codex, Azure, openai-compat/OpenRouter models that advertise reasoning) user efforts shift up one notch — `xhigh` sends `max`, `high` sends `xhigh` — mirroring the Claude Fable/Opus 4.7+ five-tier mapping, and the exposed ladder becomes `minimal..xhigh` with `minimal` reaching the native `low` tier. Devin's per-tier GPT-5.6 sibling rows now collapse into `gpt-5-6-{luna,sol,terra}` logical models with the same shifted routing (`xhigh` → `-max`), plus `-fast` families that keep the direct `low..xhigh` `-priority` scale since Devin serves no `-max-priority` tier.
12
+
13
+ ## [16.3.13] - 2026-07-09
14
+
15
+ ### Added
16
+
17
+ - Added support for Grok 4.5 across multiple providers
18
+ - Added support for GPT-5.6 series models (Luna, Sol, Terra)
19
+ - Added Aion 3.0 and 3.0 Mini models
20
+ - Added Kuaishou KAT-Coder v2.5 models
21
+ - Added Nex-N2-Mini and SWE-1.7 series models
22
+ - Added Hy3 models and free variants
23
+
24
+ ### Changed
25
+
26
+ - Updated cost and token configurations for various models across providers
27
+ - Renamed several models for consistency (e.g., MiniMax M3, Gemma 4 31B, Qwen variants)
28
+
5
29
  ## [16.3.12] - 2026-07-08
6
30
 
7
31
  ### Fixed
@@ -24,7 +24,7 @@ export interface ModelManagerOptions<TApi extends Api = Api, TModelsDevPayload =
24
24
  cacheDbPath?: string;
25
25
  /** Optional provider id override for cache namespacing. Defaults to providerId. */
26
26
  cacheProviderId?: string;
27
- /** Maximum cache age in milliseconds before considered stale. Default: 24h. */
27
+ /** Maximum cache age in milliseconds before considered stale. Default: 2h (`DEFAULT_CACHE_TTL_MS`). */
28
28
  cacheTtlMs?: number;
29
29
  /** When true, a successful dynamic fetch is the complete provider catalog and prunes static-only models. */
30
30
  dynamicModelsAuthoritative?: boolean;
@@ -14,12 +14,14 @@ import type { Api, CompatOf, Model, ModelSpec, ThinkingConfig } from "./types.js
14
14
  */
15
15
  type ApiModel<TApi extends Api = Api> = ModelSpec<TApi> | Model<TApi>;
16
16
  /**
17
- * Effort → wire-value map for the 5-tier adaptive scale (Opus 4.7+ and
18
- * Fable/Mythos 5 on the Messages API). User-facing efforts shift up one notch
19
- * so the top tier reaches the genuine "max" and "high" lands on Anthropic's
20
- * recommended "xhigh" coding/agentic default.
17
+ * Effort → wire-value map for a shifted five-tier scale (`low..max`):
18
+ * user-facing efforts shift up one notch so the top tier reaches the genuine
19
+ * "max" and "high" lands on the recommended "xhigh" coding/agentic default.
20
+ * Used by Anthropic adaptive models with a real xhigh tier (Opus 4.7+ and
21
+ * Fable/Mythos 5 on the Messages API) and by GPT-5.6+ wire-effort models,
22
+ * which expose the same genuine `max` tier above `xhigh`.
21
23
  */
22
- export declare const ANTHROPIC_ADAPTIVE_EFFORT_MAP_5_TIER: Readonly<Partial<Record<Effort, string>>>;
24
+ export declare const SHIFTED_FIVE_TIER_EFFORT_MAP: Readonly<Partial<Record<Effort, string>>>;
23
25
  /**
24
26
  * Effort → wire-value map for the legacy 4-tier adaptive scale (Opus 4.6,
25
27
  * Sonnet 4.6+, and every adaptive model on Bedrock Converse). `low..high` pass
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "16.3.12",
4
+ "version": "16.3.14",
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.0",
37
- "@oh-my-pi/pi-utils": "16.3.12",
37
+ "@oh-my-pi/pi-utils": "16.3.14",
38
38
  "arktype": "^2.2.0",
39
39
  "zod": "^4"
40
40
  },
41
41
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "16.3.12",
42
+ "@oh-my-pi/pi-ai": "16.3.14",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
@@ -13,6 +13,13 @@ const CURSOR_GET_USABLE_MODELS_PATH = "/agent.v1.AgentService/GetUsableModels";
13
13
  const DEFAULT_CONTEXT_WINDOW = 200_000;
14
14
  const DEFAULT_MAX_TOKENS = 64_000;
15
15
 
16
+ /**
17
+ * Model-id families whose native catalogs (anthropic, openai/openai-codex,
18
+ * google) are multimodal. Cursor-only or text-only families (`composer-*`,
19
+ * `grok-code-*`) intentionally stay outside this pattern.
20
+ */
21
+ const CURSOR_MULTIMODAL_ID_PATTERN = /claude|gemini|gpt-|codex/;
22
+
16
23
  const OptionalDisplayNameSchema = type("unknown").pipe(raw => (typeof raw === "string" ? raw : undefined));
17
24
  const CursorAliasesSchema = type("unknown").pipe(raw => {
18
25
  if (Array.isArray(raw)) {
@@ -292,7 +299,7 @@ function normalizeCursorModel(
292
299
  provider: "cursor",
293
300
  baseUrl: baseUrlOverride ?? CURSOR_DEFAULT_BASE_URL,
294
301
  reasoning,
295
- input: ["text"],
302
+ input: inferInputFromCursorId(id),
296
303
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
297
304
  contextWindow: DEFAULT_CONTEXT_WINDOW,
298
305
  maxTokens: DEFAULT_MAX_TOKENS,
@@ -312,3 +319,18 @@ function pickModelDisplayName(model: CursorModelDetailsValue, fallbackId: string
312
319
  }
313
320
  return fallbackId;
314
321
  }
322
+
323
+ /**
324
+ * Infers input modalities for Cursor models without a bundled reference.
325
+ *
326
+ * `GetUsableModels` carries no per-model modality metadata, so classification
327
+ * falls back to the model family: families that are multimodal in OMP's own
328
+ * native catalogs accept images, everything else stays text-only. Mirrors
329
+ * `inferInputFromGeminiId` in ./gemini.ts.
330
+ */
331
+ function inferInputFromCursorId(id: string): ("text" | "image")[] {
332
+ if (CURSOR_MULTIMODAL_ID_PATTERN.test(id.toLowerCase())) {
333
+ return ["text", "image"];
334
+ }
335
+ return ["text"];
336
+ }
@@ -35,7 +35,7 @@ export interface ModelManagerOptions<TApi extends Api = Api, TModelsDevPayload =
35
35
  cacheDbPath?: string;
36
36
  /** Optional provider id override for cache namespacing. Defaults to providerId. */
37
37
  cacheProviderId?: string;
38
- /** Maximum cache age in milliseconds before considered stale. Default: 24h. */
38
+ /** Maximum cache age in milliseconds before considered stale. Default: 2h (`DEFAULT_CACHE_TTL_MS`). */
39
39
  cacheTtlMs?: number;
40
40
  /** When true, a successful dynamic fetch is the complete provider catalog and prunes static-only models. */
41
41
  dynamicModelsAuthoritative?: boolean;
@@ -17,6 +17,7 @@ import {
17
17
  type ParsedModel,
18
18
  parseAnthropicModel,
19
19
  parseKnownModel,
20
+ parseOpenAIModel,
20
21
  semverEqual,
21
22
  semverGte,
22
23
  } from "./identity/classify";
@@ -101,12 +102,14 @@ const MIMO_REASONING_EFFORT_MAP: Readonly<EffortMap> = {
101
102
  };
102
103
 
103
104
  /**
104
- * Effort → wire-value map for the 5-tier adaptive scale (Opus 4.7+ and
105
- * Fable/Mythos 5 on the Messages API). User-facing efforts shift up one notch
106
- * so the top tier reaches the genuine "max" and "high" lands on Anthropic's
107
- * recommended "xhigh" coding/agentic default.
105
+ * Effort → wire-value map for a shifted five-tier scale (`low..max`):
106
+ * user-facing efforts shift up one notch so the top tier reaches the genuine
107
+ * "max" and "high" lands on the recommended "xhigh" coding/agentic default.
108
+ * Used by Anthropic adaptive models with a real xhigh tier (Opus 4.7+ and
109
+ * Fable/Mythos 5 on the Messages API) and by GPT-5.6+ wire-effort models,
110
+ * which expose the same genuine `max` tier above `xhigh`.
108
111
  */
109
- export const ANTHROPIC_ADAPTIVE_EFFORT_MAP_5_TIER: Readonly<Partial<Record<Effort, string>>> = {
112
+ export const SHIFTED_FIVE_TIER_EFFORT_MAP: Readonly<Partial<Record<Effort, string>>> = {
110
113
  [Effort.Minimal]: "low",
111
114
  [Effort.Low]: "medium",
112
115
  [Effort.Medium]: "high",
@@ -295,6 +298,27 @@ function isOpenAICompatReasoningApi(api: Api): boolean {
295
298
  return api === "openai-completions" || api === "openrouter";
296
299
  }
297
300
 
301
+ /**
302
+ * GPT-5.6+ addressed through a wire `reasoning.effort`/`reasoning_effort`
303
+ * field, where the shifted five-tier map applies. Devin (`devin-agent`)
304
+ * selects effort by routing to per-tier sibling model ids instead and must
305
+ * stay unmapped.
306
+ */
307
+ function isGpt56PlusWireEffortModel<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
308
+ switch (spec.api) {
309
+ case "openai-responses":
310
+ case "openai-codex-responses":
311
+ case "azure-openai-responses":
312
+ case "openai-completions":
313
+ case "openrouter":
314
+ break;
315
+ default:
316
+ return false;
317
+ }
318
+ const parsed = parseOpenAIModel(bareModelId(spec.id));
319
+ return parsed !== null && semverGte(parsed.version, "5.6");
320
+ }
321
+
298
322
  function getModelDefinedEfforts<TApi extends Api>(
299
323
  spec: ModelSpec<TApi>,
300
324
  compat: CompatOf<TApi>,
@@ -313,6 +337,12 @@ function getModelDefinedEfforts<TApi extends Api>(
313
337
  if (isSakanaFuguReasoningModel(spec)) {
314
338
  return FUGU_REASONING_EFFORTS;
315
339
  }
340
+ if (isGpt56PlusWireEffortModel(spec)) {
341
+ // Normalize stale baked/discovered `low..xhigh` surfaces to the full
342
+ // five-tier ladder so the shifted map keeps the native `low` tier
343
+ // reachable (user `minimal`).
344
+ return DEFAULT_REASONING_EFFORTS_WITH_XHIGH;
345
+ }
316
346
  return isOpenAICompatReasoningApi(spec.api) &&
317
347
  (isMinimaxM2FamilyModelId(spec.id) ||
318
348
  isOpenAIGptOssModelId(spec.id) ||
@@ -373,7 +403,7 @@ function inferDetectedEffortMap<TApi extends Api>(
373
403
  return MINIMAX_ANTHROPIC_ADAPTIVE_EFFORT_MAP;
374
404
  }
375
405
  return anthropicModelHasRealXHighEffort(spec, parsedModel)
376
- ? ANTHROPIC_ADAPTIVE_EFFORT_MAP_5_TIER
406
+ ? SHIFTED_FIVE_TIER_EFFORT_MAP
377
407
  : ANTHROPIC_ADAPTIVE_EFFORT_MAP_4_TIER;
378
408
  }
379
409
  // GLM-5.2 coding SKUs accept `reasoning_effort`, but the effort dialect is
@@ -397,6 +427,9 @@ function inferDetectedEffortMap<TApi extends Api>(
397
427
  if (isSakanaFuguReasoningModel(spec)) {
398
428
  return FUGU_REASONING_EFFORT_MAP;
399
429
  }
430
+ if (isGpt56PlusWireEffortModel(spec)) {
431
+ return SHIFTED_FIVE_TIER_EFFORT_MAP;
432
+ }
400
433
  if (!isOpenAICompatReasoningApi(spec.api)) {
401
434
  return undefined;
402
435
  }
@@ -446,7 +479,7 @@ function getOpenRouterAnthropicReasoningEffortMap(modelId: string): EffortMap |
446
479
  if (!isAnthropicAdaptiveGenAtLeast(parsed, "4.6")) return undefined;
447
480
 
448
481
  const hasRealXHigh = isAnthropicAdaptiveGenAtLeast(parsed, "4.7");
449
- return hasRealXHigh ? ANTHROPIC_ADAPTIVE_EFFORT_MAP_5_TIER : ANTHROPIC_ADAPTIVE_EFFORT_MAP_4_TIER;
482
+ return hasRealXHigh ? SHIFTED_FIVE_TIER_EFFORT_MAP : ANTHROPIC_ADAPTIVE_EFFORT_MAP_4_TIER;
450
483
  }
451
484
 
452
485
  function inferSupportedEfforts<TApi extends Api>(
@@ -474,6 +507,11 @@ function inferOpenAISupportedEfforts(model: OpenAIModel): readonly Effort[] {
474
507
  if (model.variant === "codex-mini" && semverEqual(model.version, "5.1")) {
475
508
  return GPT_5_1_CODEX_MINI_EFFORTS;
476
509
  }
510
+ // 5.6+ exposes the full five-tier ladder: the shifted wire map spans
511
+ // low..max, with user `minimal` reaching the native `low` tier.
512
+ if (semverGte(model.version, "5.6")) {
513
+ return DEFAULT_REASONING_EFFORTS_WITH_XHIGH;
514
+ }
477
515
  if (semverGte(model.version, "5.2")) {
478
516
  return GPT_5_2_PLUS_EFFORTS;
479
517
  }