@oh-my-pi/pi-catalog 16.0.5 → 16.0.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.
@@ -1,4 +1,4 @@
1
- import { z } from "zod/v4";
1
+ import { type } from "arktype";
2
2
  import type { ModelSpec } from "../types";
3
3
  import { toPositiveNumber } from "../utils";
4
4
  import {
@@ -56,94 +56,78 @@ export interface AntigravityDiscoveryApiResponse {
56
56
  models?: Record<string, AntigravityDiscoveryApiModel>;
57
57
  agentModelSorts?: AntigravityDiscoveryAgentModelSort[];
58
58
  }
59
- const AntigravityDiscoveryApiModelSchema: z.ZodType<AntigravityDiscoveryApiModel> = z
60
- .object({
61
- displayName: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
62
- supportsImages: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
63
- supportsThinking: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
64
- thinkingBudget: z.preprocess(
65
- value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
66
- z.number().optional(),
67
- ),
68
- recommended: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
69
- maxTokens: z.preprocess(
70
- value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
71
- z.number().optional(),
72
- ),
73
- maxOutputTokens: z.preprocess(
74
- value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
75
- z.number().optional(),
76
- ),
77
- model: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
78
- apiProvider: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
79
- modelProvider: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
80
- isInternal: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
81
- supportsVideo: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
82
- })
83
- .loose();
84
- const AntigravityDiscoveryAgentModelGroupSchema: z.ZodType<AntigravityDiscoveryAgentModelGroup> = z
85
- .object({
86
- modelIds: z.preprocess(
87
- value =>
88
- Array.isArray(value)
89
- ? value.filter((modelId): modelId is string => typeof modelId === "string")
90
- : undefined,
91
- z.array(z.string()).optional(),
92
- ),
93
- })
94
- .loose();
95
- const AntigravityDiscoveryAgentModelSortSchema: z.ZodType<AntigravityDiscoveryAgentModelSort> = z
96
- .object({
97
- groups: z.preprocess(
98
- value => (Array.isArray(value) ? value : undefined),
99
- z
100
- .array(z.unknown())
101
- .transform(groups =>
102
- groups.flatMap(group => {
103
- const parsedGroup = AntigravityDiscoveryAgentModelGroupSchema.safeParse(group);
104
- return parsedGroup.success ? [parsedGroup.data] : [];
105
- }),
106
- )
107
- .optional(),
108
- ),
109
- })
110
- .loose();
111
- const AntigravityDiscoveryApiResponseSchema: z.ZodType<AntigravityDiscoveryApiResponse> = z
112
- .object({
113
- models: z.preprocess(
114
- value => (typeof value === "object" && value !== null ? value : undefined),
115
- z
116
- .record(z.string(), z.unknown())
117
- .transform(models => {
118
- const normalized: Record<string, AntigravityDiscoveryApiModel> = {};
119
- for (const [modelId, modelValue] of Object.entries(models)) {
120
- if (typeof modelValue !== "object" || modelValue === null) {
121
- continue;
122
- }
123
- const parsedModel = AntigravityDiscoveryApiModelSchema.safeParse(modelValue);
124
- if (parsedModel.success) {
125
- normalized[modelId] = parsedModel.data;
126
- }
127
- }
128
- return normalized;
129
- })
130
- .optional(),
131
- ),
132
- agentModelSorts: z.preprocess(
133
- value => (Array.isArray(value) ? value : undefined),
134
- z
135
- .array(z.unknown())
136
- .transform(sorts =>
137
- sorts.flatMap(sort => {
138
- const parsedSort = AntigravityDiscoveryAgentModelSortSchema.safeParse(sort);
139
- return parsedSort.success ? [parsedSort.data] : [];
140
- }),
141
- )
142
- .optional(),
143
- ),
144
- })
145
- .loose();
146
-
59
+ const AntigravityDiscoveryApiModelSchema = type({
60
+ "displayName?": type("unknown").pipe(value => (typeof value === "string" ? value : undefined)),
61
+ "supportsImages?": type("unknown").pipe(value => (typeof value === "boolean" ? value : undefined)),
62
+ "supportsThinking?": type("unknown").pipe(value => (typeof value === "boolean" ? value : undefined)),
63
+ "thinkingBudget?": type("unknown").pipe(value =>
64
+ typeof value === "number" && Number.isFinite(value) ? value : undefined,
65
+ ),
66
+ "recommended?": type("unknown").pipe(value => (typeof value === "boolean" ? value : undefined)),
67
+ "maxTokens?": type("unknown").pipe(value =>
68
+ typeof value === "number" && Number.isFinite(value) ? value : undefined,
69
+ ),
70
+ "maxOutputTokens?": type("unknown").pipe(value =>
71
+ typeof value === "number" && Number.isFinite(value) ? value : undefined,
72
+ ),
73
+ "model?": type("unknown").pipe(value => (typeof value === "string" ? value : undefined)),
74
+ "apiProvider?": type("unknown").pipe(value => (typeof value === "string" ? value : undefined)),
75
+ "modelProvider?": type("unknown").pipe(value => (typeof value === "string" ? value : undefined)),
76
+ "isInternal?": type("unknown").pipe(value => (typeof value === "boolean" ? value : undefined)),
77
+ "supportsVideo?": type("unknown").pipe(value => (typeof value === "boolean" ? value : undefined)),
78
+ });
79
+
80
+ const AntigravityDiscoveryAgentModelGroupSchema = type({
81
+ "modelIds?": type("unknown").pipe(value =>
82
+ Array.isArray(value) ? value.filter((modelId): modelId is string => typeof modelId === "string") : undefined,
83
+ ),
84
+ });
85
+
86
+ const AntigravityDiscoveryAgentModelSortSchema = type({
87
+ "groups?": type("unknown").pipe(value => {
88
+ if (!Array.isArray(value)) return undefined;
89
+ const result: AntigravityDiscoveryAgentModelGroup[] = [];
90
+ for (const group of value) {
91
+ const parsedGroup = AntigravityDiscoveryAgentModelGroupSchema(group);
92
+ if (!(parsedGroup instanceof type.errors)) {
93
+ result.push(parsedGroup);
94
+ }
95
+ }
96
+ return result;
97
+ }),
98
+ });
99
+
100
+ const AntigravityDiscoveryApiResponseSchema = type({
101
+ "models?": type("unknown").pipe(value => {
102
+ if (typeof value !== "object" || value === null) {
103
+ return undefined;
104
+ }
105
+ const normalized: Record<string, AntigravityDiscoveryApiModel> = {};
106
+ for (const [modelId, modelValue] of Object.entries(value)) {
107
+ if (typeof modelValue !== "object" || modelValue === null) {
108
+ continue;
109
+ }
110
+ const parsedModel = AntigravityDiscoveryApiModelSchema(modelValue);
111
+ if (!(parsedModel instanceof type.errors)) {
112
+ normalized[modelId] = parsedModel;
113
+ }
114
+ }
115
+ return normalized;
116
+ }),
117
+ "agentModelSorts?": type("unknown").pipe(value => {
118
+ if (!Array.isArray(value)) {
119
+ return undefined;
120
+ }
121
+ const result: AntigravityDiscoveryAgentModelSort[] = [];
122
+ for (const sort of value) {
123
+ const parsedSort = AntigravityDiscoveryAgentModelSortSchema(sort);
124
+ if (!(parsedSort instanceof type.errors)) {
125
+ result.push(parsedSort);
126
+ }
127
+ }
128
+ return result;
129
+ }),
130
+ });
147
131
  /**
148
132
  * Options for fetching Antigravity discovery models.
149
133
  */
@@ -257,11 +241,11 @@ export async function fetchAntigravityDiscoveryModels(
257
241
  }
258
242
 
259
243
  function parseAntigravityDiscoveryResponse(value: unknown): AntigravityDiscoveryApiResponse | null {
260
- const parsed = AntigravityDiscoveryApiResponseSchema.safeParse(value);
261
- if (!parsed.success) {
244
+ const parsed = AntigravityDiscoveryApiResponseSchema(value);
245
+ if (parsed instanceof type.errors) {
262
246
  return null;
263
247
  }
264
- return parsed.data;
248
+ return parsed;
265
249
  }
266
250
 
267
251
  function trimTrailingSlashes(value: string): string {
@@ -1,4 +1,4 @@
1
- import { z } from "zod/v4";
1
+ import { type } from "arktype";
2
2
  import type { ModelSpec } from "../types";
3
3
  import { isRecord } from "../utils";
4
4
  import { CODEX_BASE_URL, OPENAI_HEADER_VALUES, OPENAI_HEADERS } from "../wire/codex";
@@ -9,36 +9,29 @@ const DEFAULT_MAX_TOKENS = 128_000;
9
9
  const DEFAULT_CODEX_CLIENT_VERSION = "0.99.0";
10
10
  const NPM_CODEX_LATEST_URL = "https://registry.npmjs.org/@openai%2Fcodex/latest";
11
11
 
12
- const codexReasoningPresetSchema = z
13
- .object({
14
- effort: z.unknown().optional(),
15
- })
16
- .loose();
17
-
18
- const codexModelEntrySchema = z
19
- .object({
20
- slug: z.unknown().optional(),
21
- id: z.unknown().optional(),
22
- display_name: z.unknown().optional(),
23
- context_window: z.unknown().optional(),
24
- default_reasoning_level: z.unknown().optional(),
25
- supported_reasoning_levels: z.unknown().optional(),
26
- input_modalities: z.unknown().optional(),
27
- supported_in_api: z.unknown().optional(),
28
- priority: z.unknown().optional(),
29
- prefer_websockets: z.unknown().optional(),
30
- })
31
- .loose();
32
-
33
- const codexModelsResponseSchema = z
34
- .object({
35
- models: z.array(z.unknown()).optional(),
36
- data: z.array(z.unknown()).optional(),
37
- })
38
- .loose();
39
-
40
- type CodexModelEntry = z.infer<typeof codexModelEntrySchema>;
41
-
12
+ const codexReasoningPresetSchema = type({
13
+ "effort?": "unknown",
14
+ });
15
+
16
+ const codexModelEntrySchema = type({
17
+ "slug?": "unknown",
18
+ "id?": "unknown",
19
+ "display_name?": "unknown",
20
+ "context_window?": "unknown",
21
+ "default_reasoning_level?": "unknown",
22
+ "supported_reasoning_levels?": "unknown",
23
+ "input_modalities?": "unknown",
24
+ "supported_in_api?": "unknown",
25
+ "priority?": "unknown",
26
+ "prefer_websockets?": "unknown",
27
+ });
28
+
29
+ const codexModelsResponseSchema = type({
30
+ "models?": "unknown[]",
31
+ "data?": "unknown[]",
32
+ });
33
+
34
+ type CodexModelEntry = typeof codexModelEntrySchema.infer;
42
35
  interface NormalizedCodexModel {
43
36
  model: ModelSpec<"openai-codex-responses">;
44
37
  priority: number;
@@ -216,12 +209,12 @@ function isAbortError(error: unknown): error is Error {
216
209
  }
217
210
 
218
211
  function normalizeCodexModels(payload: unknown, baseUrl: string): ModelSpec<"openai-codex-responses">[] | null {
219
- const parsedResponse = codexModelsResponseSchema.safeParse(payload);
220
- if (!parsedResponse.success) {
212
+ const parsedResponse = codexModelsResponseSchema(payload);
213
+ if (parsedResponse instanceof type.errors) {
221
214
  return null;
222
215
  }
223
216
 
224
- const entries = parsedResponse.data.models ?? parsedResponse.data.data ?? [];
217
+ const entries = parsedResponse.models ?? parsedResponse.data ?? [];
225
218
  const normalized: NormalizedCodexModel[] = [];
226
219
  for (const entry of entries) {
227
220
  const model = normalizeCodexModelEntry(entry, baseUrl);
@@ -241,12 +234,12 @@ function normalizeCodexModels(payload: unknown, baseUrl: string): ModelSpec<"ope
241
234
  }
242
235
 
243
236
  function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCodexModel | null {
244
- const parsedEntry = codexModelEntrySchema.safeParse(entry);
245
- if (!parsedEntry.success) {
237
+ const parsedEntry = codexModelEntrySchema(entry);
238
+ if (parsedEntry instanceof type.errors) {
246
239
  return null;
247
240
  }
248
241
 
249
- const payload: CodexModelEntry = parsedEntry.data;
242
+ const payload: CodexModelEntry = parsedEntry;
250
243
  const slug = toNonEmptyString(payload.slug) ?? toNonEmptyString(payload.id);
251
244
  if (!slug) {
252
245
  return null;
@@ -295,11 +288,11 @@ function supportsReasoning(defaultReasoningLevel: unknown, supportedReasoningLev
295
288
  }
296
289
 
297
290
  for (const level of supportedReasoningLevels) {
298
- const parsedLevel = codexReasoningPresetSchema.safeParse(level);
299
- if (!parsedLevel.success) {
291
+ const parsedLevel = codexReasoningPresetSchema(level);
292
+ if (parsedLevel instanceof type.errors) {
300
293
  continue;
301
294
  }
302
- const effort = toNonEmptyString(parsedLevel.data.effort)?.toLowerCase();
295
+ const effort = toNonEmptyString(parsedLevel.effort)?.toLowerCase();
303
296
  if (effort && effort !== "none") {
304
297
  return true;
305
298
  }
@@ -1,6 +1,6 @@
1
1
  import * as http2 from "node:http2";
2
2
  import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
3
- import { z } from "zod/v4";
3
+ import { type } from "arktype";
4
4
  import { getBundledModels } from "../models";
5
5
  import { toModelSpec } from "../provider-models/bundled-references";
6
6
  import type { Model, ModelSpec } from "../types";
@@ -13,27 +13,34 @@ 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
- const OptionalDisplayNameSchema = z.string().optional().catch(undefined);
17
- const CursorAliasesSchema = z
18
- .array(z.unknown())
19
- .optional()
20
- .catch([])
21
- .transform(aliases => (aliases ?? []).filter((alias: unknown): alias is string => typeof alias === "string"));
22
-
23
- const CursorModelDetailsSchema = z.object({
24
- modelId: z.string(),
25
- displayName: OptionalDisplayNameSchema,
26
- displayNameShort: OptionalDisplayNameSchema,
27
- displayModelId: OptionalDisplayNameSchema,
28
- aliases: CursorAliasesSchema,
29
- thinkingDetails: z.unknown().optional(),
16
+ const OptionalDisplayNameSchema = type("unknown").pipe(raw => (typeof raw === "string" ? raw : undefined));
17
+ const CursorAliasesSchema = type("unknown").pipe(raw => {
18
+ if (Array.isArray(raw)) {
19
+ return raw.filter((alias: unknown): alias is string => typeof alias === "string");
20
+ }
21
+ return [];
22
+ });
23
+
24
+ const CursorModelDetailsSchema = type({
25
+ modelId: "string",
26
+ displayName: OptionalDisplayNameSchema.default(undefined),
27
+ displayNameShort: OptionalDisplayNameSchema.default(undefined),
28
+ displayModelId: OptionalDisplayNameSchema.default(undefined),
29
+ aliases: CursorAliasesSchema.default(() => []),
30
+ "thinkingDetails?": "unknown",
31
+ });
32
+
33
+ const CursorModelsInnerSchema = type("unknown[]");
34
+ const ResilientCursorModelsSchema = type("unknown").pipe(raw => {
35
+ const out = CursorModelsInnerSchema(raw);
36
+ return out instanceof type.errors ? [] : out;
30
37
  });
31
38
 
32
- const CursorDecodedResponseSchema = z.object({
33
- models: z.array(z.unknown()).optional().catch([]),
39
+ const CursorDecodedResponseSchema = type({
40
+ models: ResilientCursorModelsSchema.default(() => []),
34
41
  });
35
42
 
36
- type CursorModelDetailsValue = z.infer<typeof CursorModelDetailsSchema>;
43
+ type CursorModelDetailsValue = typeof CursorModelDetailsSchema.infer;
37
44
 
38
45
  /**
39
46
  * Options for fetching dynamic Cursor models from `GetUsableModels`.
@@ -74,13 +81,13 @@ export async function fetchCursorUsableModels(
74
81
  return null;
75
82
  }
76
83
  const decoded = decodeGetUsableModelsResponse(responseBuffer);
77
- const parsedDecoded = CursorDecodedResponseSchema.safeParse(decoded);
78
- if (!parsedDecoded.success) {
84
+ const parsedDecoded = CursorDecodedResponseSchema(decoded);
85
+ if (parsedDecoded instanceof type.errors) {
79
86
  return null;
80
87
  }
81
88
 
82
89
  const references = createCursorReferenceMap();
83
- return normalizeCursorModels(parsedDecoded.data.models, options.baseUrl, references);
90
+ return normalizeCursorModels(parsedDecoded.models, options.baseUrl, references);
84
91
  } catch {
85
92
  return null;
86
93
  }
@@ -254,12 +261,12 @@ function normalizeCursorModel(
254
261
  baseUrlOverride: string | undefined,
255
262
  references: Map<string, ModelSpec<"cursor-agent">>,
256
263
  ): ModelSpec<"cursor-agent"> | null {
257
- const parsedModel = CursorModelDetailsSchema.safeParse(model);
258
- if (!parsedModel.success) {
264
+ const parsedModel = CursorModelDetailsSchema(model);
265
+ if (parsedModel instanceof type.errors) {
259
266
  return null;
260
267
  }
261
268
 
262
- const details = parsedModel.data;
269
+ const details = parsedModel;
263
270
  const id = details.modelId.trim();
264
271
  if (!id) {
265
272
  return null;
@@ -1,4 +1,4 @@
1
- import { z } from "zod/v4";
1
+ import { type } from "arktype";
2
2
  import { getBundledModels } from "../models";
3
3
  import { toModelSpec } from "../provider-models/bundled-references";
4
4
  import type { FetchImpl, Model, ModelSpec } from "../types";
@@ -7,36 +7,45 @@ const GOOGLE_GENERATIVE_AI_BASE_URL = "https://generativelanguage.googleapis.com
7
7
  const DEFAULT_PAGE_SIZE = 100;
8
8
  const DEFAULT_MAX_PAGES = 25;
9
9
 
10
- const geminiModelListItemSchema = z.object({
11
- name: z.string().optional().catch(undefined),
12
- displayName: z.string().optional().catch(undefined),
13
- supportedGenerationMethods: z.array(z.string()).optional(),
14
- inputTokenLimit: z.number().finite().optional().catch(undefined),
15
- outputTokenLimit: z.number().finite().optional().catch(undefined),
10
+ const resilientString = type("unknown").pipe(val => {
11
+ if (val === undefined) return undefined;
12
+ const out = type("string")(val);
13
+ return out instanceof type.errors ? undefined : out;
16
14
  });
17
15
 
18
- const geminiModelListResponseSchema = z.object({
19
- models: z
20
- .array(z.unknown())
21
- .optional()
22
- .transform(items => {
23
- if (!items) {
24
- return [];
25
- }
26
- const parsedItems: GeminiModelListItem[] = [];
27
- for (const item of items) {
28
- const parsed = geminiModelListItemSchema.safeParse(item);
29
- if (parsed.success) {
30
- parsedItems.push(parsed.data);
31
- }
32
- }
33
- return parsedItems;
34
- }),
35
- nextPageToken: z.string().optional().catch(undefined),
16
+ const resilientNumber = type("unknown").pipe(val => {
17
+ if (val === undefined) return undefined;
18
+ const out = type("number")(val);
19
+ return out instanceof type.errors ? undefined : out;
20
+ });
21
+
22
+ const geminiModelListItemSchema = type({
23
+ "name?": resilientString,
24
+ "displayName?": resilientString,
25
+ "supportedGenerationMethods?": "string[]",
26
+ "inputTokenLimit?": resilientNumber,
27
+ "outputTokenLimit?": resilientNumber,
36
28
  });
37
29
 
38
- type GeminiModelListItem = z.infer<typeof geminiModelListItemSchema>;
30
+ type GeminiModelListItem = typeof geminiModelListItemSchema.infer;
39
31
 
32
+ const modelsSchema = type("unknown[]")
33
+ .pipe(items => {
34
+ const parsedItems: GeminiModelListItem[] = [];
35
+ for (const item of items) {
36
+ const parsed = geminiModelListItemSchema(item);
37
+ if (!(parsed instanceof type.errors)) {
38
+ parsedItems.push(parsed);
39
+ }
40
+ }
41
+ return parsedItems;
42
+ })
43
+ .default(() => []);
44
+
45
+ const geminiModelListResponseSchema = type({
46
+ models: modelsSchema,
47
+ "nextPageToken?": resilientString,
48
+ });
40
49
  /**
41
50
  * Configuration for Google Generative AI model discovery.
42
51
  */
@@ -103,19 +112,19 @@ export async function fetchGeminiModels(
103
112
  return null;
104
113
  }
105
114
 
106
- const parsed = geminiModelListResponseSchema.safeParse(payload);
107
- if (!parsed.success) {
115
+ const parsed = geminiModelListResponseSchema(payload);
116
+ if (parsed instanceof type.errors) {
108
117
  return null;
109
118
  }
110
119
 
111
- for (const item of parsed.data.models) {
120
+ for (const item of parsed.models) {
112
121
  const model = normalizeModel(item, baseUrl, bundledById);
113
122
  if (model) {
114
123
  modelsById.set(model.id, model);
115
124
  }
116
125
  }
117
126
 
118
- const token = normalizePageToken(parsed.data.nextPageToken);
127
+ const token = normalizePageToken(parsed.nextPageToken);
119
128
  if (!token) {
120
129
  break;
121
130
  }
@@ -1,4 +1,4 @@
1
- import { z } from "zod/v4";
1
+ import { type } from "arktype";
2
2
  import type { Api, FetchImpl, ModelSpec, Provider } from "../types";
3
3
 
4
4
  const MODELS_PATH = "/models";
@@ -32,28 +32,23 @@ export interface OpenAICompatibleModelsEnvelope {
32
32
  [key: string]: unknown;
33
33
  }
34
34
 
35
- const openAICompatibleModelRecordSchema = z
36
- .object({
37
- id: z.string().min(1),
38
- name: z.string().optional().nullable(),
39
- object: z.unknown().optional(),
40
- owned_by: z.unknown().optional(),
41
- })
42
- .loose();
35
+ const openAICompatibleModelRecordSchema = type({
36
+ id: "string >= 1",
37
+ "name?": "string | null",
38
+ "object?": "unknown",
39
+ "owned_by?": "unknown",
40
+ });
43
41
 
44
- const openAICompatibleModelsEnvelopeSchema = z
45
- .object({
46
- data: z.unknown().optional(),
47
- models: z.unknown().optional(),
48
- result: z.unknown().optional(),
49
- items: z.unknown().optional(),
50
- })
51
- .loose();
42
+ const openAICompatibleModelsEnvelopeSchema = type({
43
+ "data?": "unknown",
44
+ "models?": "unknown",
45
+ "result?": "unknown",
46
+ "items?": "unknown",
47
+ });
52
48
 
53
- const openAICompatibleModelsPayloadSchema = z.union([z.array(z.unknown()), openAICompatibleModelsEnvelopeSchema]);
54
-
55
- type ParsedOpenAICompatibleModelRecord = z.infer<typeof openAICompatibleModelRecordSchema>;
49
+ const openAICompatibleModelsPayloadSchema = type("unknown[]").or(openAICompatibleModelsEnvelopeSchema);
56
50
 
51
+ type ParsedOpenAICompatibleModelRecord = typeof openAICompatibleModelRecordSchema.infer;
57
52
  /**
58
53
  * Context passed to custom OpenAI-compatible model mappers.
59
54
  */
@@ -196,22 +191,17 @@ function extractModelEntries(payload: unknown): ParsedOpenAICompatibleModelRecor
196
191
  }
197
192
 
198
193
  function extractModelEntriesFromNode(node: unknown): ParsedOpenAICompatibleModelRecord[] | null {
199
- const parsedPayload = openAICompatibleModelsPayloadSchema.safeParse(node);
200
- if (!parsedPayload.success) {
194
+ const parsedPayload = openAICompatibleModelsPayloadSchema(node);
195
+ if (parsedPayload instanceof type.errors) {
201
196
  return null;
202
197
  }
203
- if (Array.isArray(parsedPayload.data)) {
204
- const parsedEntries = parsedPayload.data
205
- .map(entry => openAICompatibleModelRecordSchema.safeParse(entry))
206
- .flatMap(entry => (entry.success ? [entry.data] : []));
198
+ if (Array.isArray(parsedPayload)) {
199
+ const parsedEntries = parsedPayload
200
+ .map(entry => openAICompatibleModelRecordSchema(entry))
201
+ .flatMap(entry => (entry instanceof type.errors ? [] : [entry]));
207
202
  return parsedEntries;
208
203
  }
209
- for (const candidate of [
210
- parsedPayload.data.data,
211
- parsedPayload.data.models,
212
- parsedPayload.data.result,
213
- parsedPayload.data.items,
214
- ]) {
204
+ for (const candidate of [parsedPayload.data, parsedPayload.models, parsedPayload.result, parsedPayload.items]) {
215
205
  if (candidate === undefined) {
216
206
  continue;
217
207
  }
@@ -56,6 +56,19 @@ export function isMimoModelIdOrName(value: string): boolean {
56
56
  return value.toLowerCase().includes("mimo");
57
57
  }
58
58
 
59
+ const GROK_EFFORT_CAPABLE_PREFIXES = ["grok-3-mini", "grok-4.20-multi-agent", "grok-4.3"] as const;
60
+
61
+ /**
62
+ * Grok SKUs that expose the wire `reasoning.effort` dial. Other Grok reasoners
63
+ * (e.g. `grok-build`, `grok-4.20-0309-reasoning`) think natively but reject the
64
+ * param, so callers must omit reasoning effort for them.
65
+ */
66
+ export function isGrokReasoningEffortCapable(modelId: string): boolean {
67
+ const bare = bareModelId(modelId).trim().toLowerCase();
68
+ if (!bare) return false;
69
+ return GROK_EFFORT_CAPABLE_PREFIXES.some(prefix => bare.startsWith(prefix));
70
+ }
71
+
59
72
  /**
60
73
  * MiniMax M2-generation family (M2, M2.1, M2.5, M2.7, including `-highspeed`/
61
74
  * `-lightning`/`-her`/`-turbo` variants, dotless aliases like `minimax-m21`,