@linxiraos/pi-catalog 1.1.4 → 1.1.6

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,11 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [1.1.4] - 2026-08-26
5
+ ## [1.1.6] - 2026-08-30
6
6
 
7
- ### Changed
7
+ - 同步上游 OMP v18.0.9(`cc14e04f075d`)。
8
+
9
+ ## [1.1.5] - 2026-08-26
8
10
 
9
- - 同步 1.1.4 发布线(与 1.1.3 无功能差异)。
11
+ - 同步上游 OMP v18.0.5 / v18.0.6:新增 DeepInfra / Yolo-Auto 提供商标识。
10
12
 
11
13
  ## [1.1.3] - 2026-08-25
12
14
 
@@ -145,24 +145,28 @@ export declare const supportsCodexReasoningSummary: (modelId: string) => boolean
145
145
  export declare const isOpenAISamplingRestrictedModelId: (modelId: string) => boolean;
146
146
  /**
147
147
  * Reasoning-capable GLM coding SKUs: glm-4.5 and up on the base / `-air` /
148
- * `-turbo` lines. Excludes the vision (`…v`) shape, the non-reasoning
149
- * `-flash`/`-flashx`/`-preview` variants, and pre-4.5 ids. Matching the family
150
- * keeps newly-bumped integers (`glm-5.3`, `glm-6`, …) covered without a per-id
151
- * allowlist.
148
+ * `-turbo` lines, plus `-flash` from GLM-5.3-Flash on. Excludes the vision
149
+ * (`…v`) shape, the non-reasoning `-flashx`/`-preview` variants, and pre-4.5
150
+ * ids. Matching the family keeps newly-bumped integers (`glm-5.4`, `glm-6`, …)
151
+ * covered without a per-id allowlist.
152
152
  */
153
153
  export declare const isReasoningGlmModelId: (modelId: string) => boolean;
154
154
  /** GLM-5.2+ coding SKUs accept `reasoning_effort` in addition to binary thinking. */
155
155
  export declare const isGlm52ReasoningEffortModelId: (modelId: string) => boolean;
156
156
  /**
157
- * GLM-5.3+ coding SKUs. Unlike GLM-5.2 (whose reasoning_effort dialect is
158
- * host-specific), GLM-5.3+ exposes a uniform wire-exact `low`/`high`/`max`
159
- * ladder on every host, and thinking can no longer be disabled —
160
- * `thinking.type` must always be `enabled`. Matching the family keeps future
161
- * bumps (`glm-5.4`, `glm-6`, …) covered while excluding the vision (`…v`)
162
- * shape and the non-reasoning `-flash`/`-flashx`/`-preview` variants.
157
+ * GLM-5.3+ reasoning-effort SKUs. Unlike GLM-5.2 (whose dialect is
158
+ * host-specific), the base, `-air`, `-turbo`, and `-flash` variants expose a
159
+ * uniform wire-exact `low`/`high`/`max` ladder on every host, and thinking can
160
+ * no longer be disabled — `thinking.type` must always be `enabled`. Matching
161
+ * the family keeps future bumps (`glm-5.4`, `glm-6`, …) covered while excluding
162
+ * the vision (`…v`) shape and the non-reasoning `-flashx`/`-preview` variants.
163
163
  */
164
164
  export declare const isGlm53ReasoningEffortModelId: (modelId: string) => boolean;
165
- /** GLM vision SKUs — the `v` that attaches to the version (`glm-4v`, `glm-4.5v`). */
165
+ /**
166
+ * GLM SKUs that accept image input: the `v` that attaches to the version
167
+ * (`glm-4v`, `glm-4.5v`) and the natively multimodal `-flash` line from
168
+ * GLM-5.3-Flash on, whose id carries no `v` marker.
169
+ */
166
170
  export declare const isGlmVisionModelId: (modelId: string) => boolean;
167
171
  /**
168
172
  * Coarse vendor-lineage token for "are two models the same family?" checks
@@ -11,6 +11,8 @@ export interface ModelsDevFallback<TApi extends Api = Api, TPayload = unknown> {
11
11
  fetch(): Promise<TPayload>;
12
12
  /** Maps payload into provider models. */
13
13
  map(payload: TPayload, providerId: Provider): readonly ModelSpec<TApi>[];
14
+ /** When true, mapped rows can add model ids but cannot replace static metadata. */
15
+ additiveOnly?: boolean;
14
16
  }
