@wrongstack/core 0.298.1 → 0.298.2

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.
@@ -3632,13 +3632,32 @@ function inlineDefinition(model) {
3632
3632
  if (maxOutput !== void 0) definition.maxOutput = maxOutput;
3633
3633
  const capabilities = readCapabilities(model);
3634
3634
  if (capabilities) definition.capabilities = capabilities;
3635
+ const { id: _id, ...rest } = model;
3636
+ if (Object.keys(rest).length > 0) {
3637
+ definition.modelsDev = rest;
3638
+ }
3635
3639
  return definition;
3636
3640
  }
3637
3641
  function mergeDefinitions(base, patch) {
3642
+ const mergedModelsDev = (() => {
3643
+ if (!base?.modelsDev && !patch.modelsDev) return void 0;
3644
+ const baseMd = base?.modelsDev ?? {};
3645
+ const patchMd = patch.modelsDev ?? {};
3646
+ const result = { ...baseMd, ...patchMd };
3647
+ for (const nestedKey of ["limit", "cost", "modalities"]) {
3648
+ const bn = baseMd?.[nestedKey];
3649
+ const pn = patchMd?.[nestedKey];
3650
+ if (bn || pn) {
3651
+ result[nestedKey] = { ...bn ?? {}, ...pn ?? {} };
3652
+ }
3653
+ }
3654
+ return result;
3655
+ })();
3638
3656
  return {
3639
3657
  ...base,
3640
3658
  ...patch,
3641
- ...base?.capabilities || patch.capabilities ? { capabilities: { ...base?.capabilities, ...patch.capabilities } } : {}
3659
+ ...base?.capabilities || patch.capabilities ? { capabilities: { ...base?.capabilities, ...patch.capabilities } } : {},
3660
+ ...mergedModelsDev ? { modelsDev: mergedModelsDev } : {}
3642
3661
  };
3643
3662
  }
