@codeworksh/aikit 0.11.0-dev.20261013131320 → 0.11.0-dev.20261019181702
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/cli.mjs +3 -3
- package/{copilot-JLgwmznn.mjs → copilot-DvUXC6Kx.mjs} +2 -2
- package/{copilot-JLgwmznn.mjs.map → copilot-DvUXC6Kx.mjs.map} +1 -1
- package/{copilot-headers-BvQ3FFn-.mjs → copilot-headers-BLnBaJyp.mjs} +2 -2
- package/{copilot-headers-BvQ3FFn-.mjs.map → copilot-headers-BLnBaJyp.mjs.map} +1 -1
- package/{github-copilot-C7oJ2Tfp.mjs → github-copilot-BcmOr0jd.mjs} +2 -2
- package/{github-copilot-C7oJ2Tfp.mjs.map → github-copilot-BcmOr0jd.mjs.map} +1 -1
- package/github-copilot-llyP2NK4.mjs +3 -0
- package/index.d.mts +3 -3
- package/index.mjs +5 -5
- package/index.mjs.map +1 -1
- package/model-Cjp-Dr8V.mjs +13955 -0
- package/model-Cjp-Dr8V.mjs.map +1 -0
- package/{model-DCfjY0fS.d.mts → model-D3wc9-u4.d.mts} +42 -19
- package/modelgen-DDO_NHoQ.mjs +731 -0
- package/modelgen-DDO_NHoQ.mjs.map +1 -0
- package/modelgen.d.mts +20 -3
- package/modelgen.mjs +61 -2
- package/modelgen.mjs.map +1 -0
- package/oauth/github/copilot.mjs +1 -1
- package/{openai-codex-Dj0oh0UV.mjs → openai-codex-C1Yb02kM.mjs} +2 -2
- package/{openai-codex-Dj0oh0UV.mjs.map → openai-codex-C1Yb02kM.mjs.map} +1 -1
- package/openai-codex-CHxShIN3.mjs +2 -0
- package/package.json +10 -10
- package/{registry-CfGgGfSs.mjs → registry-u49t0S4S.mjs} +4 -4
- package/{registry-CfGgGfSs.mjs.map → registry-u49t0S4S.mjs.map} +1 -1
- package/github-copilot-CLJx-bcP.mjs +0 -3
- package/model-D-FoGzVN.mjs +0 -522
- package/model-D-FoGzVN.mjs.map +0 -1
- package/modelgen-D6UBM1fq.mjs +0 -561
- package/modelgen-D6UBM1fq.mjs.map +0 -1
- package/openai-codex-CIBVNhQx.mjs +0 -2
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
import { C as readJson, S as path, T as writeJsonAtomic, d as effortThinkingLevels, h as isAnthropicAdaptiveThinkingModel, i as KnownProviderEnum, t as APIMethodEnum, v as normalizeInput } from "./model-Cjp-Dr8V.mjs";
|
|
2
|
+
import { a as protocolForPackage, n as isAISDKPackage } from "./registry-u49t0S4S.mjs";
|
|
3
|
+
import { n as GITHUB_COPILOT_STATIC_HEADERS } from "./copilot-headers-BLnBaJyp.mjs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { mapValues, pick, pickBy, pipe } from "remeda";
|
|
6
|
+
//#region src/model/openrouter.ts
|
|
7
|
+
const PROVIDER_ID = "openrouter";
|
|
8
|
+
const BASE_URL = "https://openrouter.ai/api/v1";
|
|
9
|
+
const NPM = "@openrouter/ai-sdk-provider";
|
|
10
|
+
const USER_MODELS_TIMEOUT_MS = 15e3;
|
|
11
|
+
/**
|
|
12
|
+
* $/token to $/1M tokens. Missing, invalid and negative prices use the fallback: OpenRouter
|
|
13
|
+
* reports -1 for router models such as `openrouter/auto`, whose price depends on the model it picks.
|
|
14
|
+
*/
|
|
15
|
+
function perMillion(value, fallback) {
|
|
16
|
+
const perToken = Number.parseFloat(value ?? "");
|
|
17
|
+
return perToken >= 0 ? Number((perToken * 1e6).toFixed(6)) : fallback;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Prompt-length overrides become request-wide tiers; a rate a tier does not list keeps the base
|
|
21
|
+
* price. Time-of-day overrides are skipped: the cost model cannot express them.
|
|
22
|
+
*/
|
|
23
|
+
function cost(pricing) {
|
|
24
|
+
const base = {
|
|
25
|
+
input: perMillion(pricing?.prompt, 0),
|
|
26
|
+
output: perMillion(pricing?.completion, 0),
|
|
27
|
+
cacheRead: perMillion(pricing?.input_cache_read, 0),
|
|
28
|
+
cacheWrite: perMillion(pricing?.input_cache_write, 0)
|
|
29
|
+
};
|
|
30
|
+
const tiers = (pricing?.overrides ?? []).flatMap((override) => {
|
|
31
|
+
if (override.min_prompt_tokens === void 0 || override.utc_start !== void 0 || override.utc_end !== void 0 || override.utc_days !== void 0) return [];
|
|
32
|
+
return [{
|
|
33
|
+
inputTokensAbove: override.min_prompt_tokens,
|
|
34
|
+
input: perMillion(override.prompt, base.input),
|
|
35
|
+
output: perMillion(override.completion, base.output),
|
|
36
|
+
cacheRead: perMillion(override.input_cache_read, base.cacheRead),
|
|
37
|
+
cacheWrite: perMillion(override.input_cache_write, base.cacheWrite)
|
|
38
|
+
}];
|
|
39
|
+
});
|
|
40
|
+
return tiers.length > 0 ? {
|
|
41
|
+
...base,
|
|
42
|
+
tiers
|
|
43
|
+
} : base;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `supported_efforts` uses models.dev's effort vocabulary. Off maps to `none` unless reasoning is
|
|
47
|
+
* mandatory; a mandatory model without listed efforts can only refuse off.
|
|
48
|
+
*/
|
|
49
|
+
function thinkingLevels(reasoning) {
|
|
50
|
+
if (!reasoning) return void 0;
|
|
51
|
+
const map = effortThinkingLevels(reasoning.supported_efforts ?? []);
|
|
52
|
+
if (!map) return reasoning.mandatory === true ? { off: null } : void 0;
|
|
53
|
+
return {
|
|
54
|
+
...map,
|
|
55
|
+
off: reasoning.mandatory === true ? null : "none"
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The catalog entry for one listed model, or undefined for one an agent cannot use: no tool
|
|
60
|
+
* calling, or a `:batch` variant, whose asynchronous pricing an interactive turn never gets.
|
|
61
|
+
*/
|
|
62
|
+
function toModel(entry) {
|
|
63
|
+
if (!entry.supported_parameters?.includes("tools") || entry.id.endsWith(":batch")) return void 0;
|
|
64
|
+
const thinkingLevelMap = thinkingLevels(entry.reasoning);
|
|
65
|
+
return {
|
|
66
|
+
id: entry.id,
|
|
67
|
+
name: entry.name ?? entry.id,
|
|
68
|
+
provider: {
|
|
69
|
+
id: PROVIDER_ID,
|
|
70
|
+
name: "OpenRouter",
|
|
71
|
+
source: "api",
|
|
72
|
+
env: ["OPENROUTER_API_KEY"]
|
|
73
|
+
},
|
|
74
|
+
baseUrl: BASE_URL,
|
|
75
|
+
reasoning: entry.supported_parameters.includes("reasoning"),
|
|
76
|
+
...thinkingLevelMap ? { thinkingLevelMap } : {},
|
|
77
|
+
input: normalizeInput(entry.architecture?.input_modalities),
|
|
78
|
+
cost: cost(entry.pricing),
|
|
79
|
+
contextWindow: entry.top_provider?.context_length || entry.context_length || 4096,
|
|
80
|
+
maxTokens: entry.top_provider?.max_completion_tokens || 4096,
|
|
81
|
+
npm: NPM,
|
|
82
|
+
api: {
|
|
83
|
+
id: entry.id,
|
|
84
|
+
url: BASE_URL,
|
|
85
|
+
method: APIMethodEnum.languageModel
|
|
86
|
+
},
|
|
87
|
+
providerOptionsKey: PROVIDER_ID,
|
|
88
|
+
protocol: KnownProviderEnum.openrouter
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function entries(body) {
|
|
92
|
+
if (typeof body !== "object" || body === null || !("data" in body) || !Array.isArray(body.data)) throw new Error("invalid OpenRouter model list");
|
|
93
|
+
return body.data.filter((entry) => typeof entry === "object" && entry !== null && "id" in entry && typeof entry.id === "string");
|
|
94
|
+
}
|
|
95
|
+
/** The public `GET /models`, built into catalog entries keyed by id. */
|
|
96
|
+
function catalog(body) {
|
|
97
|
+
const models = {};
|
|
98
|
+
for (const entry of entries(body)) {
|
|
99
|
+
const model = toModel(entry);
|
|
100
|
+
if (model) models[model.id] = model;
|
|
101
|
+
}
|
|
102
|
+
return models;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Restrict OpenRouter models to those `key` may use, with the key's limits and prices from
|
|
106
|
+
* `GET /models/user` (pi). A missing limit keeps the catalog value. When the endpoint rejects the
|
|
107
|
+
* key (401/403) or does not exist (404), or allows nothing, the models come back unchanged.
|
|
108
|
+
*/
|
|
109
|
+
async function personalize(models, key, options = {}) {
|
|
110
|
+
const signal = AbortSignal.timeout(USER_MODELS_TIMEOUT_MS);
|
|
111
|
+
const response = await fetch(`${(options.baseUrl ?? "https://openrouter.ai/api/v1").replace(/\/+$/, "")}/models/user`, {
|
|
112
|
+
headers: {
|
|
113
|
+
accept: "application/json",
|
|
114
|
+
authorization: `Bearer ${key}`
|
|
115
|
+
},
|
|
116
|
+
signal: options.signal ? AbortSignal.any([options.signal, signal]) : signal
|
|
117
|
+
});
|
|
118
|
+
if (response.status === 401 || response.status === 403 || response.status === 404) return models;
|
|
119
|
+
if (!response.ok) throw new Error(`OpenRouter model list request failed: ${response.status}`);
|
|
120
|
+
const allowed = new Map(entries(await response.json()).map((entry) => [entry.id, entry]));
|
|
121
|
+
const personal = {};
|
|
122
|
+
for (const [id, model] of Object.entries(models)) {
|
|
123
|
+
const entry = allowed.get(id);
|
|
124
|
+
if (!entry) continue;
|
|
125
|
+
personal[id] = {
|
|
126
|
+
...model,
|
|
127
|
+
contextWindow: entry.top_provider?.context_length || entry.context_length || model.contextWindow,
|
|
128
|
+
maxTokens: entry.top_provider?.max_completion_tokens || model.maxTokens,
|
|
129
|
+
cost: entry.pricing ? cost(entry.pricing) : model.cost
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return Object.keys(personal).length > 0 ? personal : models;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/cli/modelgen.ts
|
|
136
|
+
const DEFAULT_PROVIDER_BASE_URLS = {
|
|
137
|
+
[KnownProviderEnum.anthropic]: "https://api.anthropic.com/v1",
|
|
138
|
+
[KnownProviderEnum.openai]: "https://api.openai.com/v1",
|
|
139
|
+
[KnownProviderEnum.openrouter]: BASE_URL,
|
|
140
|
+
[KnownProviderEnum.xai]: "https://api.x.ai/v1"
|
|
141
|
+
};
|
|
142
|
+
/** Providers bundled with aikit as the baseline catalog, read until a generated one exists. */
|
|
143
|
+
const BASELINE_PROVIDERS = [
|
|
144
|
+
"anthropic",
|
|
145
|
+
"openai",
|
|
146
|
+
PROVIDER_ID
|
|
147
|
+
];
|
|
148
|
+
function modelsDevURL() {
|
|
149
|
+
return process.env.CODEWORK_MODELS_DEV_URL || "https://models.dev";
|
|
150
|
+
}
|
|
151
|
+
function modelsDevPath() {
|
|
152
|
+
return process.env.CODEWORK_MODELS_DEV_FILE;
|
|
153
|
+
}
|
|
154
|
+
async function pullModelsDevData() {
|
|
155
|
+
const path = modelsDevPath();
|
|
156
|
+
if (path) {
|
|
157
|
+
const result = await readJson(path).catch(() => void 0);
|
|
158
|
+
if (result) return result;
|
|
159
|
+
}
|
|
160
|
+
const response = await fetch(`${modelsDevURL()}/api.json`);
|
|
161
|
+
if (!response.ok) throw new Error(`models.dev responded ${response.status} ${response.statusText}`);
|
|
162
|
+
return await response.json();
|
|
163
|
+
}
|
|
164
|
+
/** OpenRouter's public listing, or undefined when it cannot be had: models.dev's copy stands in. */
|
|
165
|
+
async function pullOpenRouterData() {
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(`${BASE_URL}/models`, { signal: AbortSignal.timeout(3e4) });
|
|
168
|
+
return response.ok ? await response.json() : void 0;
|
|
169
|
+
} catch {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function toModelValue(providerId, provider, model) {
|
|
174
|
+
return applyModification(providerId, provider, model);
|
|
175
|
+
}
|
|
176
|
+
const MODELS_DEV_UNSUPPORTED_MODEL_IDS = /* @__PURE__ */ new Set(["openai/gpt-5.6"]);
|
|
177
|
+
function usable(providerId, provider, model) {
|
|
178
|
+
return Boolean(model.tool_call) && !MODELS_DEV_UNSUPPORTED_MODEL_IDS.has(`${providerId}/${model.id}`) && isAISDKPackage(resolveModelNpm(provider, model));
|
|
179
|
+
}
|
|
180
|
+
function loadBuiltInFromModelsDev(catalog) {
|
|
181
|
+
return pipe(catalog, pickBy((provider, providerId) => Object.values(provider.models).some((model) => usable(providerId, provider, model))), mapValues((provider, providerId) => pipe(provider.models, pickBy((model) => usable(providerId, provider, model)), mapValues((model) => toModelValue(providerId, provider, model)), pickBy((model) => model !== void 0))));
|
|
182
|
+
}
|
|
183
|
+
function resolveModelNpm(provider, model) {
|
|
184
|
+
return model.provider?.npm ?? provider.npm ?? "@ai-sdk/openai-compatible";
|
|
185
|
+
}
|
|
186
|
+
function resolveModelBaseUrl(provider, model) {
|
|
187
|
+
const npm = resolveModelNpm(provider, model);
|
|
188
|
+
const protocol = protocolForPackage(npm);
|
|
189
|
+
return model.baseUrl ?? model.provider?.api ?? provider.api ?? DEFAULT_PROVIDER_BASE_URLS[protocol] ?? "";
|
|
190
|
+
}
|
|
191
|
+
function resolveModelAPIMethod(npm) {
|
|
192
|
+
const protocol = protocolForPackage(npm);
|
|
193
|
+
if (protocol === KnownProviderEnum.openai || protocol === KnownProviderEnum.xai) return APIMethodEnum.responses;
|
|
194
|
+
return APIMethodEnum.languageModel;
|
|
195
|
+
}
|
|
196
|
+
function resolveProviderOptionsKey(protocol) {
|
|
197
|
+
if (protocol === KnownProviderEnum.openaiCompatible) return "openai-compatible";
|
|
198
|
+
if (protocol === KnownProviderEnum.googleVertex) return "google-vertex";
|
|
199
|
+
if (protocol === KnownProviderEnum.googleVertexAnthropic) return "google-vertex-anthropic";
|
|
200
|
+
return protocol;
|
|
201
|
+
}
|
|
202
|
+
function roundCost(value) {
|
|
203
|
+
return Number(value.toFixed(6));
|
|
204
|
+
}
|
|
205
|
+
/** models.dev prices, with its context tiers; a rate a tier does not list keeps the base price (pi). */
|
|
206
|
+
function modelsDevCost(cost) {
|
|
207
|
+
const base = {
|
|
208
|
+
input: cost?.input ?? 0,
|
|
209
|
+
output: cost?.output ?? 0,
|
|
210
|
+
cacheRead: cost?.cache_read ?? 0,
|
|
211
|
+
cacheWrite: cost?.cache_write ?? 0
|
|
212
|
+
};
|
|
213
|
+
const tiers = cost?.tiers?.flatMap((tier) => {
|
|
214
|
+
const context = tier.tier;
|
|
215
|
+
if (context?.type !== "context" || context.size === void 0) return [];
|
|
216
|
+
return [{
|
|
217
|
+
inputTokensAbove: context.size,
|
|
218
|
+
input: tier.input ?? base.input,
|
|
219
|
+
output: tier.output ?? base.output,
|
|
220
|
+
cacheRead: tier.cache_read ?? base.cacheRead,
|
|
221
|
+
cacheWrite: tier.cache_write ?? base.cacheWrite
|
|
222
|
+
}];
|
|
223
|
+
});
|
|
224
|
+
return tiers && tiers.length > 0 ? {
|
|
225
|
+
...base,
|
|
226
|
+
tiers
|
|
227
|
+
} : base;
|
|
228
|
+
}
|
|
229
|
+
/** The efforts models.dev verified for a model, or undefined when it lists none. */
|
|
230
|
+
function modelsDevEfforts(model) {
|
|
231
|
+
const efforts = model?.reasoning_options?.flatMap((option) => option.type === "effort" && Array.isArray(option.values) ? option.values : []);
|
|
232
|
+
return efforts && efforts.length > 0 ? efforts : void 0;
|
|
233
|
+
}
|
|
234
|
+
function mergeThinkingLevelMap(model, map) {
|
|
235
|
+
model.thinkingLevelMap = {
|
|
236
|
+
...model.thinkingLevelMap,
|
|
237
|
+
...map
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function mergeCompat(model, compat) {
|
|
241
|
+
model.compat = {
|
|
242
|
+
...model.compat,
|
|
243
|
+
...compat
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/** Merge the level map models.dev's verified efforts give, when it lists any. */
|
|
247
|
+
function applyEffortThinkingLevels(model, source) {
|
|
248
|
+
const efforts = modelsDevEfforts(source);
|
|
249
|
+
const map = efforts ? effortThinkingLevels(efforts) : void 0;
|
|
250
|
+
if (map) mergeThinkingLevelMap(model, map);
|
|
251
|
+
}
|
|
252
|
+
const OPENAI_LONG_CONTEXT_INPUT_THRESHOLD = 272e3;
|
|
253
|
+
const OPENAI_MAX_TOKENS = 128e3;
|
|
254
|
+
const OPENAI_RESPONSES_NONE_REASONING_MODELS = /* @__PURE__ */ new Set([
|
|
255
|
+
"gpt-5.1",
|
|
256
|
+
"gpt-5.2",
|
|
257
|
+
"gpt-5.3-codex",
|
|
258
|
+
"gpt-5.4",
|
|
259
|
+
"gpt-5.4-mini",
|
|
260
|
+
"gpt-5.4-nano",
|
|
261
|
+
"gpt-5.5",
|
|
262
|
+
"gpt-5.6-luna",
|
|
263
|
+
"gpt-5.6-sol",
|
|
264
|
+
"gpt-5.6-terra",
|
|
265
|
+
"gpt-6-luna",
|
|
266
|
+
"gpt-6-sol"
|
|
267
|
+
]);
|
|
268
|
+
const OPENAI_GPT6_MODELS = /* @__PURE__ */ new Set([
|
|
269
|
+
"gpt-6-astra",
|
|
270
|
+
"gpt-6-luna",
|
|
271
|
+
"gpt-6-sol",
|
|
272
|
+
"gpt-6.1-sol"
|
|
273
|
+
]);
|
|
274
|
+
const OPENAI_GPT6_NO_NONE_MODELS = /* @__PURE__ */ new Set(["gpt-6-astra", "gpt-6.1-sol"]);
|
|
275
|
+
const OPENAI_NO_MINIMAL_REASONING = /gpt-5\.[456]|gpt-6/;
|
|
276
|
+
const OPENAI_SHORT_CONTEXT_CAPPED_MODELS = /* @__PURE__ */ new Set([
|
|
277
|
+
"gpt-5.4",
|
|
278
|
+
"gpt-5.5",
|
|
279
|
+
"gpt-5.6-luna",
|
|
280
|
+
"gpt-5.6-sol",
|
|
281
|
+
"gpt-5.6-terra",
|
|
282
|
+
"gpt-6-astra",
|
|
283
|
+
"gpt-6-luna",
|
|
284
|
+
"gpt-6-sol",
|
|
285
|
+
"gpt-6.1-sol"
|
|
286
|
+
]);
|
|
287
|
+
const OPENAI_LONG_CONTEXT_PRICING_MODELS = /* @__PURE__ */ new Set([
|
|
288
|
+
...OPENAI_SHORT_CONTEXT_CAPPED_MODELS,
|
|
289
|
+
"gpt-5.4-pro",
|
|
290
|
+
"gpt-5.5-pro"
|
|
291
|
+
]);
|
|
292
|
+
function isOpenAiResponses(model) {
|
|
293
|
+
return model.protocol === KnownProviderEnum.openai || model.protocol === KnownProviderEnum.openaiCodex;
|
|
294
|
+
}
|
|
295
|
+
function isOpenAiDirect(model) {
|
|
296
|
+
return model.protocol === KnownProviderEnum.openai && model.provider.id === "openai";
|
|
297
|
+
}
|
|
298
|
+
function supportsOpenAiXhigh(model) {
|
|
299
|
+
return /gpt-5\.[2-6]|gpt-6/.test(model.id);
|
|
300
|
+
}
|
|
301
|
+
function supportsOpenAiMax(model) {
|
|
302
|
+
return isOpenAiResponses(model) && /gpt-5\.6|gpt-6/.test(model.id);
|
|
303
|
+
}
|
|
304
|
+
function withOpenAiLongContextPricing(cost) {
|
|
305
|
+
return {
|
|
306
|
+
...cost,
|
|
307
|
+
tiers: [{
|
|
308
|
+
inputTokensAbove: OPENAI_LONG_CONTEXT_INPUT_THRESHOLD,
|
|
309
|
+
input: roundCost(cost.input * 2),
|
|
310
|
+
output: roundCost(cost.output * 1.5),
|
|
311
|
+
cacheRead: roundCost(cost.cacheRead * 2),
|
|
312
|
+
cacheWrite: roundCost(cost.cacheWrite * 2)
|
|
313
|
+
}]
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Price multipliers per service tier: models.dev's modes that set `service_tier` (fast is
|
|
318
|
+
* `priority`), over OpenAI's flex 0.5x / priority 2x list defaults.
|
|
319
|
+
*/
|
|
320
|
+
function serviceTierMultipliers(model, source) {
|
|
321
|
+
const multipliers = {
|
|
322
|
+
flex: .5,
|
|
323
|
+
priority: 2
|
|
324
|
+
};
|
|
325
|
+
for (const mode of Object.values(source?.experimental?.modes ?? {})) {
|
|
326
|
+
const tier = mode.provider?.body?.service_tier;
|
|
327
|
+
const input = mode.cost?.input;
|
|
328
|
+
if (typeof tier !== "string" || input === void 0 || model.cost.input <= 0) continue;
|
|
329
|
+
multipliers[tier] = roundCost(input / model.cost.input);
|
|
330
|
+
}
|
|
331
|
+
return multipliers;
|
|
332
|
+
}
|
|
333
|
+
function applyOpenAiMetadata(model, source) {
|
|
334
|
+
const id = model.id;
|
|
335
|
+
if (isOpenAiDirect(model)) {
|
|
336
|
+
if (OPENAI_SHORT_CONTEXT_CAPPED_MODELS.has(id)) {
|
|
337
|
+
model.contextWindow = OPENAI_LONG_CONTEXT_INPUT_THRESHOLD;
|
|
338
|
+
model.maxTokens = OPENAI_MAX_TOKENS;
|
|
339
|
+
}
|
|
340
|
+
if (OPENAI_LONG_CONTEXT_PRICING_MODELS.has(id) && !model.cost.tiers) model.cost = withOpenAiLongContextPricing(model.cost);
|
|
341
|
+
if (id === "gpt-5-pro") model.maxTokens = OPENAI_MAX_TOKENS;
|
|
342
|
+
}
|
|
343
|
+
model.cost.serviceTierMultipliers = serviceTierMultipliers(model, source);
|
|
344
|
+
applyEffortThinkingLevels(model, source);
|
|
345
|
+
if (model.protocol === KnownProviderEnum.openai && id.startsWith("gpt-5")) mergeThinkingLevelMap(model, { off: null });
|
|
346
|
+
if (OPENAI_GPT6_MODELS.has(id)) mergeThinkingLevelMap(model, {
|
|
347
|
+
off: OPENAI_GPT6_NO_NONE_MODELS.has(id) ? null : "none",
|
|
348
|
+
minimal: null,
|
|
349
|
+
low: "low",
|
|
350
|
+
medium: "medium",
|
|
351
|
+
high: "high",
|
|
352
|
+
xhigh: "xhigh",
|
|
353
|
+
max: "max"
|
|
354
|
+
});
|
|
355
|
+
if (isOpenAiDirect(model) && OPENAI_RESPONSES_NONE_REASONING_MODELS.has(id)) mergeThinkingLevelMap(model, { off: "none" });
|
|
356
|
+
if (supportsOpenAiMax(model)) mergeThinkingLevelMap(model, { max: "max" });
|
|
357
|
+
if (OPENAI_NO_MINIMAL_REASONING.test(id)) mergeThinkingLevelMap(model, { minimal: null });
|
|
358
|
+
if (id.endsWith("gpt-5.5-pro")) mergeThinkingLevelMap(model, {
|
|
359
|
+
off: null,
|
|
360
|
+
minimal: null,
|
|
361
|
+
low: null
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function isAnthropicMessages(model) {
|
|
365
|
+
return model.protocol === KnownProviderEnum.anthropic || model.protocol === KnownProviderEnum.googleVertexAnthropic;
|
|
366
|
+
}
|
|
367
|
+
const ANTHROPIC_NO_TEMPERATURE = /opus-4[-.][78]|opus-5|(sonnet|haiku)-5[-.]5/;
|
|
368
|
+
function applyAnthropicMetadata(model) {
|
|
369
|
+
const id = model.id;
|
|
370
|
+
if (/sonnet-4[-.]5/.test(id)) model.contextWindow = 2e5;
|
|
371
|
+
if (isAnthropicAdaptiveThinkingModel(id)) mergeCompat(model, { forceAdaptiveThinking: true });
|
|
372
|
+
if (/(opus|sonnet)-4[-.]6/.test(id)) mergeThinkingLevelMap(model, { max: "max" });
|
|
373
|
+
if (/opus-4[-.][78]|(opus|sonnet|fable|haiku)-5/.test(id)) mergeThinkingLevelMap(model, {
|
|
374
|
+
xhigh: "xhigh",
|
|
375
|
+
max: "max"
|
|
376
|
+
});
|
|
377
|
+
if (/(opus|sonnet|haiku)-5[-.]5/.test(id)) mergeThinkingLevelMap(model, {
|
|
378
|
+
...id.includes("haiku") ? {} : { off: null },
|
|
379
|
+
minimal: null,
|
|
380
|
+
low: "low",
|
|
381
|
+
medium: "medium",
|
|
382
|
+
high: "high",
|
|
383
|
+
xhigh: "xhigh",
|
|
384
|
+
max: "max"
|
|
385
|
+
});
|
|
386
|
+
if (/fable-5/.test(id)) mergeThinkingLevelMap(model, { off: null });
|
|
387
|
+
if (ANTHROPIC_NO_TEMPERATURE.test(id)) mergeCompat(model, { supportsTemperature: false });
|
|
388
|
+
}
|
|
389
|
+
function applyGoogleThinkingMetadata(model) {
|
|
390
|
+
const id = model.id.toLowerCase();
|
|
391
|
+
const supportsThinkingLevel = /gemini-3(?:\.\d+)?-(?:pro|flash)|gemma-?4/.test(id) || id === "gemini-flash-latest" || id === "gemini-flash-lite-latest";
|
|
392
|
+
mergeCompat(model, { supportsThinkingLevel });
|
|
393
|
+
if (supportsThinkingLevel) return;
|
|
394
|
+
model.thinkingBudgets = [
|
|
395
|
+
["2.5-pro", {
|
|
396
|
+
minimal: 128,
|
|
397
|
+
low: 2048,
|
|
398
|
+
medium: 8192,
|
|
399
|
+
high: 32768
|
|
400
|
+
}],
|
|
401
|
+
["2.5-flash-lite", {
|
|
402
|
+
minimal: 512,
|
|
403
|
+
low: 2048,
|
|
404
|
+
medium: 8192,
|
|
405
|
+
high: 24576
|
|
406
|
+
}],
|
|
407
|
+
["2.5-flash", {
|
|
408
|
+
minimal: 128,
|
|
409
|
+
low: 2048,
|
|
410
|
+
medium: 8192,
|
|
411
|
+
high: 24576
|
|
412
|
+
}]
|
|
413
|
+
].find(([family]) => id.includes(family))?.[1] ?? {
|
|
414
|
+
minimal: -1,
|
|
415
|
+
low: -1,
|
|
416
|
+
medium: -1,
|
|
417
|
+
high: -1
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function applyModelMetadata(model, source) {
|
|
421
|
+
if (model.protocol === KnownProviderEnum.google || model.protocol === KnownProviderEnum.googleVertex) {
|
|
422
|
+
applyGoogleThinkingMetadata(model);
|
|
423
|
+
if (/gemini-3(?:\.\d+)?-pro|gemini-3\.[78]-flash/.test(model.id.toLowerCase())) mergeThinkingLevelMap(model, {
|
|
424
|
+
off: "low",
|
|
425
|
+
minimal: null
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
if (model.id.includes("opus-4-6") || model.id.includes("opus-4.6")) mergeThinkingLevelMap(model, { xhigh: "max" });
|
|
429
|
+
if (model.id.includes("opus-4-7") || model.id.includes("opus-4.7")) mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
|
430
|
+
if (isOpenAiResponses(model)) applyOpenAiMetadata(model, source);
|
|
431
|
+
if (supportsOpenAiXhigh(model)) mergeThinkingLevelMap(model, { xhigh: "xhigh" });
|
|
432
|
+
if (isAnthropicMessages(model)) applyAnthropicMetadata(model);
|
|
433
|
+
}
|
|
434
|
+
const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
|
|
435
|
+
const OPENAI_CODEX_NPM = "@codeworksh/ai-sdk-openai-codex";
|
|
436
|
+
const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
437
|
+
const OPENAI_CODEX_CONTEXT = 272e3;
|
|
438
|
+
const OPENAI_CODEX_MODELS = [
|
|
439
|
+
{
|
|
440
|
+
id: "gpt-5.3-codex-spark",
|
|
441
|
+
contextWindow: 128e3
|
|
442
|
+
},
|
|
443
|
+
{ id: "gpt-5.5" },
|
|
444
|
+
{ id: "gpt-5.6-luna" },
|
|
445
|
+
{ id: "gpt-5.6-sol" },
|
|
446
|
+
{ id: "gpt-5.6-terra" },
|
|
447
|
+
{ id: "gpt-6-astra" },
|
|
448
|
+
{ id: "gpt-6-luna" },
|
|
449
|
+
{ id: "gpt-6-sol" },
|
|
450
|
+
{
|
|
451
|
+
id: "gpt-6.1-sol",
|
|
452
|
+
contextWindow: 5e5
|
|
453
|
+
}
|
|
454
|
+
];
|
|
455
|
+
const OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
456
|
+
"gpt-5.6-luna",
|
|
457
|
+
"gpt-5.6-sol",
|
|
458
|
+
"gpt-5.6-terra",
|
|
459
|
+
"gpt-6-astra",
|
|
460
|
+
"gpt-6-luna",
|
|
461
|
+
"gpt-6-sol",
|
|
462
|
+
"gpt-6.1-sol"
|
|
463
|
+
]);
|
|
464
|
+
const OPENAI_CODEX_TOOL_SEARCH_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.5", ...OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS]);
|
|
465
|
+
const OPENAI_CODEX_NONE_REASONING_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
466
|
+
"gpt-5.5",
|
|
467
|
+
"gpt-5.6-luna",
|
|
468
|
+
"gpt-6-luna",
|
|
469
|
+
"gpt-6-sol"
|
|
470
|
+
]);
|
|
471
|
+
/** The Codex models, from the generated `openai` entries; one models.dev does not list is skipped. */
|
|
472
|
+
function openAICodexBuiltInModels(openai) {
|
|
473
|
+
const models = {};
|
|
474
|
+
for (const seed of OPENAI_CODEX_MODELS) {
|
|
475
|
+
const base = openai[seed.id];
|
|
476
|
+
if (!base) continue;
|
|
477
|
+
const info = {
|
|
478
|
+
...base,
|
|
479
|
+
provider: {
|
|
480
|
+
id: OPENAI_CODEX_PROVIDER_ID,
|
|
481
|
+
name: "OpenAI Codex (ChatGPT)",
|
|
482
|
+
source: "custom",
|
|
483
|
+
env: ["OPENAI_CODEX_API_KEY"]
|
|
484
|
+
},
|
|
485
|
+
baseUrl: OPENAI_CODEX_BASE_URL,
|
|
486
|
+
reasoning: true,
|
|
487
|
+
thinkingLevelMap: {
|
|
488
|
+
...base.thinkingLevelMap,
|
|
489
|
+
off: OPENAI_CODEX_NONE_REASONING_MODEL_IDS.has(seed.id) ? "none" : null,
|
|
490
|
+
...supportsOpenAiXhigh(base) ? { minimal: "low" } : {}
|
|
491
|
+
},
|
|
492
|
+
contextWindow: seed.contextWindow ?? OPENAI_CODEX_CONTEXT,
|
|
493
|
+
maxTokens: OPENAI_MAX_TOKENS,
|
|
494
|
+
npm: OPENAI_CODEX_NPM,
|
|
495
|
+
api: {
|
|
496
|
+
id: seed.id,
|
|
497
|
+
url: OPENAI_CODEX_BASE_URL,
|
|
498
|
+
method: APIMethodEnum.responses
|
|
499
|
+
},
|
|
500
|
+
providerOptionsKey: OPENAI_CODEX_PROVIDER_ID,
|
|
501
|
+
compat: {
|
|
502
|
+
supportsOpenAIGrammarTools: true,
|
|
503
|
+
...OPENAI_CODEX_TOOL_SEARCH_MODEL_IDS.has(seed.id) ? { supportsToolSearch: true } : {},
|
|
504
|
+
...OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS.has(seed.id) ? { supportsAdditionalTools: true } : {}
|
|
505
|
+
},
|
|
506
|
+
protocol: KnownProviderEnum.openaiCodex
|
|
507
|
+
};
|
|
508
|
+
delete info.headers;
|
|
509
|
+
models[seed.id] = info;
|
|
510
|
+
}
|
|
511
|
+
return models;
|
|
512
|
+
}
|
|
513
|
+
const GITHUB_COPILOT_PROVIDER_ID = "github-copilot";
|
|
514
|
+
const GITHUB_COPILOT_NPM = "@codeworksh/ai-sdk-github-copilot";
|
|
515
|
+
const GITHUB_COPILOT_BASE_URL = "https://api.githubcopilot.com";
|
|
516
|
+
const GITHUB_COPILOT_EXTENDED_CONTEXT = 1e6;
|
|
517
|
+
const GITHUB_COPILOT_EXTENDED_CONTEXT_MODELS = /* @__PURE__ */ new Set([
|
|
518
|
+
"claude-fable-5",
|
|
519
|
+
"claude-opus-4.6",
|
|
520
|
+
"claude-opus-4.7",
|
|
521
|
+
"claude-opus-4.8",
|
|
522
|
+
"claude-opus-5",
|
|
523
|
+
"claude-sonnet-4.6",
|
|
524
|
+
"claude-sonnet-5",
|
|
525
|
+
"gpt-5.3-codex",
|
|
526
|
+
"gpt-5.4",
|
|
527
|
+
"gpt-5.5"
|
|
528
|
+
]);
|
|
529
|
+
const GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES = {
|
|
530
|
+
"claude-opus-4.7": { minimal: "low" },
|
|
531
|
+
"claude-opus-4.8": { minimal: "low" },
|
|
532
|
+
"claude-opus-5": { minimal: "low" },
|
|
533
|
+
"claude-sonnet-4.6": {
|
|
534
|
+
minimal: "low",
|
|
535
|
+
max: "max"
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
/**
|
|
539
|
+
* The offline routing approximation (pi). The live `/models` response's
|
|
540
|
+
* `supported_endpoints` is authoritative at runtime.
|
|
541
|
+
*
|
|
542
|
+
* - `claude-(haiku|sonnet|opus|fable)-[45]` → Anthropic Messages
|
|
543
|
+
* - `gpt-*`, `grok-*`, `oswe*`, `mai-*` → OpenAI Responses
|
|
544
|
+
* - everything else → OpenAI Chat Completions
|
|
545
|
+
*/
|
|
546
|
+
function githubCopilotApiMethod(modelId) {
|
|
547
|
+
if (/^claude-(haiku|sonnet|opus|fable)-[45]([.-]|$)/.test(modelId)) return APIMethodEnum.messages;
|
|
548
|
+
const gpt = /^gpt-(\d+)/.exec(modelId);
|
|
549
|
+
if (gpt !== null && Number(gpt[1]) >= 5 || modelId.startsWith("grok-") || modelId.startsWith("oswe") || modelId.startsWith("mai-")) return APIMethodEnum.responses;
|
|
550
|
+
return APIMethodEnum.chat;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Derive the level map from models.dev `reasoning_options`: a level maps to
|
|
554
|
+
* itself only when the endpoint actually advertises it. `minimal` degrades to
|
|
555
|
+
* `low` — the lowest effort every reasoning model accepts.
|
|
556
|
+
*/
|
|
557
|
+
function githubCopilotThinkingLevels(model, method) {
|
|
558
|
+
const listed = modelsDevEfforts(model);
|
|
559
|
+
const efforts = listed ? new Set(listed) : void 0;
|
|
560
|
+
const map = {};
|
|
561
|
+
if (method !== APIMethodEnum.messages) map.off = null;
|
|
562
|
+
if (!efforts) return Object.keys(map).length > 0 ? map : void 0;
|
|
563
|
+
if (efforts.has("minimal")) map.minimal = "minimal";
|
|
564
|
+
else if (efforts.has("low")) map.minimal = "low";
|
|
565
|
+
for (const level of [
|
|
566
|
+
"low",
|
|
567
|
+
"medium",
|
|
568
|
+
"high",
|
|
569
|
+
"xhigh",
|
|
570
|
+
"max"
|
|
571
|
+
]) map[level] = efforts.has(level) ? level : null;
|
|
572
|
+
return map;
|
|
573
|
+
}
|
|
574
|
+
function githubCopilotBuiltInModels(provider) {
|
|
575
|
+
const models = {};
|
|
576
|
+
if (!provider) return models;
|
|
577
|
+
for (const [id, source] of Object.entries(provider.models)) {
|
|
578
|
+
if (source.tool_call !== true) continue;
|
|
579
|
+
if (source.status === "deprecated") continue;
|
|
580
|
+
if (id === "gpt-5-chat-latest") continue;
|
|
581
|
+
const base = applyModification(GITHUB_COPILOT_PROVIDER_ID, provider, source);
|
|
582
|
+
if (!base) continue;
|
|
583
|
+
const method = githubCopilotApiMethod(id);
|
|
584
|
+
const info = {
|
|
585
|
+
...base,
|
|
586
|
+
provider: {
|
|
587
|
+
id: GITHUB_COPILOT_PROVIDER_ID,
|
|
588
|
+
name: "GitHub Copilot",
|
|
589
|
+
source: "custom",
|
|
590
|
+
env: ["COPILOT_GITHUB_TOKEN"]
|
|
591
|
+
},
|
|
592
|
+
baseUrl: GITHUB_COPILOT_BASE_URL,
|
|
593
|
+
headers: { ...GITHUB_COPILOT_STATIC_HEADERS },
|
|
594
|
+
npm: GITHUB_COPILOT_NPM,
|
|
595
|
+
api: {
|
|
596
|
+
id,
|
|
597
|
+
url: GITHUB_COPILOT_BASE_URL,
|
|
598
|
+
method
|
|
599
|
+
},
|
|
600
|
+
providerOptionsKey: GITHUB_COPILOT_PROVIDER_ID,
|
|
601
|
+
protocol: KnownProviderEnum.githubCopilot,
|
|
602
|
+
...method === APIMethodEnum.responses ? { providerOptions: {
|
|
603
|
+
...base.providerOptions,
|
|
604
|
+
[GITHUB_COPILOT_PROVIDER_ID]: {
|
|
605
|
+
store: false,
|
|
606
|
+
include: ["reasoning.encrypted_content"]
|
|
607
|
+
}
|
|
608
|
+
} } : {}
|
|
609
|
+
};
|
|
610
|
+
if (GITHUB_COPILOT_EXTENDED_CONTEXT_MODELS.has(id)) info.contextWindow = GITHUB_COPILOT_EXTENDED_CONTEXT;
|
|
611
|
+
if (method === APIMethodEnum.messages && isAnthropicAdaptiveThinkingModel(id)) mergeCompat(info, { forceAdaptiveThinking: true });
|
|
612
|
+
const gpt = /^gpt-(\d+)/.exec(id);
|
|
613
|
+
if (method === APIMethodEnum.responses && gpt !== null && Number(gpt[1]) >= 5) mergeCompat(info, { supportsOpenAIGrammarTools: true });
|
|
614
|
+
if (id.startsWith("gpt-5")) mergeThinkingLevelMap(info, {
|
|
615
|
+
off: null,
|
|
616
|
+
minimal: "low"
|
|
617
|
+
});
|
|
618
|
+
if (id.includes("fable-5")) mergeThinkingLevelMap(info, {
|
|
619
|
+
off: null,
|
|
620
|
+
xhigh: "xhigh",
|
|
621
|
+
max: "max"
|
|
622
|
+
});
|
|
623
|
+
const levels = githubCopilotThinkingLevels(source, method);
|
|
624
|
+
if (levels) mergeThinkingLevelMap(info, levels);
|
|
625
|
+
const override = GITHUB_COPILOT_THINKING_LEVEL_OVERRIDES[id];
|
|
626
|
+
if (override) mergeThinkingLevelMap(info, override);
|
|
627
|
+
models[id] = info;
|
|
628
|
+
}
|
|
629
|
+
return models;
|
|
630
|
+
}
|
|
631
|
+
/** OpenRouter's listing as catalog entries, or undefined when it is missing or unreadable. */
|
|
632
|
+
function openRouterModels(listing) {
|
|
633
|
+
if (listing === void 0) return void 0;
|
|
634
|
+
try {
|
|
635
|
+
const models = catalog(listing);
|
|
636
|
+
return Object.keys(models).length > 0 ? models : void 0;
|
|
637
|
+
} catch {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
/** Object keys in order at every level, so identical content serializes to identical bytes. */
|
|
642
|
+
function sortKeys(value) {
|
|
643
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
644
|
+
if (typeof value !== "object" || value === null) return value;
|
|
645
|
+
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, entry]) => [key, sortKeys(entry)]));
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* The catalog from fetched sources, keys sorted so identical content serializes to identical
|
|
649
|
+
* bytes. OpenRouter's own listing replaces models.dev's copy of it.
|
|
650
|
+
*/
|
|
651
|
+
function buildCatalog(sources) {
|
|
652
|
+
const modelsDev = loadBuiltInFromModelsDev(sources.modelsDev);
|
|
653
|
+
const openrouter = openRouterModels(sources.openRouter);
|
|
654
|
+
const copilotProvider = sources.modelsDev[GITHUB_COPILOT_PROVIDER_ID];
|
|
655
|
+
return sortKeys({
|
|
656
|
+
...modelsDev,
|
|
657
|
+
...openrouter ? { [PROVIDER_ID]: openrouter } : {},
|
|
658
|
+
[OPENAI_CODEX_PROVIDER_ID]: openAICodexBuiltInModels(modelsDev.openai ?? {}),
|
|
659
|
+
...copilotProvider ? { [GITHUB_COPILOT_PROVIDER_ID]: githubCopilotBuiltInModels(copilotProvider) } : {}
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
async function generateModels(args = {}) {
|
|
663
|
+
const path$1 = resolve(args.path ?? path());
|
|
664
|
+
const [modelsDev, openRouter] = await Promise.all([pullModelsDevData(), pullOpenRouterData()]);
|
|
665
|
+
const catalog = buildCatalog({
|
|
666
|
+
modelsDev,
|
|
667
|
+
openRouter
|
|
668
|
+
});
|
|
669
|
+
await writeJsonAtomic(path$1, args.baseline ? pick(catalog, BASELINE_PROVIDERS) : catalog);
|
|
670
|
+
return path$1;
|
|
671
|
+
}
|
|
672
|
+
const ModelgenCommand = {
|
|
673
|
+
command: "modelgen [path]",
|
|
674
|
+
describe: "generate models.gen.json",
|
|
675
|
+
builder: (yargs) => yargs.positional("path", {
|
|
676
|
+
type: "string",
|
|
677
|
+
describe: "output path (defaults to CODEWORK_MODELS_FILE or ./models.gen.json)"
|
|
678
|
+
}).option("baseline", {
|
|
679
|
+
type: "boolean",
|
|
680
|
+
describe: `keep only the bundled baseline providers (${BASELINE_PROVIDERS.join(", ")})`
|
|
681
|
+
}),
|
|
682
|
+
handler: async (args) => {
|
|
683
|
+
const path = await generateModels(args);
|
|
684
|
+
console.log(`Generated model catalog at ${path}`);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
function applyModification(providerId, provider, model) {
|
|
688
|
+
const npm = resolveModelNpm(provider, model);
|
|
689
|
+
if (!isAISDKPackage(npm)) return;
|
|
690
|
+
const protocol = protocolForPackage(npm);
|
|
691
|
+
const baseUrl = resolveModelBaseUrl(provider, model);
|
|
692
|
+
const providerInfo = {
|
|
693
|
+
id: providerId,
|
|
694
|
+
name: provider.name,
|
|
695
|
+
source: "api",
|
|
696
|
+
env: provider.env
|
|
697
|
+
};
|
|
698
|
+
if (provider.key) providerInfo.key = provider.key;
|
|
699
|
+
const api = {
|
|
700
|
+
id: model.id,
|
|
701
|
+
method: resolveModelAPIMethod(npm)
|
|
702
|
+
};
|
|
703
|
+
if (baseUrl) api.url = baseUrl;
|
|
704
|
+
const info = {
|
|
705
|
+
id: model.id,
|
|
706
|
+
name: model.name,
|
|
707
|
+
provider: providerInfo,
|
|
708
|
+
baseUrl,
|
|
709
|
+
reasoning: Boolean(model.reasoning),
|
|
710
|
+
input: normalizeInput(model.modalities.input),
|
|
711
|
+
cost: modelsDevCost(model.cost),
|
|
712
|
+
contextWindow: model.limit?.context ?? 4096,
|
|
713
|
+
maxTokens: model.limit?.output ?? 4096,
|
|
714
|
+
headers: {
|
|
715
|
+
...provider.headers,
|
|
716
|
+
...model.provider?.headers,
|
|
717
|
+
...model.headers
|
|
718
|
+
},
|
|
719
|
+
npm,
|
|
720
|
+
api,
|
|
721
|
+
providerOptionsKey: resolveProviderOptionsKey(protocol),
|
|
722
|
+
protocol
|
|
723
|
+
};
|
|
724
|
+
if (Object.keys(info.headers ?? {}).length === 0) delete info.headers;
|
|
725
|
+
applyModelMetadata(info, model);
|
|
726
|
+
return info;
|
|
727
|
+
}
|
|
728
|
+
//#endregion
|
|
729
|
+
export { personalize as i, generateModels as n, PROVIDER_ID as r, ModelgenCommand as t };
|
|
730
|
+
|
|
731
|
+
//# sourceMappingURL=modelgen-DDO_NHoQ.mjs.map
|