@oh-my-pi/pi-catalog 16.4.8 → 16.5.1

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,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.5.1] - 2026-07-14
6
+
7
+ ### Fixed
8
+
9
+ - Fixed reasoning effort mapping for Z.ai GLM-5.2 on the Anthropic messages endpoint to correctly use the two-tier scale (high, max) and emit output_config.effort.
10
+ - Fixed an issue where stale cached model limits would override updated static catalog limits after a catalog fingerprint mismatch.
11
+ - Fixed Cursor discovery to correctly preserve GetUsableModels max-mode metadata for premium models and invalidate stale cache entries.
12
+
5
13
  ## [16.4.3] - 2026-07-11
6
14
 
7
15
  ### Fixed
@@ -590,6 +590,8 @@ export interface Model<TApi extends Api = Api> {
590
590
  supportsTools?: boolean;
591
591
  /** GitLab Duo Workflow root namespace selected during catalog discovery. */
592
592
  gitlabDuoWorkflowRootNamespaceId?: string;
593
+ /** Cursor `max_mode` request flag returned by `GetUsableModels` for premium models that require max mode. */
594
+ cursorMaxMode?: boolean;
593
595
  cost: {
594
596
  input: number;
595
597
  output: number;
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.4.8",
4
+ "version": "16.5.1",
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",
@@ -33,13 +33,13 @@
33
33
  "gen:models": "bun scripts/generate-models.ts"
34
34
  },
35
35
  "dependencies": {
36
- "@bufbuild/protobuf": "^2.12.0",
37
- "@oh-my-pi/pi-utils": "16.4.8",
38
- "arktype": "2.2.2",
36
+ "@bufbuild/protobuf": "^2.12.1",
37
+ "@oh-my-pi/pi-utils": "16.5.1",
38
+ "arktype": "2.2.3",
39
39
  "zod": "^4"
40
40
  },
41
41
  "devDependencies": {
42
- "@oh-my-pi/pi-ai": "16.4.8",
42
+ "@oh-my-pi/pi-ai": "16.5.1",
43
43
  "@types/bun": "^1.3.14"
44
44
  },
45
45
  "engines": {
@@ -35,6 +35,7 @@ const CursorModelDetailsSchema = type({
35
35
  displayModelId: OptionalDisplayNameSchema.default(undefined),
36
36
  aliases: CursorAliasesSchema.default(() => []),
37
37
  "thinkingDetails?": "unknown",
38
+ maxMode: "boolean = false",
38
39
  });
39
40
 
40
41
  const CursorModelsInnerSchema = type("unknown[]");
@@ -290,6 +291,7 @@ function normalizeCursorModel(
290
291
  name,
291
292
  baseUrl: baseUrlOverride ?? reference.baseUrl,
292
293
  reasoning,
294
+ cursorMaxMode: details.maxMode,
293
295
  };
294
296
  }
295
297
  return {
@@ -303,6 +305,7 @@ function normalizeCursorModel(
303
305
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
304
306
  contextWindow: DEFAULT_CONTEXT_WINDOW,
305
307
  maxTokens: DEFAULT_MAX_TOKENS,
308
+ cursorMaxMode: details.maxMode,
306
309
  };
307
310
  }
308
311
 
@@ -152,8 +152,9 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
152
152
  const dynamicFetchSucceeded = fetchedDynamicModels !== null;
153
153
  const cacheModels = dynamicFetchSucceeded
154
154
  ? []
155
- : dropCachedModelIdsOnStaticMismatch(
155
+ : prepareCacheModelsForStaticMismatch(
156
156
  normalizeModelList<TApi>(cache?.models ?? []),
157
+ staticModels,
157
158
  cacheFingerprintMatches,
158
159
  options.dropCachedModelIdsOnStaticMismatch,
159
160
  );
@@ -188,8 +189,9 @@ export async function resolveProviderModels<TApi extends Api = Api, TModelsDevPa
188
189
  collapseBuiltModelVariants(
189
190
  mergeDynamicModels(
190
191
  mergeModelSources(staticModels, modelsDevModels),
191
- dropCachedModelIdsOnStaticMismatch(
192
+ prepareCacheModelsForStaticMismatch(
192
193
  normalizeModelList<TApi>(latestCache?.models ?? cache?.models ?? []),
194
+ staticModels,
193
195
  cacheFingerprintMatches,
194
196
  options.dropCachedModelIdsOnStaticMismatch,
195
197
  ),
@@ -260,16 +262,29 @@ function shouldFetchRemoteSources(
260
262
  return false;
261
263
  }
262
264
 
263
- function dropCachedModelIdsOnStaticMismatch<TApi extends Api>(
265
+ function prepareCacheModelsForStaticMismatch<TApi extends Api>(
264
266
  models: readonly Model<TApi>[],
267
+ staticModels: readonly Model<TApi>[],
265
268
  cacheFingerprintMatches: boolean,
266
269
  ids: readonly string[] | undefined,
267
270
  ): Model<TApi>[] {
268
- if (cacheFingerprintMatches || ids === undefined || ids.length === 0 || models.length === 0) {
269
- return models.length === 0 ? [] : [...models];
271
+ if (models.length === 0) {
272
+ return [];
273
+ }
274
+ if (cacheFingerprintMatches) {
275
+ return [...models];
276
+ }
277
+
278
+ const droppedIds = ids && ids.length > 0 ? new Set(ids) : undefined;
279
+ const staticIds = staticModels.length > 0 ? new Set(staticModels.map(model => model.id)) : undefined;
280
+ const sanitizedModels: Model<TApi>[] = [];
281
+ for (const model of models) {
282
+ if (droppedIds?.has(model.id)) {
283
+ continue;
284
+ }
285
+ sanitizedModels.push(staticIds?.has(model.id) ? { ...model, contextWindow: null, maxTokens: null } : model);
270
286
  }
271
- const droppedIds = new Set(ids);
272
- return models.filter(model => !droppedIds.has(model.id));
287
+ return sanitizedModels;
273
288
  }
274
289
 
275
290
  function mergeModelSources<TApi extends Api>(...sources: readonly (readonly Model<TApi>[])[]): Model<TApi>[] {
@@ -318,7 +318,7 @@ function getModelDefinedEfforts<TApi extends Api>(
318
318
  }
319
319
  if (
320
320
  isZaiThinkingFormat(compat) ||
321
- isUmansGlm52ReasoningEffortModel(spec) ||
321
+ isAnthropicMessagesGlm52ReasoningEffortModel(spec) ||
322
322
  isOllamaCloudGlm52ReasoningEffortModel(spec) ||
323
323
  spec.provider === "baseten"
324
324
  ) {
@@ -394,8 +394,12 @@ function isOllamaCloudGlm52ReasoningEffortModel<TApi extends Api>(spec: ModelSpe
394
394
  return spec.api === "ollama-chat" && spec.provider === "ollama-cloud" && isGlm52ReasoningEffortModelId(spec.id);
395
395
  }
396
396
 
397
- function isUmansGlm52ReasoningEffortModel<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
398
- return spec.api === "anthropic-messages" && spec.provider === "umans" && isGlm52ReasoningEffortModelId(spec.id);
397
+ function isAnthropicMessagesGlm52ReasoningEffortModel<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
398
+ return (
399
+ spec.api === "anthropic-messages" &&
400
+ (spec.provider === "umans" || spec.provider === "zai") &&
401
+ isGlm52ReasoningEffortModelId(spec.id)
402
+ );
399
403
  }
400
404
 
401
405
  function isMinimaxReasoningModelOnAnthropicEndpoint<TApi extends Api>(spec: ModelSpec<TApi>): boolean {
@@ -617,7 +621,7 @@ function inferThinkingControlMode<TApi extends Api>(
617
621
  if (isMinimaxReasoningModelOnAnthropicEndpoint(spec)) {
618
622
  return "anthropic-adaptive";
619
623
  }
620
- if (isUmansGlm52ReasoningEffortModel(spec)) {
624
+ if (isAnthropicMessagesGlm52ReasoningEffortModel(spec)) {
621
625
  return "anthropic-budget-effort";
622
626
  }
623
627
  if (parsedModel.family === "anthropic") {
package/src/models.json CHANGED
@@ -88484,13 +88484,10 @@
88484
88484
  "contextWindow": 1000000,
88485
88485
  "maxTokens": 131072,
88486
88486
  "thinking": {
88487
- "mode": "budget",
88487
+ "mode": "anthropic-budget-effort",
88488
88488
  "efforts": [
88489
- "minimal",
88490
- "low",
88491
- "medium",
88492
88489
  "high",
88493
- "xhigh"
88490
+ "max"
88494
88491
  ]
88495
88492
  }
88496
88493
  },
@@ -42,10 +42,13 @@ export interface CursorModelManagerConfig {
42
42
  clientVersion?: string;
43
43
  }
44
44
 
45
+ const CURSOR_CACHE_PROVIDER_ID = "cursor:max-mode-v2";
46
+
45
47
  export function cursorModelManagerOptions(config: CursorModelManagerConfig = {}): ModelManagerOptions<"cursor-agent"> {
46
48
  const { apiKey, baseUrl, clientVersion } = config;
47
49
  return {
48
50
  providerId: "cursor",
51
+ cacheProviderId: CURSOR_CACHE_PROVIDER_ID,
49
52
  ...(apiKey
50
53
  ? {
51
54
  fetchDynamicModels: async () => {
package/src/types.ts CHANGED
@@ -718,6 +718,8 @@ export interface Model<TApi extends Api = Api> {
718
718
  supportsTools?: boolean;
719
719
  /** GitLab Duo Workflow root namespace selected during catalog discovery. */
720
720
  gitlabDuoWorkflowRootNamespaceId?: string;
721
+ /** Cursor `max_mode` request flag returned by `GetUsableModels` for premium models that require max mode. */
722
+ cursorMaxMode?: boolean;
721
723
  cost: {
722
724
  input: number; // $/million tokens
723
725
  output: number; // $/million tokens