3644
3663
  function normalizeInlineProviderModels(config, warn) {
@@ -5,6 +5,7 @@ export { LLMSelector, type LLMSelectorOptions } from './llm-selector.js';
5
5
  export { resolveProviderModelList, describeCatalogModel, type ProviderModelDescriptor, } from './provider-model-resolve.js';
6
6
  export { CODEX_MODELS, codexModelMeta, type CodexModelMeta } from './codex-catalog.js';
7
7
  export { ALIBABA_TOKEN_PLAN_MODELS, alibabaTokenPlanModelMeta, type AlibabaTokenPlanModelMeta, } from './alibaba-token-plan-catalog.js';
8
+ export { MODELS_DEV_MODALITY_VALUES, modelsDevCostSchema, modelsDevLimitSchema, modelsDevModalitiesSchema, modelsDevModelSchema, modelsDevPayloadSchema, modelsDevProviderSchema, type ModelsDevModelParsed, type ModelsDevPayloadParsed, type ModelsDevProviderParsed, type ModelsDevSchemaSyncProof, } from './models-dev-schema.js';
8
9
  export { MODEL_PROFILES, TASK_TO_ROLE, inferTaskType, findModelProfile, scoreModelForTask, type ModelProfile, type TaskType, } from './model-intelligence.js';
9
10
  export { ModelRouter, type RouterConfig, type ModelPick, type RouterCosts, type ModelIntelligenceEntry, } from './model-router.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -504,7 +504,7 @@ function stripUndefined(obj) {
504
504
  // src/models/models-registry.ts
505
505
  var DEFAULT_URL = "https://models.dev/api.json";
506
506
  var ENV_URL_KEY = "WRONGSTACK_MODELS_DEV_URL";
507
- var DEFAULT_TTL_SECONDS = 24 * 3600;
507
+ var DEFAULT_TTL_SECONDS = 3 * 3600;
508
508
  var DEFAULT_REFRESH_TIMEOUT_MS = 15e3;
509
509
  var FAMILY_BY_NPM = {
510
510
  "@ai-sdk/anthropic": "anthropic",
@@ -1801,6 +1801,106 @@ function alibabaTokenPlanModelMeta(id) {
1801
1801
  return BY_ID2.get(id);
1802
1802
  }
1803
1803
 
1804
+ // src/models/models-dev-schema.ts
1805
+ import { z } from "zod";
1806
+
1807
+ // src/utils/deep-merge.ts
1808
+ var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
1809
+ "__proto__",
1810
+ "constructor",
1811
+ "prototype",
1812
+ "__defineGetter__",
1813
+ "__defineSetter__",
1814
+ "__lookupGetter__",
1815
+ "__lookupSetter__"
1816
+ ]);
1817
+
1818
+ // src/models/models-dev-schema.ts
1819
+ var MODELS_DEV_MODALITY_VALUES = ["text", "image", "audio", "video", "pdf"];
1820
+ var REASONING_EFFORT_LITERALS = [
1821
+ "none",
1822
+ "minimal",
1823
+ "low",
1824
+ "medium",
1825
+ "high",
1826
+ "xhigh",
1827
+ "max"
1828
+ ];
1829
+ var nonNegativeInt = z.number().int().nonnegative();
1830
+ var finiteNumber = z.number().finite();
1831
+ var modelsDevLimitSchema = z.looseObject({
1832
+ context: nonNegativeInt.optional(),
1833
+ output: nonNegativeInt.optional(),
1834
+ input: nonNegativeInt.optional()
1835
+ });
1836
+ var modelsDevCostSchema = z.looseObject({
1837
+ input: finiteNumber.optional(),
1838
+ output: finiteNumber.optional(),
1839
+ cache_read: finiteNumber.optional(),
1840
+ cache_write: finiteNumber.optional(),
1841
+ cache_write_5m: finiteNumber.optional(),
1842
+ cache_write_1h: finiteNumber.optional(),
1843
+ context_over_200k: finiteNumber.optional(),
1844
+ reasoning: finiteNumber.optional(),
1845
+ input_audio: finiteNumber.optional(),
1846
+ output_audio: finiteNumber.optional()
1847
+ });
1848
+ var modelsDevModalitiesSchema = z.looseObject({
1849
+ input: z.array(z.string().min(1)).optional(),
1850
+ output: z.array(z.string().min(1)).optional()
1851
+ });
1852
+ var reasoningOptionSchema = z.union([
1853
+ z.looseObject({ type: z.literal("toggle") }),
1854
+ z.looseObject({
1855
+ type: z.literal("effort"),
1856
+ // Closed on purpose: effort literals are a runtime concept consumed via
1857
+ // ReasoningEffort (types/provider.ts). Keep this list in sync with that
1858
+ // union — a new upstream literal should update BOTH deliberately (the
1859
+ // compile-time sync proof below is designed to fail loudly on drift).
1860
+ values: z.array(z.enum(REASONING_EFFORT_LITERALS)).optional()
1861
+ }),
1862
+ z.looseObject({
1863
+ type: z.literal("budget_tokens"),
1864
+ min: z.number().optional(),
1865
+ max: z.number().optional()
1866
+ })
1867
+ ]);
1868
+ var protoKeyRefinement = (label) => ({
1869
+ message: `${label} id is a forbidden prototype-pollution key`
1870
+ });
1871
+ var modelsDevModelSchema = z.looseObject({
1872
+ id: z.string().min(1).refine((id) => !FORBIDDEN_PROTO_KEYS.has(id), protoKeyRefinement("Model")),
1873
+ name: z.string().min(1),
1874
+ description: z.string().optional(),
1875
+ family: z.string().optional(),
1876
+ attachment: z.boolean().optional(),
1877
+ reasoning: z.boolean().optional(),
1878
+ reasoning_options: z.union([reasoningOptionSchema, z.array(reasoningOptionSchema)]).optional(),
1879
+ interleaved: z.union([z.boolean(), z.looseObject({ field: z.string().optional() })]).optional(),
1880
+ tool_call: z.boolean().optional(),
1881
+ structured_output: z.boolean().optional(),
1882
+ temperature: z.boolean().optional(),
1883
+ knowledge: z.string().optional(),
1884
+ release_date: z.string().optional(),
1885
+ last_updated: z.string().optional(),
1886
+ open_weights: z.boolean().optional(),
1887
+ modalities: modelsDevModalitiesSchema.optional(),
1888
+ cost: modelsDevCostSchema.optional(),
1889
+ limit: modelsDevLimitSchema.optional(),
1890
+ status: z.string().optional(),
1891
+ experimental: z.boolean().optional()
1892
+ });
1893
+ var modelsDevProviderSchema = z.looseObject({
1894
+ id: z.string().min(1).refine((id) => !FORBIDDEN_PROTO_KEYS.has(id), protoKeyRefinement("Provider")),
1895
+ name: z.string().min(1),
1896
+ env: z.array(z.string()).optional(),
1897
+ npm: z.string().optional(),
1898
+ api: z.string().optional(),
1899
+ doc: z.string().optional(),
1900
+ models: z.record(z.string(), modelsDevModelSchema)
1901
+ });
1902
+ var modelsDevPayloadSchema = z.record(z.string(), modelsDevProviderSchema);
1903
+
1804
1904
  // src/models/model-intelligence.ts