15
17
  /**
16
18
  * Configuration for provider model resolution.
@@ -45,18 +47,25 @@ export interface ModelManagerOptions<TApi extends Api = Api, TModelsDevPayload =
45
47
  /** Clock override for deterministic tests. */
46
48
  now?: () => number;
47
49
  }
50
+ /**
51
+ * Catalog source that most recently refreshed the resolved provider snapshot.
52
+ */
53
+ export type ModelResolutionSource = "bundled" | "cache" | "models.dev" | "provider";
48
54
  /**
49
55
  * Resolution result.
50
56
  *
51
57
  * `stale` is false when the resolved catalog is authoritative for the selected provider:
52
- * - a dynamic endpoint fetch succeeded in this call (an empty catalog is still
58
+ * - a provider endpoint fetch succeeded in this call (an empty catalog is still
53
59
  * authoritative for the cycle, so downstream pruning of removed models runs),
60
+ * - a models.dev fetch succeeded for a provider without endpoint discovery,
54
61
  * - a still-fresh authoritative cache was reused in `online-if-uncached` mode, or
55
- * - the provider has no dynamic fetcher configured.
62
+ * - the provider has no remote fetcher configured.
56
63
  */
57
64
  export interface ModelResolutionResult<TApi extends Api = Api> {
58
65
  models: Model<TApi>[];
59
66
  stale: boolean;
67
+ source: ModelResolutionSource;
68
+ updatedAt?: number;
60
69
  }
61
70
  /**
62
71
  * Stateful facade over provider model resolution.
@@ -70,8 +79,15 @@ export interface ModelManager<TApi extends Api = Api> {
70
79
  export declare function createModelManager<TApi extends Api = Api, TModelsDevPayload = unknown>(options: ModelManagerOptions<TApi, TModelsDevPayload>): ModelManager<TApi>;
71
80
  /**
72
81
  * Resolves provider models with source precedence:
73
- * static -> stencil.so -> cache -> dynamic.
82
+ * static -> cached fallback -> stencil.so -> dynamic.
74
83
  *
75
- * Later sources override earlier ones by model id.
84
+ * Later sources override earlier ones by model id. Cached rows participate only
85
+ * when at least one configured remote source did not refresh successfully.
76
86
  */
77
87
  export declare function resolveProviderModels<TApi extends Api = Api, TModelsDevPayload = unknown>(options: ModelManagerOptions<TApi, TModelsDevPayload>, strategy?: ModelRefreshStrategy): Promise<ModelResolutionResult<TApi>>;
