@oh-my-pi/pi-catalog 18.0.9 → 18.0.11

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
+ ## [18.0.11] - 2026-08-29
6
+
7
+ ### Fixed
8
+
9
+ - Fixed Baseten GLM models, including GLM-5.3-Flash, being incorrectly classified as non-reasoning models.
10
+ - Fixed Cloudflare AI Gateway catalog refreshes so active Workers AI chat models, including newly released models, are discovered correctly.
11
+ - Fixed Cursor Kimi K3, Grok 4, and Composer 2.5 models being incorrectly treated as text-only when they support image attachments.
12
+ - Fixed OpenRouter routed model variants, including GLM-5.3 and dated DeepSeek V4 Pro, so their reasoning effort options are preserved correctly.
13
+ - Fixed MiniMax-M3 max output regressing to the upstream 512K pricing-tier boundary; all MiniMax providers keep the documented 128K output cap.
14
+ - Fixed GLM-5.3-Flash bundling the 50%-off launch promotion price; the catalog stays on the documented list price.
15
+ - Fixed Synthetic model discovery re-adding image input from the bundled reference when the route advertises text-only modalities.
16
+
5
17
  ## [18.0.9] - 2026-08-28
6
18
 
7
19
  ### Added
@@ -21,3 +21,9 @@ export interface CursorModelDiscoveryOptions {
21
21
  * Returns `[]` only when the endpoint responds successfully with no usable models.
22
22
  */
23
23
  export declare function fetchCursorUsableModels(options: CursorModelDiscoveryOptions): Promise<ModelSpec<"cursor-agent">[] | null>;
24
+ /**
25
+ * Resolves input modalities from a bundled reference when available, except
26
+ * for Cursor-only families whose image support is known independently. Without
27
+ * a reference, native multimodal families fall back to id classification.
28
+ */
29
+ export declare function resolveCursorInput(id: string, referenceInput?: ("text" | "image")[]): ("text" | "image")[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-catalog",
4
- "version": "18.0.9",
4
+ "version": "18.0.11",
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": "Stencil Labs, Inc.",
@@ -34,11 +34,11 @@
34
34
  "gen:proto": "bun scripts/generate-protocols.ts"
35
35
  },
36
36
  "dependencies": {
37
- "@oh-my-pi/omptype": "18.0.9",
38
- "@oh-my-pi/pi-utils": "18.0.9"
37
+ "@oh-my-pi/omptype": "18.0.11",
38
+ "@oh-my-pi/pi-utils": "18.0.11"
39
39
  },
40
40
  "devDependencies": {
41
- "@oh-my-pi/pi-ai": "18.0.9",
41
+ "@oh-my-pi/pi-ai": "18.0.11",
42
42
  "@types/bun": "^1.3.14"
43
43
  },
44
44
  "engines": {
@@ -33,14 +33,20 @@ const CURSOR_KIMI_K3_BARE_ID_PATTERN = /(^|\/)k3$/i;
33
33
  * reasoning models whose effort is carried in the per-tier sibling id.
34
34
  * `GetUsableModels` ships no `thinkingDetails` and the bundled references read
35
35
  * `reasoning: false`, so classification falls back to the id. The non-reasoning
36
- * `grok-code-*` coding models lack the version digit and stay out.
36
+ * `grok-code-fast-*` family deliberately stays out.
37
37
  */
38
38
  const CURSOR_GROK_REASONING_ID_PATTERN = /^cursor-grok-\d/i;
39
39
 
40
+ /**
41
+ * Cursor-only families verified to accept `selectedImages` even though
42
+ * `GetUsableModels` does not advertise input modalities.
43
+ */
44
+ const CURSOR_GROK_4_MULTIMODAL_ID_PATTERN = /^cursor-grok-4(?:[.:_-]|$)/i;
45
+ const CURSOR_COMPOSER_25_MULTIMODAL_ID_PATTERN = /^composer-2\.5(?:[.:_-]|$)/i;
46
+
40
47
  /**
41
48
  * Model-id families whose native catalogs (anthropic, openai/openai-codex,
42
- * google) are multimodal. Cursor-only or text-only families (`composer-*`,
43
- * `grok-code-*`) intentionally stay outside this pattern.
49
+ * google) are multimodal. Cursor-only verified families are handled separately.
44
50
  */
45
51
  const CURSOR_MULTIMODAL_ID_PATTERN = /claude|gemini|gpt-|codex/;
46
52
 
@@ -319,6 +325,7 @@ function normalizeCursorModel(
319
325
  name,
320
326
  baseUrl: baseUrlOverride ?? reference.baseUrl,
321
327
  reasoning,
328
+ input: resolveCursorInput(id, reference.input),
322
329
  contextWindow: resolveCursorContextWindow(details, id, reference.contextWindow),
323
330
  cursorMaxMode: details.maxMode,
324
331
  };
@@ -330,7 +337,7 @@ function normalizeCursorModel(
330
337
  provider: "cursor",
331
338
  baseUrl: baseUrlOverride ?? CURSOR_DEFAULT_BASE_URL,
332
339
  reasoning,
333
- input: inferInputFromCursorId(id),
340
+ input: resolveCursorInput(id),
334
341
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
335
342
  contextWindow: resolveCursorContextWindow(details, id, DEFAULT_CONTEXT_WINDOW),
336
343
  maxTokens: DEFAULT_MAX_TOKENS,
@@ -394,14 +401,22 @@ function pickModelDisplayName(model: CursorModelDetailsValue, fallbackId: string
394
401
  }
395
402
 
396
403
  /**
397
- * Infers input modalities for Cursor models without a bundled reference.
398
- *
399
- * `GetUsableModels` carries no per-model modality metadata, so classification
400
- * falls back to the model family: families that are multimodal in OMP's own
401
- * native catalogs accept images, everything else stays text-only. Mirrors
402
- * `inferInputFromGeminiId` in ./gemini.ts.
404
+ * Resolves input modalities from a bundled reference when available, except
405
+ * for Cursor-only families whose image support is known independently. Without
406
+ * a reference, native multimodal families fall back to id classification.
403
407
  */
404
- function inferInputFromCursorId(id: string): ("text" | "image")[] {
408
+ export function resolveCursorInput(id: string, referenceInput?: ("text" | "image")[]): ("text" | "image")[] {
409
+ if (
410
+ isKimiK3ModelId(id) ||
411
+ CURSOR_KIMI_K3_BARE_ID_PATTERN.test(id) ||
412
+ CURSOR_GROK_4_MULTIMODAL_ID_PATTERN.test(id) ||
413
+ CURSOR_COMPOSER_25_MULTIMODAL_ID_PATTERN.test(id)
414
+ ) {
415
+ return ["text", "image"];
416
+ }
417
+ if (referenceInput) {
418
+ return referenceInput;
419
+ }
405
420
  if (CURSOR_MULTIMODAL_ID_PATTERN.test(id.toLowerCase())) {
406
421
  return ["text", "image"];
407
422
  }
@@ -429,11 +429,14 @@ function getModelDefinedEfforts<TApi extends Api>(
429
429
  if (isDeepseekV4FlashModelId(spec.id)) {
430
430
  return LOW_HIGH_MAX_REASONING_EFFORTS;
431
431
  }
432
- if (bareModelId(spec.id).toLowerCase().includes("deepseek-v4")) {
432
+ const bareId = bareModelId(spec.id).toLowerCase();
433
+ if (bareId.includes("deepseek-v4")) {
433
434
  if (!isOpenRouterThinkingFormat(compat)) {
434
435
  return LOW_HIGH_MAX_REASONING_EFFORTS;
435
436
  }
436
- return bareModelId(spec.id).toLowerCase() === "deepseek-v4-pro-0813"
437
+ // Route suffixes are OpenRouter-specific and not part of the model identity.
438
+ const openRouterBaseId = bareId.replace(/:[^:]+$/, "");
439
+ return openRouterBaseId === "deepseek-v4-pro-0813"
437
440
  ? LOW_HIGH_MAX_REASONING_EFFORTS
438
441
  : HIGH_ONLY_REASONING_EFFORTS;
439
442
  }