1805
1905
  var MODEL_PROFILES = [
1806
1906
  // ── Anthropic ──
@@ -2297,6 +2397,7 @@ export {
2297
2397
  DefaultModeStore,
2298
2398
  DefaultModelsRegistry,
2299
2399
  LLMSelector,
2400
+ MODELS_DEV_MODALITY_VALUES,
2300
2401
  MODEL_PROFILES,
2301
2402
  ModelRouter,
2302
2403
  TASK_TO_ROLE,
@@ -2308,6 +2409,12 @@ export {
2308
2409
  inferTaskType,
2309
2410
  loadProjectModes,
2310
2411
  loadUserModes,
2412
+ modelsDevCostSchema,
2413
+ modelsDevLimitSchema,
2414
+ modelsDevModalitiesSchema,
2415
+ modelsDevModelSchema,
2416
+ modelsDevPayloadSchema,
2417
+ modelsDevProviderSchema,
2311
2418
  resolveProviderModelList,
2312
2419
  scoreModelForTask
2313
2420
  };
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Runtime-validated mirror of the models.dev/api.json schema.
3
+ *
4
+ * ME-1 (Model Editor board): one zod schema pair shared by config-loader
5
+ * validation, WS payloads, WebUI forms, and TUI validation. The static type
6
+ * mirror lives in `../types/models-registry.js` (ModelsDevModel /
7
+ * ModelsDevProvider); the compile-time assertion at the bottom of this file
8
+ * keeps parsed schema output assignable to the static mirror.
9
+ *
10
+ * Passthrough policy: models.dev keeps adding fields (`limit.input`,
11
+ * `cost.tiers`, `reasoning_options` are recent examples), so every object
12
+ * schema below is LOOSE — unknown keys are accepted and preserved, never
13
+ * stripped or rejected. Known keys are type-checked; unknown ones pass.
14
+ *
15
+ * Modalities are plain string arrays upstream ("text" | "image" | "audio" |
16
+ * "video" | "pdf" observed in the 2026-08-03 census). The schema validates
17
+ * "array of non-empty strings" rather than a closed enum so new upstream
18
+ * modality values don't break parsing; MODELS_DEV_MODALITY_VALUES documents
19
+ * the known set for UI/editor use.
20
+ */
21
+ import { z } from 'zod';
22
+ import type { ModelsDevModel, ModelsDevProvider } from '../types/models-registry.js';
23
+ /** Known values observed in models.dev modality arrays (2026-08-03 census). */
24
+ export declare const MODELS_DEV_MODALITY_VALUES: readonly ['text', 'image', 'audio', 'video', 'pdf'];
25
+ /** `limit` — context/output on every model; `input` on a subset. 0 is valid. */
26
+ export declare const modelsDevLimitSchema: z.ZodObject<{
27
+ context: z.ZodOptional<z.ZodNumber>;
28
+ output: z.ZodOptional<z.ZodNumber>;
29
+ input: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$loose>;
31
+ /**
32
+ * `cost` — USD per 1M tokens upstream. Known numeric keys are validated;
33
+ * non-numeric additions like `tiers` (observed on ~300 models) pass through
34
+ * untouched via the loose object.
35
+ */
36
+ export declare const modelsDevCostSchema: z.ZodObject<{
37
+ input: z.ZodOptional<z.ZodNumber>;
38
+ output: z.ZodOptional<z.ZodNumber>;
39
+ cache_read: z.ZodOptional<z.ZodNumber>;
40
+ cache_write: z.ZodOptional<z.ZodNumber>;
41
+ cache_write_5m: z.ZodOptional<z.ZodNumber>;
42
+ cache_write_1h: z.ZodOptional<z.ZodNumber>;
43
+ context_over_200k: z.ZodOptional<z.ZodNumber>;
44
+ reasoning: z.ZodOptional<z.ZodNumber>;
45
+ input_audio: z.ZodOptional<z.ZodNumber>;
46
+ output_audio: z.ZodOptional<z.ZodNumber>;
47
+ }, z.core.$loose>;
48
+ /** `modalities` — plain string arrays; new values accepted (see file docs). */
49
+ export declare const modelsDevModalitiesSchema: z.ZodObject<{
50
+ input: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ output: z.ZodOptional<z.ZodArray<z.ZodString>>;
52
+ }, z.core.$loose>;
53
+ /** One models.dev model entry (values of `provider.models`). */
54
+ export declare const modelsDevModelSchema: z.ZodObject<{
55
+ id: z.ZodString;
56
+ name: z.ZodString;
57
+ description: z.ZodOptional<z.ZodString>;
58
+ family: z.ZodOptional<z.ZodString>;
59
+ attachment: z.ZodOptional<z.ZodBoolean>;
60
+ reasoning: z.ZodOptional<z.ZodBoolean>;
61
+ reasoning_options: z.ZodOptional<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
62
+ type: z.ZodLiteral<"toggle">;
63
+ }, z.core.$loose>, z.ZodObject<{
64
+ type: z.ZodLiteral<"effort">;
65
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
66
+ high: "high";
67
+ low: "low";
68
+ max: "max";
69
+ medium: "medium";
70
+ minimal: "minimal";
71
+ none: "none";
72
+ xhigh: "xhigh";
73
+ }>>>;
74
+ }, z.core.$loose>, z.ZodObject<{
75
+ type: z.ZodLiteral<"budget_tokens">;
76
+ min: z.ZodOptional<z.ZodNumber>;
77
+ max: z.ZodOptional<z.ZodNumber>;
78
+ }, z.core.$loose>]>, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
79
+ type: z.ZodLiteral<"toggle">;
80
+ }, z.core.$loose>, z.ZodObject<{
81
+ type: z.ZodLiteral<"effort">;
82
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
83
+ high: "high";
84
+ low: "low";
85
+ max: "max";
86
+ medium: "medium";
87
+ minimal: "minimal";
88
+ none: "none";
89
+ xhigh: "xhigh";
90
+ }>>>;
91
+ }, z.core.$loose>, z.ZodObject<{
92
+ type: z.ZodLiteral<"budget_tokens">;
93
+ min: z.ZodOptional<z.ZodNumber>;
94
+ max: z.ZodOptional<z.ZodNumber>;
95
+ }, z.core.$loose>]>>]>>;
96
+ interleaved: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
97
+ field: z.ZodOptional<z.ZodString>;
98
+ }, z.core.$loose>]>>;
99
+ tool_call: z.ZodOptional<z.ZodBoolean>;
100
+ structured_output: z.ZodOptional<z.ZodBoolean>;
101
+ temperature: z.ZodOptional<z.ZodBoolean>;
102
+ knowledge: z.ZodOptional<z.ZodString>;
103
+ release_date: z.ZodOptional<z.ZodString>;
104
+ last_updated: z.ZodOptional<z.ZodString>;
105
+ open_weights: z.ZodOptional<z.ZodBoolean>;
106
+ modalities: z.ZodOptional<z.ZodObject<{
107
+ input: z.ZodOptional<z.ZodArray<z.ZodString>>;
108
+ output: z.ZodOptional<z.ZodArray<z.ZodString>>;
109
+ }, z.core.$loose>>;
110
+ cost: z.ZodOptional<z.ZodObject<{
111
+ input: z.ZodOptional<z.ZodNumber>;
112
+ output: z.ZodOptional<z.ZodNumber>;
113
+ cache_read: z.ZodOptional<z.ZodNumber>;
114
+ cache_write: z.ZodOptional<z.ZodNumber>;
115
+ cache_write_5m: z.ZodOptional<z.ZodNumber>;
116
+ cache_write_1h: z.ZodOptional<z.ZodNumber>;
117
+ context_over_200k: z.ZodOptional<z.ZodNumber>;
118
+ reasoning: z.ZodOptional<z.ZodNumber>;
119
+ input_audio: z.ZodOptional<z.ZodNumber>;
120
+ output_audio: z.ZodOptional<z.ZodNumber>;
121
+ }, z.core.$loose>>;
122
+ limit: z.ZodOptional<z.ZodObject<{
123
+ context: z.ZodOptional<z.ZodNumber>;
124
+ output: z.ZodOptional<z.ZodNumber>;
125
+ input: z.ZodOptional<z.ZodNumber>;
126
+ }, z.core.$loose>>;
127
+ status: z.ZodOptional<z.ZodString>;
128
+ experimental: z.ZodOptional<z.ZodBoolean>;
129
+ }, z.core.$loose>;
130
+ /** One models.dev provider entry (top-level values of api.json). */
131
+ export declare const modelsDevProviderSchema: z.ZodObject<{
132
+ id: z.ZodString;
133
+ name: z.ZodString;
134
+ env: z.ZodOptional<z.ZodArray<z.ZodString>>;
135
+ npm: z.ZodOptional<z.ZodString>;
136
+ api: z.ZodOptional<z.ZodString>;
137
+ doc: z.ZodOptional<z.ZodString>;
138
+ models: z.ZodRecord<z.ZodString, z.ZodObject<{
139
+ id: z.ZodString;
140
+ name: z.ZodString;
141
+ description: z.ZodOptional<z.ZodString>;
142
+ family: z.ZodOptional<z.ZodString>;
143
+ attachment: z.ZodOptional<z.ZodBoolean>;
144
+ reasoning: z.ZodOptional<z.ZodBoolean>;
145
+ reasoning_options: z.ZodOptional<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
146
+ type: z.ZodLiteral<"toggle">;
147
+ }, z.core.$loose>, z.ZodObject<{
148
+ type: z.ZodLiteral<"effort">;
149
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
150
+ high: "high";
151
+ low: "low";
152
+ max: "max";
153
+ medium: "medium";
154
+ minimal: "minimal";
155
+ none: "none";
156
+ xhigh: "xhigh";
157
+ }>>>;
158
+ }, z.core.$loose>, z.ZodObject<{
159
+ type: z.ZodLiteral<"budget_tokens">;
160
+ min: z.ZodOptional<z.ZodNumber>;
161
+ max: z.ZodOptional<z.ZodNumber>;
162
+ }, z.core.$loose>]>, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
163
+ type: z.ZodLiteral<"toggle">;
164
+ }, z.core.$loose>, z.ZodObject<{
165
+ type: z.ZodLiteral<"effort">;
166
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
167
+ high: "high";
168
+ low: "low";
169
+ max: "max";
170
+ medium: "medium";
171
+ minimal: "minimal";
172
+ none: "none";
173
+ xhigh: "xhigh";
174
+ }>>>;
175
+ }, z.core.$loose>, z.ZodObject<{
176
+ type: z.ZodLiteral<"budget_tokens">;
177
+ min: z.ZodOptional<z.ZodNumber>;
178
+ max: z.ZodOptional<z.ZodNumber>;
179
+ }, z.core.$loose>]>>]>>;
180
+ interleaved: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
181
+ field: z.ZodOptional<z.ZodString>;
182
+ }, z.core.$loose>]>>;
183
+ tool_call: z.ZodOptional<z.ZodBoolean>;
184
+ structured_output: z.ZodOptional<z.ZodBoolean>;
185
+ temperature: z.ZodOptional<z.ZodBoolean>;
186
+ knowledge: z.ZodOptional<z.ZodString>;
187
+ release_date: z.ZodOptional<z.ZodString>;
188
+ last_updated: z.ZodOptional<z.ZodString>;
189
+ open_weights: z.ZodOptional<z.ZodBoolean>;
190
+ modalities: z.ZodOptional<z.ZodObject<{
191
+ input: z.ZodOptional<z.ZodArray<z.ZodString>>;
192
+ output: z.ZodOptional<z.ZodArray<z.ZodString>>;
193
+ }, z.core.$loose>>;
194
+ cost: z.ZodOptional<z.ZodObject<{
195
+ input: z.ZodOptional<z.ZodNumber>;
196
+ output: z.ZodOptional<z.ZodNumber>;
197
+ cache_read: z.ZodOptional<z.ZodNumber>;
198
+ cache_write: z.ZodOptional<z.ZodNumber>;
199
+ cache_write_5m: z.ZodOptional<z.ZodNumber>;
200
+ cache_write_1h: z.ZodOptional<z.ZodNumber>;
201
+ context_over_200k: z.ZodOptional<z.ZodNumber>;
202
+ reasoning: z.ZodOptional<z.ZodNumber>;
203
+ input_audio: z.ZodOptional<z.ZodNumber>;
204
+ output_audio: z.ZodOptional<z.ZodNumber>;
205
+ }, z.core.$loose>>;
206
+ limit: z.ZodOptional<z.ZodObject<{
207
+ context: z.ZodOptional<z.ZodNumber>;
208
+ output: z.ZodOptional<z.ZodNumber>;
209
+ input: z.ZodOptional<z.ZodNumber>;
210
+ }, z.core.$loose>>;
211
+ status: z.ZodOptional<z.ZodString>;
212
+ experimental: z.ZodOptional<z.ZodBoolean>;
213
+ }, z.core.$loose>>;
214
+ }, z.core.$loose>;
215
+ /** The whole api.json payload: provider id → provider entry. */
216
+ export declare const modelsDevPayloadSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
217
+ id: z.ZodString;
218
+ name: z.ZodString;
219
+ env: z.ZodOptional<z.ZodArray<z.ZodString>>;
220
+ npm: z.ZodOptional<z.ZodString>;
221
+ api: z.ZodOptional<z.ZodString>;
222
+ doc: z.ZodOptional<z.ZodString>;
223
+ models: z.ZodRecord<z.ZodString, z.ZodObject<{
224
+ id: z.ZodString;
225
+ name: z.ZodString;
226
+ description: z.ZodOptional<z.ZodString>;
227
+ family: z.ZodOptional<z.ZodString>;
228
+ attachment: z.ZodOptional<z.ZodBoolean>;
229
+ reasoning: z.ZodOptional<z.ZodBoolean>;
230
+ reasoning_options: z.ZodOptional<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
231
+ type: z.ZodLiteral<"toggle">;
232
+ }, z.core.$loose>, z.ZodObject<{
233
+ type: z.ZodLiteral<"effort">;
234
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
235
+ high: "high";
236
+ low: "low";
237
+ max: "max";
238
+ medium: "medium";
239
+ minimal: "minimal";
240
+ none: "none";
241
+ xhigh: "xhigh";
242
+ }>>>;
243
+ }, z.core.$loose>, z.ZodObject<{
244
+ type: z.ZodLiteral<"budget_tokens">;
245
+ min: z.ZodOptional<z.ZodNumber>;
246
+ max: z.ZodOptional<z.ZodNumber>;
247
+ }, z.core.$loose>]>, z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
248
+ type: z.ZodLiteral<"toggle">;
249
+ }, z.core.$loose>, z.ZodObject<{
250
+ type: z.ZodLiteral<"effort">;
251
+ values: z.ZodOptional<z.ZodArray<z.ZodEnum<{
252
+ high: "high";
253
+ low: "low";
254
+ max: "max";
255
+ medium: "medium";
256
+ minimal: "minimal";
257
+ none: "none";
258
+ xhigh: "xhigh";
259
+ }>>>;
260
+ }, z.core.$loose>, z.ZodObject<{
261
+ type: z.ZodLiteral<"budget_tokens">;
262
+ min: z.ZodOptional<z.ZodNumber>;
263
+ max: z.ZodOptional<z.ZodNumber>;
264
+ }, z.core.$loose>]>>]>>;
265
+ interleaved: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
266
+ field: z.ZodOptional<z.ZodString>;
267
+ }, z.core.$loose>]>>;
268
+ tool_call: z.ZodOptional<z.ZodBoolean>;
269
+ structured_output: z.ZodOptional<z.ZodBoolean>;
270
+ temperature: z.ZodOptional<z.ZodBoolean>;
271
+ knowledge: z.ZodOptional<z.ZodString>;
272
+ release_date: z.ZodOptional<z.ZodString>;
273
+ last_updated: z.ZodOptional<z.ZodString>;
274
+ open_weights: z.ZodOptional<z.ZodBoolean>;
275
+ modalities: z.ZodOptional<z.ZodObject<{
276
+ input: z.ZodOptional<z.ZodArray<z.ZodString>>;
277
+ output: z.ZodOptional<z.ZodArray<z.ZodString>>;
278
+ }, z.core.$loose>>;
279
+ cost: z.ZodOptional<z.ZodObject<{
280
+ input: z.ZodOptional<z.ZodNumber>;
281
+ output: z.ZodOptional<z.ZodNumber>;
282
+ cache_read: z.ZodOptional<z.ZodNumber>;
283
+ cache_write: z.ZodOptional<z.ZodNumber>;
284
+ cache_write_5m: z.ZodOptional<z.ZodNumber>;
285
+ cache_write_1h: z.ZodOptional<z.ZodNumber>;
286
+ context_over_200k: z.ZodOptional<z.ZodNumber>;
287
+ reasoning: z.ZodOptional<z.ZodNumber>;
288
+ input_audio: z.ZodOptional<z.ZodNumber>;
289
+ output_audio: z.ZodOptional<z.ZodNumber>;
290
+ }, z.core.$loose>>;
291
+ limit: z.ZodOptional<z.ZodObject<{
292
+ context: z.ZodOptional<z.ZodNumber>;
293
+ output: z.ZodOptional<z.ZodNumber>;
294
+ input: z.ZodOptional<z.ZodNumber>;
295
+ }, z.core.$loose>>;
296
+ status: z.ZodOptional<z.ZodString>;
297
+ experimental: z.ZodOptional<z.ZodBoolean>;
298
+ }, z.core.$loose>>;
299
+ }, z.core.$loose>>;
300
+ export type ModelsDevModelParsed = z.infer<typeof modelsDevModelSchema>;
301
+ export type ModelsDevProviderParsed = z.infer<typeof modelsDevProviderSchema>;
302
+ export type ModelsDevPayloadParsed = z.infer<typeof modelsDevPayloadSchema>;
303
+ type AssertAssignableTo<T, U extends T> = U;
304
+ type ModelSchemaSyncCheck = AssertAssignableTo<ModelsDevModel, ModelsDevModelParsed>;
305
+ type ProviderSchemaSyncCheck = AssertAssignableTo<ModelsDevProvider, ModelsDevProviderParsed>;
306
+ export type ModelsDevSchemaSyncProof = [ModelSchemaSyncCheck, ProviderSchemaSyncCheck];
307
+ export {};
308
+ //# sourceMappingURL=models-dev-schema.d.ts.map
@@ -6839,7 +6839,7 @@ function trimKnownFingerprints(map, max) {
6839
6839
  map.delete(oldest);
6840
6840
  }