88
+ /**
89
+ * Return the versioned, low-collision model-cache identity for a static provider
90
+ * slice. Results are cached by array reference so repeat cold-start paths skip
91
+ * the JSON serialization and hash.
92
+ */
93
+ export declare function fingerprintStaticModels<TApi extends Api>(models: readonly (ModelSpec<TApi> | Model<TApi>)[], dynamicModelsAuthoritative?: boolean): string;
@@ -97,6 +97,16 @@ export declare const CATALOG_PROVIDERS: readonly [{
97
97
  readonly envVars: readonly ["CURSOR_API_KEY"];
98
98
  readonly oauthProvider: "cursor";
99
99
  };
100
+ }, {
101
+ readonly id: "deepinfra";
102
+ readonly defaultModel: "deepseek-ai/DeepSeek-V4-Flash-0731";
103
+ readonly envVars: readonly ["DEEPINFRA_API_KEY"];
104
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
105
+ readonly dynamicModelsAuthoritative: true;
106
+ readonly catalogDiscovery: {
107
+ readonly label: "DeepInfra";
108
+ readonly allowUnauthenticated: true;
109
+ };
100
110
  }, {
101
111
  readonly id: "deepseek";
102
112
  readonly defaultModel: "deepseek-v4-pro";
@@ -361,7 +371,7 @@ export declare const CATALOG_PROVIDERS: readonly [{
361
371
  readonly dynamicModelsAuthoritative: true;
362
372
  }, {
363
373
  readonly id: "synthetic";
364
- readonly defaultModel: "hf:zai-org/GLM-5.1";
374
+ readonly defaultModel: "hf:zai-org/GLM-5.2";
365
375
  readonly envVars: readonly ["SYNTHETIC_API_KEY"];
366
376
  readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
367
377
  readonly dynamicModelsAuthoritative: true;
@@ -469,6 +479,15 @@ export declare const CATALOG_PROVIDERS: readonly [{
469
479
  readonly defaultModel: "mimo-v2.5";
470
480
  readonly envVars: readonly ["XIAOMI_TOKEN_PLAN_SGP_API_KEY"];
471
481
  readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
482
+ }, {
483
+ readonly id: "yolo-auto";
484
+ readonly defaultModel: "deepseek-flash-v4";
485
+ readonly envVars: readonly ["YOLO_AUTO_API_KEY"];
486
+ readonly createModelManagerOptions: (config: ModelManagerConfig) => import("../index.js").ModelManagerOptions<"openai-completions", unknown>;
487
+ readonly dynamicModelsAuthoritative: true;
488
+ readonly catalogDiscovery: {
489
+ readonly label: "Yolo-Auto";
490
+ };
472
491
  }, {
473
492
  readonly id: "zai";
474
493
  readonly defaultModel: "glm-5.3";
@@ -0,0 +1,8 @@
1
+ import type { Api, ModelSpec } from "../types.js";
2
+ /**
3
+ * Remove models.dev rows that OMP cannot route successfully.
4
+ *
5
+ * Generation and runtime refresh share this policy so a live catalog cannot
6
+ * reintroduce selectors deliberately excluded from the bundled catalog.
7
+ */
8
+ export declare function filterModelsDevCatalogRows<TApi extends Api>(models: readonly ModelSpec<TApi>[]): ModelSpec<TApi>[];
@@ -1,4 +1,4 @@
1
- import type { ModelManagerOptions } from "../model-manager.js";
1
+ import type { ModelManagerOptions, ModelsDevFallback } from "../model-manager.js";
2
2
  import { getBundledModels } from "../models.js";
3
3
  import type { Api, FetchImpl, ModelSpec, Provider } from "../types.js";
4
4
  import { ALIBABA_TOKEN_PLAN_BASE_URL } from "../wire/alibaba-token-plan.js";
@@ -32,9 +32,12 @@ export interface ModelsDevModel {
32
32
  * The frame magic is sniffed rather than trusting content-type so plain-JSON
33
33
  * responses (test stubs, fallback mirrors) parse identically.
34
34
  *
35
- * Fetched fully once per process: concurrent callers share the in-flight
36
- * request, repeat callers send a conditional GET that the server answers
37
- * (and deliberately does not log) with `304`.
35
+ * Fetched fully once per fetch context: concurrent callers sharing a fetch
36
+ * implementation reuse one transport request, while repeat callers send a
37
+ * conditional GET that the server answers with `304`. Each subscriber may stop
38
+ * waiting independently; the shared transport retains its own hard deadline.
39
+ * Transient failures reuse the last in-memory payload for callers that only
40
+ * need best-effort metadata.
38
41
  */
39
42
  export declare function fetchWellKnownModels(fetchImpl?: FetchImpl, signal?: AbortSignal): Promise<unknown>;
40
43
  /**
@@ -161,6 +164,19 @@ export interface NovitaModelManagerConfig {
161
164
  }
162
165
  /** Builds Novita's public model-discovery manager. */
163
166
  export declare function novitaModelManagerOptions(config?: NovitaModelManagerConfig): ModelManagerOptions<"openai-completions">;
167
+ export declare const DEEPINFRA_BASE_URL = "https://api.deepinfra.com/v1/openai";
168
+ /** DeepInfra OpenAI-compatible discovery configuration. */
169
+ export interface DeepinfraModelManagerConfig {
170
+ apiKey?: string;
171
+ baseUrl?: string;
172
+ fetch?: FetchImpl;
173
+ }
174
+ /**
175
+ * Builds DeepInfra's model-discovery manager. The catalog endpoint is public,
176
+ * so discovery (and keyless `gen:models` generation) works without an API key;
177
+ * model availability at runtime is still gated on credentials by the registry.
178
+ */
179
+ export declare function deepinfraModelManagerOptions(config?: DeepinfraModelManagerConfig): ModelManagerOptions<"openai-completions">;
164
180
  export interface XaiModelManagerConfig {
165
181
  apiKey?: string;
166
182
  baseUrl?: string;
@@ -528,6 +544,29 @@ export interface AiandModelManagerConfig {
528
544
  * pricing metadata, so discovery is authoritative over the bundled seed.
529
545
  */
530
546
  export declare function aiandModelManagerOptions(config?: AiandModelManagerConfig): ModelManagerOptions<"openai-completions">;
547
+ /**
548
+ * Documented Yolo-Auto catalog (yolo-auto.com/docs, 2026-08) bundled so the
549
+ * provider is usable when generation and first boot have no live key. The
550
+ * flat-rate `/v1/models` response is authoritative once discovery runs.
551
+ * The compat block mirrors the provider's documented wire surface: the API
552
+ * speaks the generic chat template with `reasoning_effort` support and rejects
553
+ * the `developer` role and `store` param.
554
+ */
555
+ export declare const YOLO_AUTO_STATIC_MODELS: readonly ModelSpec<"openai-completions">[];
556
+ export interface YoloAutoModelManagerConfig {
557
+ apiKey?: string;
558
+ baseUrl?: string;
559
+ fetch?: FetchImpl;
560
+ }
561
+ /**
562
+ * Yolo-Auto model manager: OpenAI-compatible chat completions at the
563
+ * flat-rate `deepseek-flash-v4` endpoint. Live `/v1/models` discovery replaces the
564
+ * bundled seed once a key is stored or present in `YOLO_AUTO_API_KEY`. Models
565
+ * the provider adds later inherit metadata (reasoning, thinking, context)
566
+ * from the global bundled reference index, so new ids work without a per-id
567
+ * code change.
568
+ */
569
+ export declare function yoloAutoModelManagerOptions(config?: YoloAutoModelManagerConfig): ModelManagerOptions<"openai-completions">;
531
570
  export interface QwenPortalModelManagerConfig {
532
571
  apiKey?: string;
533
572
  baseUrl?: string;
@@ -649,3 +688,16 @@ export interface ModelsDevProviderDescriptor {
649
688
  export declare function mapModelsDevToModels(data: Record<string, unknown>, descriptors: readonly ModelsDevProviderDescriptor[]): ModelSpec<Api>[];
650
689
  /** All provider descriptors for models.dev data mapping in generate-models.ts. */
651
690
  export declare const MODELS_DEV_PROVIDER_DESCRIPTORS: readonly ModelsDevProviderDescriptor[];
691
+ /** Providers whose bundled catalog can receive additive models.dev updates at runtime. */
692
+ export declare const MODELS_DEV_CATALOG_PROVIDER_IDS: readonly string[];
693
+ /**
694
+ * Build the shared models.dev fallback for one known provider.
695
+ *
696
+ * Provider managers sharing one fetch implementation reuse its conditional
697
+ * catalog session. Each mapped provider slice is persisted independently so
698
+ * startup can restore it without parsing the full catalog.
699
+ *
700
+ * `timeoutMs` bounds the catalog request. It is configurable for callers with a
701
+ * stricter startup budget and for deterministic timeout tests.
702
+ */
703
+ export declare function modelsDevCatalogFallback(providerId: string, fetchImpl?: FetchImpl, timeoutMs?: number): ModelsDevFallback<Api> | undefined;
@@ -121,8 +121,8 @@ export interface Usage {
121
121
  total: number;
122
122
  };
123
123
  }
124
- export type OpenAIReasoningFormat = "openai" | "openrouter" | "zai" | "kimi" | "qwen" | "qwen-chat-template";
125
- export type OpenAIReasoningDisableMode = "omit" | "lowest-effort" | "none-effort" | "openrouter-enabled-false" | "venice-disable-thinking" | "zai-thinking-disabled" | "qwen-enable-thinking-false" | "qwen-template-false";
124
+ export type OpenAIReasoningFormat = "openai" | "openrouter" | "zai" | "kimi" | "qwen" | "qwen-chat-template" | "chat-template";
125
+ export type OpenAIReasoningDisableMode = "omit" | "lowest-effort" | "none-effort" | "openrouter-enabled-false" | "venice-disable-thinking" | "zai-thinking-disabled" | "qwen-enable-thinking-false" | "qwen-template-false" | "chat-template-thinking-false";
126
126
  export type OpenAIStreamMarkupHealingPattern = "kimi" | "dsml" | "qwen" | "thinking";
127
127
  /**
128
128
  * Compatibility settings for openai-completions API.
@@ -0,0 +1,18 @@
1
+ /** Provider-native AI Gateway prefix before the upstream route segment. */
2
+ export declare const CLOUDFLARE_AI_GATEWAY_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>";
3
+ /** Anthropic Messages passthrough endpoint. */
4
+ export declare const CLOUDFLARE_AI_GATEWAY_ANTHROPIC_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/anthropic";
5
+ /** OpenAI Responses passthrough endpoint. */
6
+ export declare const CLOUDFLARE_AI_GATEWAY_OPENAI_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/openai";
7
+ /** OpenAI-compatible Workers AI endpoint. */
8
+ export declare const CLOUDFLARE_AI_GATEWAY_COMPAT_BASE_URL = "https://gateway.ai.cloudflare.com/v1/<account>/<gateway>/compat";
9
+ /** Opaque API-key credential payload persisted by Cloudflare AI Gateway login. */
10
+ export interface CloudflareAiGatewayCredential {
11
+ token: string;
12
+ accountId?: string;
13
+ gatewayId?: string;
14
+ }
15
+ /** Parse both structured login credentials and legacy plain gateway tokens. */
16
+ export declare function parseCloudflareAiGatewayCredential(value: string): CloudflareAiGatewayCredential | null;
17
+ /** Serialize the gateway token with the routing identifiers collected during login. */
18
+ export declare function serializeCloudflareAiGatewayCredential(token: string, accountId: string, gatewayId: string): string;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@linxiraos/pi-catalog",
4
- "version": "1.1.4",
5
- "description": "Model catalog for Zeta: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
4
+ "version": "1.1.6",
5
+ "description": "Model catalog for omp: bundled model database, provider discovery descriptors, model identity, classification, and equivalence",
6
6
  "homepage": "https://linxira-os.github.io/zeta/",
7
7
  "author": "Can Boluk",
8
8
  "license": "MIT",
@@ -34,11 +34,11 @@
34
34
  "gen:proto": "bun scripts/generate-protocols.ts"
35
35
  },
36
36
  "dependencies": {
37
- "@linxiraos/pi-omptype": "1.1.4",
38
- "@linxiraos/pi-utils": "1.1.4"
37
+ "@linxiraos/pi-omptype": "1.1.6",
38
+ "@linxiraos/pi-utils": "1.1.6"
39
39
  },
40
40
  "devDependencies": {
41
- "@linxiraos/pi-ai": "1.1.4",
41
+ "@linxiraos/pi-ai": "1.1.6",
42
42
  "@types/bun": "^1.3.14"
43
43
  },
44
44
  "engines": {
@@ -94,6 +94,8 @@ function resolveReasoningDisableMode(
94
94
  return "qwen-enable-thinking-false";
95
95
  case "qwen-chat-template":
96
96
  return "qwen-template-false";
97
+ case "chat-template":
98
+ return "chat-template-thinking-false";
97
99
  default:
98
100
  return "lowest-effort";
99
101
  }
@@ -9,6 +9,7 @@
9
9
 
10
10
  import {
11
11
  bareModelId,
12
+ type GlmModel,
12
13
  isAnthropicAdaptiveGenAtLeast,
13
14
  isFableOrMythos,
14
15
  parseAnthropicModel,
@@ -283,19 +284,35 @@ export const isOpenAISamplingRestrictedModelId = memo((modelId: string): boolean
283
284
  return isOpenAIWireGen5Plus(modelId) || O_SERIES_REASONING_RE.test(bare);
284
285
  });
285
286
 
287
+ /**
288
+ * GLM SKU shapes that carry the reasoning ladders. `base`/`air`/`turbo` have
289
+ * always been reasoning lines; `flash` joins at GLM-5.3-Flash, the first flash
290
+ * SKU whose thinking is mandatory (pre-5.3 `-flash` SKUs are non-reasoning).
291
+ * `flashx` and `preview` stay out.
292
+ */
293
+ function isGlmReasoningVariant(glm: GlmModel): boolean {
294
+ switch (glm.variant) {
295
+ case "base":
296
+ case "air":
297
+ case "turbo":
298
+ return true;
299
+ case "flash":
300
+ return semverGte(glm.version, "5.3");
301
+ default:
302
+ return false;
303
+ }
304
+ }
305
+
286
306
  /**
287
307
  * Reasoning-capable GLM coding SKUs: glm-4.5 and up on the base / `-air` /
288
- * `-turbo` lines. Excludes the vision (`…v`) shape, the non-reasoning
289
- * `-flash`/`-flashx`/`-preview` variants, and pre-4.5 ids. Matching the family
290
- * keeps newly-bumped integers (`glm-5.3`, `glm-6`, …) covered without a per-id
291
- * allowlist.
308
+ * `-turbo` lines, plus `-flash` from GLM-5.3-Flash on. Excludes the vision
309
+ * (`…v`) shape, the non-reasoning `-flashx`/`-preview` variants, and pre-4.5
310
+ * ids. Matching the family keeps newly-bumped integers (`glm-5.4`, `glm-6`, …)
311
+ * covered without a per-id allowlist.
292
312
  */
293
313
  export const isReasoningGlmModelId = memo((modelId: string): boolean => {
294
314
  const glm = parseGlmModel(bareModelId(modelId));
295
- if (!glm || glm.vision) {
296
- return false;
297
- }
298
- if (glm.variant !== "base" && glm.variant !== "air" && glm.variant !== "turbo") {
315
+ if (!glm || glm.vision || !isGlmReasoningVariant(glm)) {
299
316
  return false;
300
317
  }
301
318
  return semverGte(glm.version, "4.5");
@@ -304,37 +321,39 @@ export const isReasoningGlmModelId = memo((modelId: string): boolean => {
304
321
  /** GLM-5.2+ coding SKUs accept `reasoning_effort` in addition to binary thinking. */
305
322
  export const isGlm52ReasoningEffortModelId = memo((modelId: string): boolean => {
306
323
  const glm = parseGlmModel(bareModelId(modelId));
307
- if (!glm || glm.vision) {
308
- return false;
309
- }
310
- if (glm.variant !== "base" && glm.variant !== "air" && glm.variant !== "turbo") {
324
+ if (!glm || glm.vision || !isGlmReasoningVariant(glm)) {
311
325
  return false;
312
326
  }
313
327
  return semverGte(glm.version, "5.2");
314
328
  });
315
329
 
316
330
  /**
317
- * GLM-5.3+ coding SKUs. Unlike GLM-5.2 (whose reasoning_effort dialect is
318
- * host-specific), GLM-5.3+ exposes a uniform wire-exact `low`/`high`/`max`
319
- * ladder on every host, and thinking can no longer be disabled —
320
- * `thinking.type` must always be `enabled`. Matching the family keeps future
321
- * bumps (`glm-5.4`, `glm-6`, …) covered while excluding the vision (`…v`)
322
- * shape and the non-reasoning `-flash`/`-flashx`/`-preview` variants.
331
+ * GLM-5.3+ reasoning-effort SKUs. Unlike GLM-5.2 (whose dialect is
332
+ * host-specific), the base, `-air`, `-turbo`, and `-flash` variants expose a
333
+ * uniform wire-exact `low`/`high`/`max` ladder on every host, and thinking can
334
+ * no longer be disabled — `thinking.type` must always be `enabled`. Matching
335
+ * the family keeps future bumps (`glm-5.4`, `glm-6`, …) covered while excluding
336
+ * the vision (`…v`) shape and the non-reasoning `-flashx`/`-preview` variants.
323
337
  */
324
338
  export const isGlm53ReasoningEffortModelId = memo((modelId: string): boolean => {
325
339
  const glm = parseGlmModel(bareModelId(modelId));
326
- if (!glm || glm.vision) {
327
- return false;
328
- }
329
- if (glm.variant !== "base" && glm.variant !== "air" && glm.variant !== "turbo") {
340
+ if (!glm || glm.vision || !isGlmReasoningVariant(glm)) {
330
341
  return false;
331
342
  }
332
343
  return semverGte(glm.version, "5.3");
333
344
  });
334
345
 
335
- /** GLM vision SKUs — the `v` that attaches to the version (`glm-4v`, `glm-4.5v`). */
346
+ /**
347
+ * GLM SKUs that accept image input: the `v` that attaches to the version
348
+ * (`glm-4v`, `glm-4.5v`) and the natively multimodal `-flash` line from
349
+ * GLM-5.3-Flash on, whose id carries no `v` marker.
350
+ */
336
351
  export const isGlmVisionModelId = memo((modelId: string): boolean => {
337
- return parseGlmModel(bareModelId(modelId))?.vision === true;
352
+ const glm = parseGlmModel(bareModelId(modelId));
353
+ if (!glm) {
354
+ return false;
355
+ }
356
+ return glm.vision || (glm.variant === "flash" && semverGte(glm.version, "5.3"));
338
357
  });
339
358
 
340
359
  /**
@@ -22,6 +22,7 @@ const DEFAULT_MODEL_PROVIDER_ORDER = [
22
22
  "fireworks",
23
23
  "cerebras",
24
24
  "baseten",
25
+ "deepinfra",
25
26
  "openrouter",
26
27
  "aimlapi",
27
28
  "together",