6841
6841
  }
6842
- function buildReviewerModelPool(provider, model, fallbackModels = []) {
6842
+ function buildReviewerModelPool(provider, model, fallbackModels = [], statusTracker) {
6843
6843
  const primaryProvider = provider.trim();
6844
6844
  const primaryModel = model.trim();
6845
6845
  const primaryRef = primaryProvider && primaryModel ? `${primaryProvider}/${primaryModel}` : "";
@@ -6854,12 +6854,20 @@ function buildReviewerModelPool(provider, model, fallbackModels = []) {
6854
6854
  if (seen.has(normalized)) continue;
6855
6855
  seen.add(ref);
6856
6856
  seen.add(normalized);
6857
+ if (statusTracker && !statusTracker.isAvailable(parsed.provider.trim(), parsed.model.trim())) {
6858
+ continue;
6859
+ }
6857
6860
  pool.push(normalized);
6858
6861
  }
6859
6862
  return pool;
6860
6863
  }
6861
- function selectRoundRobinReviewerAssignment(pool, cursor, fallbackProvider = "", fallbackModel = "") {
6862
- if (pool.length === 0) {
6864
+ function selectRoundRobinReviewerAssignment(pool, cursor, fallbackProvider = "", fallbackModel = "", statusTracker) {
6865
+ const filteredPool = statusTracker ? pool.filter((ref) => {
6866
+ const parsed2 = parseModelRef(ref);
6867
+ if (!parsed2.provider?.trim() || !parsed2.model.trim()) return false;
6868
+ return statusTracker.isAvailable(parsed2.provider.trim(), parsed2.model.trim());
6869
+ }) : pool;
6870
+ if (filteredPool.length === 0) {
6863
6871
  return {
6864
6872
  provider: fallbackProvider,
6865
6873
  model: fallbackModel,
@@ -6867,13 +6875,13 @@ function selectRoundRobinReviewerAssignment(pool, cursor, fallbackProvider = "",
6867
6875
  nextCursor: cursor + 1
6868
6876
  };
6869
6877
  }
6870
- const len = pool.length;
6878
+ const len = filteredPool.length;
6871
6879
  const idx = (cursor % len + len) % len;
6872
- const primaryRef = pool[idx];
6880
+ const primaryRef = filteredPool[idx];
6873
6881
  const parsed = parseModelRef(primaryRef);
6874
6882
  const provider = parsed.provider?.trim() || fallbackProvider;
6875
6883
  const model = parsed.model.trim() || fallbackModel;
6876
- const fallbackModels = [...pool.slice(idx + 1), ...pool.slice(0, idx)];
6884
+ const fallbackModels = [...filteredPool.slice(idx + 1), ...filteredPool.slice(0, idx)];
6877
6885
  return {
6878
6886
  provider,
6879
6887
  model,
@@ -1,3 +1,4 @@
1
+ import type { ProviderModelStatusTracker } from '../coordination/provider-status-tracker.js';
1
2
  import type { Config } from '../types/config.js';
2
3
  import type { Plugin } from '../types/plugin.js';
3
4
  import type { CascadeAgentKind } from './chimera-plugin.js';
@@ -70,8 +71,15 @@ export interface ReviewerModelAssignment {
70
71
  *
71
72
  * Order is stable: configured primary first, then the fallback chain.
72
73
  * Entries must be `provider/model` (or parseable refs); bare blanks are dropped.
74
+ *
75
+ * When a {@link ProviderModelStatusTracker} is supplied, every entry that is
76
+ * currently `state: 'blocked'` (waiting-room / token-reset-limit room) is
77
+ * filtered out before the pool is returned. Without this filter, concurrent
78
+ * Chimera reviewers would re-spawn on a 429-stricken model on every round-
79
+ * robin turn and burn the entire chain instead of leaving the doomed model
80
+ * quarantined until the tracker re-admits it.
73
81
  */
74
- export declare function buildReviewerModelPool(provider: string, model: string, fallbackModels?: readonly string[]): string[];
82
+ export declare function buildReviewerModelPool(provider: string, model: string, fallbackModels?: readonly string[], statusTracker?: ProviderModelStatusTracker | undefined): string[];
75
83
  /**
76
84
  * Pick primary + fallback chain for the Nth concurrent reviewer via round-robin.
77
85
  *
@@ -79,11 +87,18 @@ export declare function buildReviewerModelPool(provider: string, model: string,
79
87
  * rotated so the former primary lands last (still available after rate limits).
80
88
  * The pool must be pre-filtered by {@link buildReviewerModelPool} so every
81
89
  * non-empty entry contains both a provider and a model.
90
+ *
91
+ * When a {@link ProviderModelStatusTracker} is supplied, the cursor advances
92
+ * over blocked entries too — a doomed entry is never picked as the primary,
93
+ * but the cursor saturates against the live pool so the next-after-blocked
94
+ * round inherits the rest of the unwalked chain instead of looping back to
95
+ * the head. Without the tracker, the cursor advances mod `pool.length`,
96
+ * which is the pre-waiting-room behavior.
82
97
  * Pure: the caller owns the cursor (typically a process-local counter).
83
98
  */
84
99
  export declare function selectRoundRobinReviewerAssignment(pool: readonly string[], cursor: number,
85
100
  /** Used only when the selected ref is somehow unparseable — defensive. */
86
- fallbackProvider?: string, fallbackModel?: string): ReviewerModelAssignment;
101
+ fallbackProvider?: string, fallbackModel?: string, statusTracker?: ProviderModelStatusTracker | undefined): ReviewerModelAssignment;
87
102
  export declare function resolveAutoReviewConfig(cfg: AutoReviewConfig, sessionConfig: Config): ResolvedAutoReviewConfig;
88
103
  export interface ParsedSeverities {
89
104
  critical: number;
@@ -6216,13 +6216,32 @@ function inlineDefinition(model) {
6216
6216
  if (maxOutput !== void 0) definition.maxOutput = maxOutput;
6217
6217
  const capabilities = readCapabilities(model);
6218
6218
  if (capabilities) definition.capabilities = capabilities;
6219
+ const { id: _id, ...rest } = model;
6220
+ if (Object.keys(rest).length > 0) {
6221
+ definition.modelsDev = rest;
6222
+ }
6219
6223
  return definition;
6220
6224
  }
6221
6225
  function mergeDefinitions(base, patch) {
6226
+ const mergedModelsDev = (() => {
6227
+ if (!base?.modelsDev && !patch.modelsDev) return void 0;
6228
+ const baseMd = base?.modelsDev ?? {};
6229
+ const patchMd = patch.modelsDev ?? {};
6230
+ const result = { ...baseMd, ...patchMd };
6231
+ for (const nestedKey of ["limit", "cost", "modalities"]) {
6232
+ const bn = baseMd?.[nestedKey];
6233
+ const pn = patchMd?.[nestedKey];
6234
+ if (bn || pn) {
6235
+ result[nestedKey] = { ...bn ?? {}, ...pn ?? {} };
6236
+ }
6237
+ }
6238
+ return result;
6239
+ })();
6222
6240
  return {
6223
6241
  ...base,
6224
6242
  ...patch,
6225
- ...base?.capabilities || patch.capabilities ? { capabilities: { ...base?.capabilities, ...patch.capabilities } } : {}
6243
+ ...base?.capabilities || patch.capabilities ? { capabilities: { ...base?.capabilities, ...patch.capabilities } } : {},
6244
+ ...mergedModelsDev ? { modelsDev: mergedModelsDev } : {}
6226
6245
  };
6227
6246
  }
6228
6247
  function normalizeInlineProviderModels(config, warn) {