@akon-labs/nexus-cli 0.1.7 → 0.1.8
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 +6 -0
- package/dist/cli.js +1192 -529
- package/dist/extensions/gitnexus/gateway.d.ts +2 -0
- package/dist/extensions/gitnexus/gateway.d.ts.map +1 -1
- package/dist/extensions/gitnexus/gateway.js +27 -0
- package/dist/extensions/gitnexus/gateway.js.map +1 -1
- package/dist/extensions/gitnexus/index.d.ts.map +1 -1
- package/dist/extensions/gitnexus/index.js +16 -1
- package/dist/extensions/gitnexus/index.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/subagent/index.d.ts +110 -0
- package/dist/extensions/subagent/index.d.ts.map +1 -0
- package/dist/extensions/subagent/index.js +568 -0
- package/dist/extensions/subagent/index.js.map +1 -0
- package/dist/index.js +1236 -573
- package/dist/rpc-entry.js +1192 -529
- package/dist/vendor/ai.js +110 -15
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -174,15 +174,15 @@ function defaultProviderAuthContext() {
|
|
|
174
174
|
const value = getProcessEnv()?.[name];
|
|
175
175
|
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
176
176
|
},
|
|
177
|
-
async fileExists(
|
|
177
|
+
async fileExists(path12) {
|
|
178
178
|
try {
|
|
179
|
-
const
|
|
180
|
-
let resolved =
|
|
179
|
+
const fs8 = await importNodeModule("node:fs/promises");
|
|
180
|
+
let resolved = path12;
|
|
181
181
|
if (resolved.startsWith("~")) {
|
|
182
|
-
const
|
|
183
|
-
resolved =
|
|
182
|
+
const os6 = await importNodeModule("node:os");
|
|
183
|
+
resolved = os6.homedir() + resolved.slice(1);
|
|
184
184
|
}
|
|
185
|
-
await
|
|
185
|
+
await fs8.access(resolved);
|
|
186
186
|
return true;
|
|
187
187
|
} catch {
|
|
188
188
|
return false;
|
|
@@ -391,7 +391,7 @@ async function resolveProviderAuthWithSignal(provider, credentials, authContext,
|
|
|
391
391
|
function overlayEnvAuthContext(base, env) {
|
|
392
392
|
return {
|
|
393
393
|
env: async (name) => env[name] || await base.env(name),
|
|
394
|
-
fileExists: (
|
|
394
|
+
fileExists: (path12) => base.fileExists(path12)
|
|
395
395
|
};
|
|
396
396
|
}
|
|
397
397
|
async function resolveStoredOAuth(credentials, providerId, oauth, stored, signal, minOAuthValidityMs) {
|
|
@@ -6891,6 +6891,15 @@ function isEncryptedReasoningDetail(detail) {
|
|
|
6891
6891
|
const candidate = detail;
|
|
6892
6892
|
return candidate.type === "reasoning.encrypted" && typeof candidate.id === "string" && candidate.id.length > 0 && typeof candidate.data === "string" && candidate.data.length > 0;
|
|
6893
6893
|
}
|
|
6894
|
+
function parseEncryptedReasoningDetail(signature) {
|
|
6895
|
+
if (!signature) return void 0;
|
|
6896
|
+
try {
|
|
6897
|
+
const detail = JSON.parse(signature);
|
|
6898
|
+
return isEncryptedReasoningDetail(detail) ? detail : void 0;
|
|
6899
|
+
} catch {
|
|
6900
|
+
return void 0;
|
|
6901
|
+
}
|
|
6902
|
+
}
|
|
6894
6903
|
function resolveCacheRetention3(cacheRetention, env) {
|
|
6895
6904
|
if (cacheRetention) {
|
|
6896
6905
|
return cacheRetention;
|
|
@@ -7287,6 +7296,18 @@ function convertMessages4(model, context, compat, options) {
|
|
|
7287
7296
|
assistantMsg.content = assistantText;
|
|
7288
7297
|
}
|
|
7289
7298
|
const toolCalls = msg.content.filter(isToolCallBlock);
|
|
7299
|
+
const reasoningDetails = msg.content.map((block) => {
|
|
7300
|
+
if (block.type === "thinking") {
|
|
7301
|
+
return parseEncryptedReasoningDetail(block.thinkingSignature);
|
|
7302
|
+
}
|
|
7303
|
+
if (block.type === "toolCall") {
|
|
7304
|
+
return parseEncryptedReasoningDetail(block.thoughtSignature);
|
|
7305
|
+
}
|
|
7306
|
+
return void 0;
|
|
7307
|
+
}).filter((detail) => detail !== void 0);
|
|
7308
|
+
if (reasoningDetails.length > 0) {
|
|
7309
|
+
assistantMsg.reasoning_details = reasoningDetails;
|
|
7310
|
+
}
|
|
7290
7311
|
if (toolCalls.length > 0) {
|
|
7291
7312
|
assistantMsg.tool_calls = toolCalls.map((tc) => {
|
|
7292
7313
|
const customInputProperty = options?.grammarToolInputProperties?.get(tc.name);
|
|
@@ -7309,23 +7330,13 @@ function convertMessages4(model, context, compat, options) {
|
|
|
7309
7330
|
}
|
|
7310
7331
|
};
|
|
7311
7332
|
});
|
|
7312
|
-
const reasoningDetails = toolCalls.filter((tc) => tc.thoughtSignature).map((tc) => {
|
|
7313
|
-
try {
|
|
7314
|
-
return JSON.parse(tc.thoughtSignature);
|
|
7315
|
-
} catch {
|
|
7316
|
-
return null;
|
|
7317
|
-
}
|
|
7318
|
-
}).filter(Boolean);
|
|
7319
|
-
if (reasoningDetails.length > 0) {
|
|
7320
|
-
assistantMsg.reasoning_details = reasoningDetails;
|
|
7321
|
-
}
|
|
7322
7333
|
}
|
|
7323
7334
|
if (compat.requiresReasoningContentOnAssistantMessages && model.reasoning && assistantMsg.reasoning_content === void 0) {
|
|
7324
7335
|
assistantMsg.reasoning_content = "";
|
|
7325
7336
|
}
|
|
7326
7337
|
const content = assistantMsg.content;
|
|
7327
7338
|
const hasContent = content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : content.length > 0);
|
|
7328
|
-
if (!hasContent && !assistantMsg.tool_calls) {
|
|
7339
|
+
if (!hasContent && !assistantMsg.tool_calls && reasoningDetails.length === 0) {
|
|
7329
7340
|
continue;
|
|
7330
7341
|
}
|
|
7331
7342
|
params.push(assistantMsg);
|
|
@@ -7878,6 +7889,14 @@ var init_openai_completions = __esm({
|
|
|
7878
7889
|
for (const block of blocks) {
|
|
7879
7890
|
finishBlock(block);
|
|
7880
7891
|
}
|
|
7892
|
+
for (const serializedDetail of pendingReasoningDetailsByToolCallId.values()) {
|
|
7893
|
+
blocks.push({
|
|
7894
|
+
type: "thinking",
|
|
7895
|
+
thinking: "",
|
|
7896
|
+
thinkingSignature: serializedDetail,
|
|
7897
|
+
redacted: true
|
|
7898
|
+
});
|
|
7899
|
+
}
|
|
7881
7900
|
if (options?.signal?.aborted) {
|
|
7882
7901
|
throw new Error("Request was aborted");
|
|
7883
7902
|
}
|
|
@@ -12188,6 +12207,36 @@ var IMAGE_MODELS = {
|
|
|
12188
12207
|
cacheWrite: 0
|
|
12189
12208
|
}
|
|
12190
12209
|
},
|
|
12210
|
+
"bytedance-seed/seedream-5-0-lite": {
|
|
12211
|
+
id: "bytedance-seed/seedream-5-0-lite",
|
|
12212
|
+
name: "ByteDance Seed: Seedream 5.0 Lite",
|
|
12213
|
+
api: "openrouter-images",
|
|
12214
|
+
provider: "openrouter",
|
|
12215
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
12216
|
+
input: ["text", "image"],
|
|
12217
|
+
output: ["image"],
|
|
12218
|
+
cost: {
|
|
12219
|
+
input: 0,
|
|
12220
|
+
output: 0,
|
|
12221
|
+
cacheRead: 0,
|
|
12222
|
+
cacheWrite: 0
|
|
12223
|
+
}
|
|
12224
|
+
},
|
|
12225
|
+
"bytedance-seed/seedream-5-0-pro": {
|
|
12226
|
+
id: "bytedance-seed/seedream-5-0-pro",
|
|
12227
|
+
name: "ByteDance Seed: Seedream 5.0 Pro",
|
|
12228
|
+
api: "openrouter-images",
|
|
12229
|
+
provider: "openrouter",
|
|
12230
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
12231
|
+
input: ["text", "image"],
|
|
12232
|
+
output: ["image"],
|
|
12233
|
+
cost: {
|
|
12234
|
+
input: 0,
|
|
12235
|
+
output: 0,
|
|
12236
|
+
cacheRead: 0,
|
|
12237
|
+
cacheWrite: 0
|
|
12238
|
+
}
|
|
12239
|
+
},
|
|
12191
12240
|
"google/gemini-2.5-flash-image": {
|
|
12192
12241
|
id: "google/gemini-2.5-flash-image",
|
|
12193
12242
|
name: "Google: Nano Banana (Gemini 2.5 Flash Image)",
|
|
@@ -12200,7 +12249,7 @@ var IMAGE_MODELS = {
|
|
|
12200
12249
|
input: 0.3,
|
|
12201
12250
|
output: 2.5,
|
|
12202
12251
|
cacheRead: 0.03,
|
|
12203
|
-
cacheWrite: 0.
|
|
12252
|
+
cacheWrite: 0.0833333333333333
|
|
12204
12253
|
}
|
|
12205
12254
|
},
|
|
12206
12255
|
"google/gemini-3-pro-image": {
|
|
@@ -12473,6 +12522,36 @@ var IMAGE_MODELS = {
|
|
|
12473
12522
|
cacheWrite: 0
|
|
12474
12523
|
}
|
|
12475
12524
|
},
|
|
12525
|
+
"qwen/qwen-image-3": {
|
|
12526
|
+
id: "qwen/qwen-image-3",
|
|
12527
|
+
name: "Qwen: Qwen Image 3",
|
|
12528
|
+
api: "openrouter-images",
|
|
12529
|
+
provider: "openrouter",
|
|
12530
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
12531
|
+
input: ["text", "image"],
|
|
12532
|
+
output: ["image"],
|
|
12533
|
+
cost: {
|
|
12534
|
+
input: 0,
|
|
12535
|
+
output: 0,
|
|
12536
|
+
cacheRead: 0,
|
|
12537
|
+
cacheWrite: 0
|
|
12538
|
+
}
|
|
12539
|
+
},
|
|
12540
|
+
"qwen/qwen-image-3-pro": {
|
|
12541
|
+
id: "qwen/qwen-image-3-pro",
|
|
12542
|
+
name: "Qwen: Qwen Image 3 Pro",
|
|
12543
|
+
api: "openrouter-images",
|
|
12544
|
+
provider: "openrouter",
|
|
12545
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
12546
|
+
input: ["text", "image"],
|
|
12547
|
+
output: ["image"],
|
|
12548
|
+
cost: {
|
|
12549
|
+
input: 0,
|
|
12550
|
+
output: 0,
|
|
12551
|
+
cacheRead: 0,
|
|
12552
|
+
cacheWrite: 0
|
|
12553
|
+
}
|
|
12554
|
+
},
|
|
12476
12555
|
"recraft/recraft-v3": {
|
|
12477
12556
|
id: "recraft/recraft-v3",
|
|
12478
12557
|
name: "Recraft: Recraft V3",
|
|
@@ -12698,9 +12777,24 @@ var IMAGE_MODELS = {
|
|
|
12698
12777
|
cacheWrite: 0
|
|
12699
12778
|
}
|
|
12700
12779
|
},
|
|
12780
|
+
"x-ai/grok-imagine-image-2.0": {
|
|
12781
|
+
id: "x-ai/grok-imagine-image-2.0",
|
|
12782
|
+
name: "xAI: Grok Imagine Image 2.0",
|
|
12783
|
+
api: "openrouter-images",
|
|
12784
|
+
provider: "openrouter",
|
|
12785
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
12786
|
+
input: ["text", "image"],
|
|
12787
|
+
output: ["image"],
|
|
12788
|
+
cost: {
|
|
12789
|
+
input: 0,
|
|
12790
|
+
output: 0,
|
|
12791
|
+
cacheRead: 0,
|
|
12792
|
+
cacheWrite: 0
|
|
12793
|
+
}
|
|
12794
|
+
},
|
|
12701
12795
|
"x-ai/grok-imagine-image-quality": {
|
|
12702
12796
|
id: "x-ai/grok-imagine-image-quality",
|
|
12703
|
-
name: "
|
|
12797
|
+
name: "SpaceXAI: Grok Imagine Image Quality",
|
|
12704
12798
|
api: "openrouter-images",
|
|
12705
12799
|
provider: "openrouter",
|
|
12706
12800
|
baseUrl: "https://openrouter.ai/api/v1",
|
|
@@ -14065,8 +14159,8 @@ function formatValidationPath(error) {
|
|
|
14065
14159
|
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
14066
14160
|
}
|
|
14067
14161
|
}
|
|
14068
|
-
const
|
|
14069
|
-
return
|
|
14162
|
+
const path12 = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
14163
|
+
return path12 || "root";
|
|
14070
14164
|
}
|
|
14071
14165
|
function validateToolCall(tools, toolCall) {
|
|
14072
14166
|
const tool = tools.find((t) => t.name === toolCall.name);
|
|
@@ -14289,13 +14383,13 @@ var opencode_default = { "anthropic-messages": { "claude-fable-5": { id: "claude
|
|
|
14289
14383
|
var OPENCODE_MODELS = flattenModelCatalog("opencode", opencode_default);
|
|
14290
14384
|
|
|
14291
14385
|
// ../ai/src/providers/data/opencode-go.json
|
|
14292
|
-
var opencode_go_default = { "anthropic-messages": { "minimax-m3": { id: "minimax-m3", name: "MiniMax-M3", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072 } }, "openai-completions": { "deepseek-v4-flash": { id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "deepseek-v4-flash-vision-exp": { id: "deepseek-v4-flash-vision-exp", name: "DeepSeek V4 Flash Vision Exp", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "deepseek-v4-pro": { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro (New)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "glm-5.1": { id: "glm-5.1", name: "GLM-5.1", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 202752, maxTokens: 32768 }, "glm-5.2": { id: "glm-5.2", name: "GLM-5.2", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: "high", xhigh: null, max: "max" } }, "glm-5.3": { id: "glm-5.3", name: "GLM-5.3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" } }, hy3: { id: "hy3", name: "Hy3 (8x usage)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.0175, output: 0.0725, cacheRead: 4375e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 256e3, maxTokens: 64e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: null } }, "kimi-k2.6": { id: "kimi-k2.6", name: "Kimi K2.6", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, thinkingFormat: "deepseek", supportsReasoningEffort: false, maxTokensField: "max_tokens", supportsLongCacheRetention: false }, contextWindow: 262144, maxTokens: 65536, thinkingLevelMap: { minimal: null, low: null, medium: null } }, "kimi-k2.7-code": { id: "kimi-k2.7-code", name: "Kimi K2.7 Code", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 262144, maxTokens: 262144 }, "kimi-k3": { id: "kimi-k3", name: "Kimi K3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: null, xhigh: null, max: "max" } }, "mimo-v2.5": { id: "mimo-v2.5", name: "MiMo V2.5", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 128e3 }, "mimo-v2.5-pro": { id: "mimo-v2.5-pro", name: "MiMo V2.5 Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 128e3 }, "minimax-m2.7": { id: "minimax-m2.7", name: "MiniMax-M2.7", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 204800, maxTokens: 131072 }, "ox-alpha-free": { id: "ox-alpha-free", name: "Ox Alpha Free (Unlimited)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" } }, "qwen3.6-plus": { id: "qwen3.6-plus", name: "Qwen3.6 Plus", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.625 }, compat: { supportsStore: false, supportsDeveloperRole: false, thinkingFormat: "qwen", maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.7-max": { id: "qwen3.7-max", name: "Qwen3.7 Max", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 2.5, output: 7.5, cacheRead: 0.5, cacheWrite: 3.125 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.7-plus": { id: "qwen3.7-plus", name: "Qwen3.7 Plus", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.04, cacheWrite: 0.5 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.8-max": { id: "qwen3.8-max", name: "Qwen3.8 Max", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072 } }, "openai-responses": { "gpt-5.6-luna": { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" } }, "grok-4.5": { id: "grok-4.5", name: "Grok 4.5", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 5e5, maxTokens: 5e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null } }, "muse-spark-1.2-contributor": { id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null } } } };
|
|
14386
|
+
var opencode_go_default = { "anthropic-messages": { "minimax-m3": { id: "minimax-m3", name: "MiniMax-M3", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072 } }, "openai-completions": { "deepseek-v4-flash": { id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "deepseek-v4-flash-vision-exp": { id: "deepseek-v4-flash-vision-exp", name: "DeepSeek V4 Flash Vision Exp", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "deepseek-v4-pro": { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro (New)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" } }, "glm-5.1": { id: "glm-5.1", name: "GLM-5.1", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 202752, maxTokens: 32768 }, "glm-5.2": { id: "glm-5.2", name: "GLM-5.2", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: "high", xhigh: null, max: "max" } }, "glm-5.3": { id: "glm-5.3", name: "GLM-5.3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" } }, hy3: { id: "hy3", name: "Hy3 (8x usage)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.0175, output: 0.0725, cacheRead: 4375e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 256e3, maxTokens: 64e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: null } }, "kimi-k2.6": { id: "kimi-k2.6", name: "Kimi K2.6", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, thinkingFormat: "deepseek", supportsReasoningEffort: false, maxTokensField: "max_tokens", supportsLongCacheRetention: false }, contextWindow: 262144, maxTokens: 65536, thinkingLevelMap: { minimal: null, low: null, medium: null } }, "kimi-k2.7-code": { id: "kimi-k2.7-code", name: "Kimi K2.7 Code", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 262144, maxTokens: 262144 }, "kimi-k3": { id: "kimi-k3", name: "Kimi K3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: null, xhigh: null, max: "max" } }, "longcat-2.0": { id: "longcat-2.0", name: "LongCat-2.0", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 6e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072 }, "mimo-v2.5": { id: "mimo-v2.5", name: "MiMo V2.5", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 128e3 }, "mimo-v2.5-pro": { id: "mimo-v2.5-pro", name: "MiMo V2.5 Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 128e3 }, "minimax-m2.7": { id: "minimax-m2.7", name: "MiniMax-M2.7", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 204800, maxTokens: 131072 }, "ox-alpha-free": { id: "ox-alpha-free", name: "Ox Alpha Free (Unlimited)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" } }, "qwen3.6-plus": { id: "qwen3.6-plus", name: "Qwen3.6 Plus", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.625 }, compat: { supportsStore: false, supportsDeveloperRole: false, thinkingFormat: "qwen", maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.7-max": { id: "qwen3.7-max", name: "Qwen3.7 Max", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text"], cost: { input: 2.5, output: 7.5, cacheRead: 0.5, cacheWrite: 3.125 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.7-plus": { id: "qwen3.7-plus", name: "Qwen3.7 Plus", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.04, cacheWrite: 0.5 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536 }, "qwen3.8-max": { id: "qwen3.8-max", name: "Qwen3.8 Max", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, compat: { supportsStore: false, supportsDeveloperRole: false, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072 } }, "openai-responses": { "gpt-5.6-luna": { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" } }, "grok-4.5": { id: "grok-4.5", name: "Grok 4.5", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 5e5, maxTokens: 5e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null } }, "muse-spark-1.2-contributor": { id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/zen/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null } } } };
|
|
14293
14387
|
|
|
14294
14388
|
// ../ai/src/providers/opencode-go.models.ts
|
|
14295
14389
|
var OPENCODE_GO_MODELS = flattenModelCatalog("opencode-go", opencode_go_default);
|
|
14296
14390
|
|
|
14297
14391
|
// ../ai/src/providers/data/openrouter.json
|
|
14298
|
-
var openrouter_default = { "openai-completions": { "aion-labs/aion-2.0": { id: "aion-labs/aion-2.0", name: "AionLabs: Aion-2.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.8, output: 1.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "aion-labs/aion-3.0": { id: "aion-labs/aion-3.0", name: "AionLabs: Aion-3.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 3, output: 6, cacheRead: 0.75, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "aion-labs/aion-3.0-mini": { id: "aion-labs/aion-3.0-mini", name: "AionLabs: Aion-3.0-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.7, output: 1.4, cacheRead: 0.18, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-2-lite-v1": { id: "amazon/nova-2-lite-v1", name: "Amazon: Nova 2 Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-lite-v1": { id: "amazon/nova-lite-v1", name: "Amazon: Nova Lite 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.06, output: 0.24, cacheRead: 0, cacheWrite: 0 }, contextWindow: 3e5, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-micro-v1": { id: "amazon/nova-micro-v1", name: "Amazon: Nova Micro 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.035, output: 0.14, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-premier-v1": { id: "amazon/nova-premier-v1", name: "Amazon: Nova Premier 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.625, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-pro-v1": { id: "amazon/nova-pro-v1", name: "Amazon: Nova Pro 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.8, output: 3.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 3e5, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "anthropic/claude-3-haiku": { id: "anthropic/claude-3-haiku", name: "Anthropic: Claude 3 Haiku", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 }, contextWindow: 2e5, maxTokens: 4096, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-fable-5": { id: "anthropic/claude-fable-5", name: "Anthropic: Claude Fable 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { off: null, xhigh: "xhigh", max: "max" } }, "anthropic/claude-fable-5:batch": { id: "anthropic/claude-fable-5:batch", name: "Anthropic: Claude Fable 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { off: null, xhigh: "xhigh", max: "max" } }, "anthropic/claude-haiku-4.5": { id: "anthropic/claude-haiku-4.5", name: "Anthropic: Claude Haiku 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-haiku-4.5:batch": { id: "anthropic/claude-haiku-4.5:batch", name: "Anthropic: Claude Haiku 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 2.5, cacheRead: 0.05, cacheWrite: 0.625 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4": { id: "anthropic/claude-opus-4", name: "Anthropic: Claude Opus 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.1": { id: "anthropic/claude-opus-4.1", name: "Anthropic: Claude Opus 4.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.1:batch": { id: "anthropic/claude-opus-4.1:batch", name: "Anthropic: Claude Opus 4.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 37.5, cacheRead: 0.75, cacheWrite: 9.375 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.5": { id: "anthropic/claude-opus-4.5", name: "Anthropic: Claude Opus 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.5:batch": { id: "anthropic/claude-opus-4.5:batch", name: "Anthropic: Claude Opus 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.6": { id: "anthropic/claude-opus-4.6", name: "Anthropic: Claude Opus 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-opus-4.6:batch": { id: "anthropic/claude-opus-4.6:batch", name: "Anthropic: Claude Opus 4.6 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-opus-4.7": { id: "anthropic/claude-opus-4.7", name: "Anthropic: Claude Opus 4.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.7-fast": { id: "anthropic/claude-opus-4.7-fast", name: "Anthropic: Claude Opus 4.7 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 150, cacheRead: 3, cacheWrite: 37.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.7:batch": { id: "anthropic/claude-opus-4.7:batch", name: "Anthropic: Claude Opus 4.7 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8": { id: "anthropic/claude-opus-4.8", name: "Anthropic: Claude Opus 4.8", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8-fast": { id: "anthropic/claude-opus-4.8-fast", name: "Anthropic: Claude Opus 4.8 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8:batch": { id: "anthropic/claude-opus-4.8:batch", name: "Anthropic: Claude Opus 4.8 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5": { id: "anthropic/claude-opus-5", name: "Claude Opus 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5-fast": { id: "anthropic/claude-opus-5-fast", name: "Claude Opus 5 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5:batch": { id: "anthropic/claude-opus-5:batch", name: "Claude Opus 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-sonnet-4": { id: "anthropic/claude-sonnet-4", name: "Anthropic: Claude Sonnet 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.5": { id: "anthropic/claude-sonnet-4.5", name: "Anthropic: Claude Sonnet 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 1e6, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.5:batch": { id: "anthropic/claude-sonnet-4.5:batch", name: "Anthropic: Claude Sonnet 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 }, contextWindow: 1e6, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.6": { id: "anthropic/claude-sonnet-4.6", name: "Anthropic: Claude Sonnet 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-sonnet-4.6:batch": { id: "anthropic/claude-sonnet-4.6:batch", name: "Anthropic: Claude Sonnet 4.6 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-sonnet-5": { id: "anthropic/claude-sonnet-5", name: "Anthropic: Claude Sonnet 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-sonnet-5:batch": { id: "anthropic/claude-sonnet-5:batch", name: "Anthropic: Claude Sonnet 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "arcee-ai/trinity-large-thinking": { id: "arcee-ai/trinity-large-thinking", name: "Arcee AI: Trinity Large Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.22, output: 0.85, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "arcee-ai/virtuoso-large": { id: "arcee-ai/virtuoso-large", name: "Arcee AI: Virtuoso Large", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.75, output: 1.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, auto: { id: "auto", name: "Auto", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 3e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-1.6": { id: "bytedance-seed/seed-1.6", name: "ByteDance Seed: Seed 1.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-1.6-flash": { id: "bytedance-seed/seed-1.6-flash", name: "ByteDance Seed: Seed 1.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.075, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2-1-turbo": { id: "bytedance-seed/seed-2-1-turbo", name: "ByteDance Seed: Seed 2.1 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-code": { id: "bytedance-seed/seed-2.0-code", name: "ByteDance Seed: Seed-2.0-Code", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-lite": { id: "bytedance-seed/seed-2.0-lite", name: "ByteDance Seed: Seed-2.0-Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-mini": { id: "bytedance-seed/seed-2.0-mini", name: "ByteDance Seed: Seed-2.0-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/command-r-08-2024": { id: "cohere/command-r-08-2024", name: "Cohere: Command R (08-2024)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/command-r-plus-08-2024": { id: "cohere/command-r-plus-08-2024", name: "Cohere: Command R+ (08-2024)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/north-mini-code:free": { id: "cohere/north-mini-code:free", name: "Cohere: North Mini Code (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat": { id: "deepseek/deepseek-chat", name: "DeepSeek: DeepSeek V3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.2574, output: 1.0287, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat-v3-0324": { id: "deepseek/deepseek-chat-v3-0324", name: "DeepSeek: DeepSeek V3 0324", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.25, output: 1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 163840, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat-v3.1": { id: "deepseek/deepseek-chat-v3.1", name: "DeepSeek: DeepSeek V3.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 1.65, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 161e3, maxTokens: 161e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-r1": { id: "deepseek/deepseek-r1", name: "DeepSeek: R1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.7, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 64e3, maxTokens: 16e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-r1-0528": { id: "deepseek/deepseek-r1-0528", name: "DeepSeek: R1 0528", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.5, output: 2.15, cacheRead: 0.35, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.1-terminus": { id: "deepseek/deepseek-v3.1-terminus", name: "DeepSeek: DeepSeek V3.1 Terminus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 1, cacheRead: 0.135, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.2": { id: "deepseek/deepseek-v3.2", name: "DeepSeek: DeepSeek V3.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.26, output: 0.38, cacheRead: 0.13, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 163840, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.2-exp": { id: "deepseek/deepseek-v3.2-exp", name: "DeepSeek: DeepSeek V3.2 Exp", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 0.41, cacheRead: 0, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v4-flash": { id: "deepseek/deepseek-v4-flash", name: "DeepSeek: DeepSeek V4 Flash 0423", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.05446, output: 0.10892, cacheRead: 0.010892, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-flash-0731": { id: "deepseek/deepseek-v4-flash-0731", name: "DeepSeek: DeepSeek V4 Flash 0731", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.08, output: 0.18, cacheRead: 0.016, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-flash-vision-exp": { id: "deepseek/deepseek-v4-flash-vision-exp", name: "DeepSeek: DeepSeek V4 Flash Vision Exp", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-pro": { id: "deepseek/deepseek-v4-pro", name: "DeepSeek: DeepSeek V4 Pro 0423", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.413772, output: 0.827544, cacheRead: 0.034481, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-pro-0813": { id: "deepseek/deepseek-v4-pro-0813", name: "DeepSeek: DeepSeek V4 Pro 0813", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.122, output: 3.366, cacheRead: 0.0374, cacheWrite: 0 }, contextWindow: 1048575, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "dots-studio/dots-3-note-preview:free": { id: "dots-studio/dots-3-note-preview:free", name: "Dots Studio: Dots3-Note Preview (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 512e3, maxTokens: 512e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash": { id: "google/gemini-2.5-flash", name: "Google: Gemini 2.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash-lite": { id: "google/gemini-2.5-flash-lite", name: "Google: Gemini 2.5 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash-lite:batch": { id: "google/gemini-2.5-flash-lite:batch", name: "Google: Gemini 2.5 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.05, output: 0.2, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash:batch": { id: "google/gemini-2.5-flash:batch", name: "Google: Gemini 2.5 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 1.25, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro": { id: "google/gemini-2.5-pro", name: "Google: Gemini 2.5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro-preview": { id: "google/gemini-2.5-pro-preview", name: "Google: Gemini 2.5 Pro Preview 06-05", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro-preview-05-06": { id: "google/gemini-2.5-pro-preview-05-06", name: "Google: Gemini 2.5 Pro Preview 05-06", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro:batch": { id: "google/gemini-2.5-pro:batch", name: "Google: Gemini 2.5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-flash-preview": { id: "google/gemini-3-flash-preview", name: "Google: Gemini 3 Flash Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-flash-preview:batch": { id: "google/gemini-3-flash-preview:batch", name: "Google: Gemini 3 Flash Preview (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-pro-image": { id: "google/gemini-3-pro-image", name: "Google: Nano Banana Pro (Gemini 3 Pro Image)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 65536, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite": { id: "google/gemini-3.1-flash-lite", name: "Google: Gemini 3.1 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite-preview": { id: "google/gemini-3.1-flash-lite-preview", name: "Google: Gemini 3.1 Flash Lite Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite:batch": { id: "google/gemini-3.1-flash-lite:batch", name: "Google: Gemini 3.1 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.125, output: 0.75, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview": { id: "google/gemini-3.1-pro-preview", name: "Google: Gemini 3.1 Pro Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview-customtools": { id: "google/gemini-3.1-pro-preview-customtools", name: "Google: Gemini 3.1 Pro Preview Custom Tools", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview:batch": { id: "google/gemini-3.1-pro-preview:batch", name: "Google: Gemini 3.1 Pro Preview (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash": { id: "google/gemini-3.5-flash", name: "Google: Gemini 3.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash-lite": { id: "google/gemini-3.5-flash-lite", name: "Google: Gemini 3.5 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash-lite:batch": { id: "google/gemini-3.5-flash-lite:batch", name: "Google: Gemini 3.5 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 1.25, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash:batch": { id: "google/gemini-3.5-flash:batch", name: "Google: Gemini 3.5 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.6-flash": { id: "google/gemini-3.6-flash", name: "Google: Gemini 3.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.6-flash:batch": { id: "google/gemini-3.6-flash:batch", name: "Google: Gemini 3.6 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.041667 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.7-flash": { id: "google/gemini-3.7-flash", name: "Google: Gemini 3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.7-flash:batch": { id: "google/gemini-3.7-flash:batch", name: "Google: Gemini 3.7 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1875, output: 0.9375, cacheRead: 0.01875, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-3-12b-it": { id: "google/gemma-3-12b-it", name: "Google: Gemma 3 12B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.05, output: 0.15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-3-27b-it": { id: "google/gemma-3-27b-it", name: "Google: Gemma 3 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.08, output: 0.45, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-26b-a4b-it": { id: "google/gemma-4-26b-a4b-it", name: "Google: Gemma 4 26B A4B ", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.07, output: 0.34, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-26b-a4b-it:free": { id: "google/gemma-4-26b-a4b-it:free", name: "Google: Gemma 4 26B A4B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-31b-it": { id: "google/gemma-4-31b-it", name: "Google: Gemma 4 31B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.34, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-31b-it:free": { id: "google/gemma-4-31b-it:free", name: "Google: Gemma 4 31B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "ibm-granite/granite-4.1-8b": { id: "ibm-granite/granite-4.1-8b", name: "IBM: Granite 4.1 8B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.05, output: 0.1, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "inception/mercury-2": { id: "inception/mercury-2", name: "Inception: Mercury 2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.25, output: 0.75, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 5e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" }, thinkingLevelMap: { off: null } }, "inclusionai/ling-2.6-1t": { id: "inclusionai/ling-2.6-1t", name: "inclusionAI: Ling-2.6-1T", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.075, output: 0.625, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "inclusionai/ling-2.6-flash": { id: "inclusionai/ling-2.6-flash", name: "inclusionAI: Ling-2.6-flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.01, output: 0.03, cacheRead: 2e-3, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "inclusionai/ling-3.0-flash": { id: "inclusionai/ling-3.0-flash", name: "Ling-3.0-flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.021, output: 0.063, cacheRead: 42e-4, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "inclusionai/ring-2.6-1t": { id: "inclusionai/ring-2.6-1t", name: "inclusionAI: Ring-2.6-1T", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.075, output: 0.625, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-air-v2.5": { id: "kwaipilot/kat-coder-air-v2.5", name: "Kwaipilot: KAT-Coder-Air V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-pro-v2": { id: "kwaipilot/kat-coder-pro-v2", name: "Kwaipilot: KAT-Coder-Pro V2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-pro-v2.5": { id: "kwaipilot/kat-coder-pro-v2.5", name: "Kwaipilot: KAT-Coder-Pro V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.74, output: 2.96, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "liquid/lfm-2.5-2.6b:free": { id: "liquid/lfm-2.5-2.6b:free", name: "LiquidAI: LFM2.5-2.6B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meituan/longcat-2.0": { id: "meituan/longcat-2.0", name: "Meituan: LongCat 2.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 6e-3, cacheWrite: 0 }, contextWindow: 1048756, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.1-70b-instruct": { id: "meta-llama/llama-3.1-70b-instruct", name: "Meta: Llama 3.1 70B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.1-8b-instruct": { id: "meta-llama/llama-3.1-8b-instruct", name: "Meta: Llama 3.1 8B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.05, output: 0.08, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.3-70b-instruct": { id: "meta-llama/llama-3.3-70b-instruct", name: "Meta: Llama 3.3 70B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.32, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-4-maverick": { id: "meta-llama/llama-4-maverick", name: "Meta: Llama 4 Maverick", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.8, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-4-scout": { id: "meta-llama/llama-4-scout", name: "Meta: Llama 4 Scout", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 327680, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-glimmer-30b": { id: "meta/muse-glimmer-30b", name: "Meta: Muse Glimmer 30B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.35, output: 1.5, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.1": { id: "meta/muse-spark-1.1", name: "Meta: Muse Spark 1.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.2": { id: "meta/muse-spark-1.2", name: "Meta: Muse Spark 1.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.2-contributor": { id: "meta/muse-spark-1.2-contributor", name: "Meta: Muse Spark 1.2 Contributor", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m1": { id: "minimax/minimax-m1", name: "MiniMax: MiniMax M1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 4e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2": { id: "minimax/minimax-m2", name: "MiniMax: MiniMax M2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.255, output: 1.02, cacheRead: 0, cacheWrite: 0 }, contextWindow: 204800, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.1": { id: "minimax/minimax-m2.1", name: "MiniMax: MiniMax M2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 204800, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.5": { id: "minimax/minimax-m2.5", name: "MiniMax: MiniMax M2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 1.08, cacheRead: 0.027, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.7": { id: "minimax/minimax-m2.7", name: "MiniMax: MiniMax M2.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 204800, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m3": { id: "minimax/minimax-m3", name: "MiniMax: MiniMax M3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 512e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m3:batch": { id: "minimax/minimax-m3:batch", name: "MiniMax: MiniMax M3 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/codestral-2508": { id: "mistralai/codestral-2508", name: "Mistral: Codestral 2508", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 0.9, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-14b-2512": { id: "mistralai/ministral-14b-2512", name: "Mistral: Ministral 3 14B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.2, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-3b-2512": { id: "mistralai/ministral-3b-2512", name: "Mistral: Ministral 3 3B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.1, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-8b-2512": { id: "mistralai/ministral-8b-2512", name: "Mistral: Ministral 3 8B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.15, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large": { id: "mistralai/mistral-large", name: "Mistral Large", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large-2407": { id: "mistralai/mistral-large-2407", name: "Mistral Large 2407", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large-2512": { id: "mistralai/mistral-large-2512", name: "Mistral: Mistral Large 3 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.5, output: 1.5, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3": { id: "mistralai/mistral-medium-3", name: "Mistral: Mistral Medium 3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3-5": { id: "mistralai/mistral-medium-3-5", name: "Mistral: Mistral Medium 3.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3.1": { id: "mistralai/mistral-medium-3.1", name: "Mistral: Mistral Medium 3.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-nemo": { id: "mistralai/mistral-nemo", name: "Mistral: Mistral Nemo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.019, output: 0.03, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-saba": { id: "mistralai/mistral-saba", name: "Mistral: Saba", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.2, output: 0.6, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-small-2603": { id: "mistralai/mistral-small-2603", name: "Mistral: Mistral Small 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-small-3.2-24b-instruct": { id: "mistralai/mistral-small-3.2-24b-instruct", name: "Mistral: Mistral Small 3.2 24B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.075, output: 0.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mixtral-8x22b-instruct": { id: "mistralai/mixtral-8x22b-instruct", name: "Mistral: Mixtral 8x22B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/voxtral-small-24b-2507": { id: "mistralai/voxtral-small-24b-2507", name: "Mistral: Voxtral Small 24B 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.3, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 32e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2": { id: "moonshotai/kimi-k2", name: "MoonshotAI: Kimi K2 0711", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.57, output: 2.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2-0905": { id: "moonshotai/kimi-k2-0905", name: "MoonshotAI: Kimi K2 0905", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.6, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2-thinking": { id: "moonshotai/kimi-k2-thinking", name: "MoonshotAI: Kimi K2 Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 2.5, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.5": { id: "moonshotai/kimi-k2.5", name: "MoonshotAI: Kimi K2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.41, output: 2.06, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.6": { id: "moonshotai/kimi-k2.6", name: "MoonshotAI: Kimi K2.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true } }, "moonshotai/kimi-k2.7-code": { id: "moonshotai/kimi-k2.7-code", name: "MoonshotAI: Kimi K2.7 Code", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.67, output: 3.4, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.7-code:batch": { id: "moonshotai/kimi-k2.7-code:batch", name: "MoonshotAI: Kimi K2.7 Code (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k3": { id: "moonshotai/kimi-k3", name: "MoonshotAI: Kimi K3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nex-agi/nex-n2-mini": { id: "nex-agi/nex-n2-mini", name: "Nex AGI: Nex-N2-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.025, output: 0.1, cacheRead: 25e-4, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nex-agi/nex-n2-pro": { id: "nex-agi/nex-n2-pro", name: "Nex AGI: Nex-N2-Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-30b-a3b": { id: "nvidia/nemotron-3-nano-30b-a3b", name: "NVIDIA: Nemotron 3 Nano 30B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.05, output: 0.2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-30b-a3b:free": { id: "nvidia/nemotron-3-nano-30b-a3b:free", name: "NVIDIA: Nemotron 3 Nano 30B A3B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free": { id: "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free", name: "NVIDIA: Nemotron 3 Nano Omni (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-super-120b-a12b": { id: "nvidia/nemotron-3-super-120b-a12b", name: "NVIDIA: Nemotron 3 Super", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.085, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-super-120b-a12b:free": { id: "nvidia/nemotron-3-super-120b-a12b:free", name: "NVIDIA: Nemotron 3 Super (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b": { id: "nvidia/nemotron-3-ultra-550b-a55b", name: "NVIDIA: Nemotron 3 Ultra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 3.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 512288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b:batch": { id: "nvidia/nemotron-3-ultra-550b-a55b:batch", name: "NVIDIA: Nemotron 3 Ultra (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 3.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 512288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b:free": { id: "nvidia/nemotron-3-ultra-550b-a55b:free", name: "NVIDIA: Nemotron 3 Ultra (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3.5-lightning": { id: "nvidia/nemotron-3.5-lightning", name: "NVIDIA: Nemotron 3.5 Lightning", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.08, output: 0.2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3.5-lightning:free": { id: "nvidia/nemotron-3.5-lightning:free", name: "NVIDIA: Nemotron 3.5 Lightning (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-nano-12b-v2-vl:free": { id: "nvidia/nemotron-nano-12b-v2-vl:free", name: "NVIDIA: Nemotron Nano 12B 2 VL (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-nano-9b-v2:free": { id: "nvidia/nemotron-nano-9b-v2:free", name: "NVIDIA: Nemotron Nano 9B V2 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo": { id: "openai/gpt-3.5-turbo", name: "OpenAI: GPT-3.5 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.5, output: 1.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo-0613": { id: "openai/gpt-3.5-turbo-0613", name: "OpenAI: GPT-3.5 Turbo (older v0613)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4095, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo-16k": { id: "openai/gpt-3.5-turbo-16k", name: "OpenAI: GPT-3.5 Turbo 16k", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 3, output: 4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo:batch": { id: "openai/gpt-3.5-turbo:batch", name: "OpenAI: GPT-3.5 Turbo (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.25, output: 0.75, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4": { id: "openai/gpt-4", name: "OpenAI: GPT-4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 30, output: 60, cacheRead: 0, cacheWrite: 0 }, contextWindow: 8191, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo": { id: "openai/gpt-4-turbo", name: "OpenAI: GPT-4 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo-preview": { id: "openai/gpt-4-turbo-preview", name: "OpenAI: GPT-4 Turbo Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo:batch": { id: "openai/gpt-4-turbo:batch", name: "OpenAI: GPT-4 Turbo (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1": { id: "openai/gpt-4.1", name: "OpenAI: GPT-4.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-mini": { id: "openai/gpt-4.1-mini", name: "OpenAI: GPT-4.1 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-mini:batch": { id: "openai/gpt-4.1-mini:batch", name: "OpenAI: GPT-4.1 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.8, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-nano": { id: "openai/gpt-4.1-nano", name: "OpenAI: GPT-4.1 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-nano:batch": { id: "openai/gpt-4.1-nano:batch", name: "OpenAI: GPT-4.1 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.05, output: 0.2, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1:batch": { id: "openai/gpt-4.1:batch", name: "OpenAI: GPT-4.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o": { id: "openai/gpt-4o", name: "OpenAI: GPT-4o", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-05-13": { id: "openai/gpt-4o-2024-05-13", name: "OpenAI: GPT-4o (2024-05-13)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-08-06": { id: "openai/gpt-4o-2024-08-06", name: "OpenAI: GPT-4o (2024-08-06)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-11-20": { id: "openai/gpt-4o-2024-11-20", name: "OpenAI: GPT-4o (2024-11-20)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini": { id: "openai/gpt-4o-mini", name: "OpenAI: GPT-4o-mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini-2024-07-18": { id: "openai/gpt-4o-mini-2024-07-18", name: "OpenAI: GPT-4o-mini (2024-07-18)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini:batch": { id: "openai/gpt-4o-mini:batch", name: "OpenAI: GPT-4o-mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o:batch": { id: "openai/gpt-4o:batch", name: "OpenAI: GPT-4o (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1.25, output: 5, cacheRead: 0.625, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5": { id: "openai/gpt-5", name: "OpenAI: GPT-5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-codex:batch": { id: "openai/gpt-5-codex:batch", name: "OpenAI: GPT-5 Codex (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-mini": { id: "openai/gpt-5-mini", name: "OpenAI: GPT-5 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-mini:batch": { id: "openai/gpt-5-mini:batch", name: "OpenAI: GPT-5 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.125, output: 1, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-nano": { id: "openai/gpt-5-nano", name: "OpenAI: GPT-5 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.05, output: 0.4, cacheRead: 5e-3, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-nano:batch": { id: "openai/gpt-5-nano:batch", name: "OpenAI: GPT-5 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.025, output: 0.2, cacheRead: 25e-4, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-pro": { id: "openai/gpt-5-pro", name: "OpenAI: GPT-5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 120, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-pro:batch": { id: "openai/gpt-5-pro:batch", name: "OpenAI: GPT-5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 60, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1": { id: "openai/gpt-5.1", name: "OpenAI: GPT-5.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex": { id: "openai/gpt-5.1-codex", name: "OpenAI: GPT-5.1-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.13, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex-max": { id: "openai/gpt-5.1-codex-max", name: "OpenAI: GPT-5.1-Codex-Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex-mini": { id: "openai/gpt-5.1-codex-mini", name: "OpenAI: GPT-5.1-Codex-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1:batch": { id: "openai/gpt-5.1:batch", name: "OpenAI: GPT-5.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.2": { id: "openai/gpt-5.2", name: "OpenAI: GPT-5.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-chat": { id: "openai/gpt-5.2-chat", name: "OpenAI: GPT-5.2 Chat", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 32e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-codex": { id: "openai/gpt-5.2-codex", name: "OpenAI: GPT-5.2-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-pro": { id: "openai/gpt-5.2-pro", name: "OpenAI: GPT-5.2 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 21, output: 168, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-pro:batch": { id: "openai/gpt-5.2-pro:batch", name: "OpenAI: GPT-5.2 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10.5, output: 84, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2:batch": { id: "openai/gpt-5.2:batch", name: "OpenAI: GPT-5.2 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.875, output: 7, cacheRead: 0.0875, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.3-codex": { id: "openai/gpt-5.3-codex", name: "OpenAI: GPT-5.3-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4": { id: "openai/gpt-5.4", name: "OpenAI: GPT-5.4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-mini": { id: "openai/gpt-5.4-mini", name: "OpenAI: GPT-5.4 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-mini:batch": { id: "openai/gpt-5.4-mini:batch", name: "OpenAI: GPT-5.4 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 2.25, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-nano": { id: "openai/gpt-5.4-nano", name: "OpenAI: GPT-5.4 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.25, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-nano:batch": { id: "openai/gpt-5.4-nano:batch", name: "OpenAI: GPT-5.4 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.625, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-pro": { id: "openai/gpt-5.4-pro", name: "OpenAI: GPT-5.4 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-pro:batch": { id: "openai/gpt-5.4-pro:batch", name: "OpenAI: GPT-5.4 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4:batch": { id: "openai/gpt-5.4:batch", name: "OpenAI: GPT-5.4 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 7.5, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5": { id: "openai/gpt-5.5", name: "OpenAI: GPT-5.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5-pro": { id: "openai/gpt-5.5-pro", name: "OpenAI: GPT-5.5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", off: null, minimal: null, low: null } }, "openai/gpt-5.5-pro:batch": { id: "openai/gpt-5.5-pro:batch", name: "OpenAI: GPT-5.5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5:batch": { id: "openai/gpt-5.5:batch", name: "OpenAI: GPT-5.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.6-luna": { id: "openai/gpt-5.6-luna", name: "OpenAI: GPT-5.6 Luna", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna-pro": { id: "openai/gpt-5.6-luna-pro", name: "OpenAI: GPT-5.6 Luna Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna-pro:batch": { id: "openai/gpt-5.6-luna-pro:batch", name: "OpenAI: GPT-5.6 Luna Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna:batch": { id: "openai/gpt-5.6-luna:batch", name: "OpenAI: GPT-5.6 Luna (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol": { id: "openai/gpt-5.6-sol", name: "OpenAI: GPT-5.6 Sol", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol-pro": { id: "openai/gpt-5.6-sol-pro", name: "OpenAI: GPT-5.6 Sol Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol-pro:batch": { id: "openai/gpt-5.6-sol-pro:batch", name: "OpenAI: GPT-5.6 Sol Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol:batch": { id: "openai/gpt-5.6-sol:batch", name: "OpenAI: GPT-5.6 Sol (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra": { id: "openai/gpt-5.6-terra", name: "OpenAI: GPT-5.6 Terra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra-pro": { id: "openai/gpt-5.6-terra-pro", name: "OpenAI: GPT-5.6 Terra Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra-pro:batch": { id: "openai/gpt-5.6-terra-pro:batch", name: "OpenAI: GPT-5.6 Terra Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra:batch": { id: "openai/gpt-5.6-terra:batch", name: "OpenAI: GPT-5.6 Terra (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5:batch": { id: "openai/gpt-5:batch", name: "OpenAI: GPT-5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-audio": { id: "openai/gpt-audio", name: "OpenAI: GPT Audio", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-audio-mini": { id: "openai/gpt-audio-mini", name: "OpenAI: GPT Audio Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.6, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-chat-latest": { id: "openai/gpt-chat-latest", name: "OpenAI: GPT Chat Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-120b": { id: "openai/gpt-oss-120b", name: "OpenAI: gpt-oss-120b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.037, output: 0.17, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-20b": { id: "openai/gpt-oss-20b", name: "OpenAI: gpt-oss-20b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.03, output: 0.13, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-safeguard-20b": { id: "openai/gpt-oss-safeguard-20b", name: "OpenAI: gpt-oss-safeguard-20b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536, compat: { thinkingFormat: "openrouter" } }, "openai/o1": { id: "openai/o1", name: "OpenAI: o1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 60, cacheRead: 7.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o1:batch": { id: "openai/o1:batch", name: "OpenAI: o1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 30, cacheRead: 3.75, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3": { id: "openai/o3", name: "OpenAI: o3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini": { id: "openai/o3-mini", name: "OpenAI: o3 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini-high": { id: "openai/o3-mini-high", name: "OpenAI: o3 Mini High", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini-high:batch": { id: "openai/o3-mini-high:batch", name: "OpenAI: o3 Mini High (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini:batch": { id: "openai/o3-mini:batch", name: "OpenAI: o3 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-pro": { id: "openai/o3-pro", name: "OpenAI: o3 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 20, output: 80, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-pro:batch": { id: "openai/o3-pro:batch", name: "OpenAI: o3 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 40, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3:batch": { id: "openai/o3:batch", name: "OpenAI: o3 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini": { id: "openai/o4-mini", name: "OpenAI: o4 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini-high": { id: "openai/o4-mini-high", name: "OpenAI: o4 Mini High", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini-high:batch": { id: "openai/o4-mini-high:batch", name: "OpenAI: o4 Mini High (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.55, output: 2.2, cacheRead: 0.1375, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini:batch": { id: "openai/o4-mini:batch", name: "OpenAI: o4 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.55, output: 2.2, cacheRead: 0.1375, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openrouter/auto": { id: "openrouter/auto", name: "Auto Router", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: -1e6, output: -1e6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/auto-beta": { id: "openrouter/auto-beta", name: "Auto Router (Beta)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: -1e6, output: -1e6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/free": { id: "openrouter/free", name: "Free Models Router", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/fusion": { id: "openrouter/fusion", name: "OpenRouter: Fusion", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 3e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-s-2.1": { id: "poolside/laguna-s-2.1", name: "Poolside: Laguna S 2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.09, output: 0.18, cacheRead: 9e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-s-2.1:free": { id: "poolside/laguna-s-2.1:free", name: "Poolside: Laguna S 2.1 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-xs-2.1": { id: "poolside/laguna-xs-2.1", name: "Poolside: Laguna XS 2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.06, output: 0.12, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-xs-2.1:free": { id: "poolside/laguna-xs-2.1:free", name: "Poolside: Laguna XS 2.1 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-2.5-72b-instruct": { id: "qwen/qwen-2.5-72b-instruct", name: "Qwen2.5 72B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.36, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-2.5-7b-instruct": { id: "qwen/qwen-2.5-7b-instruct", name: "Qwen: Qwen2.5 7B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus": { id: "qwen/qwen-plus", name: "Qwen: Qwen-Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0.052, cacheWrite: 0.325 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus-2025-07-28": { id: "qwen/qwen-plus-2025-07-28", name: "Qwen: Qwen Plus 0728", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus-2025-07-28:thinking": { id: "qwen/qwen-plus-2025-07-28:thinking", name: "Qwen: Qwen Plus 0728 (thinking)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-14b": { id: "qwen/qwen3-14b", name: "Qwen: Qwen3 14B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.12, output: 0.24, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b": { id: "qwen/qwen3-235b-a22b", name: "Qwen: Qwen3 235B A22B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.455, output: 1.82, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b-2507": { id: "qwen/qwen3-235b-a22b-2507", name: "Qwen: Qwen3 235B A22B Instruct 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.09, output: 0.55, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b-thinking-2507": { id: "qwen/qwen3-235b-a22b-thinking-2507", name: "Qwen: Qwen3 235B A22B Thinking 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.23, output: 2.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b": { id: "qwen/qwen3-30b-a3b", name: "Qwen: Qwen3 30B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.12, output: 0.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b-instruct-2507": { id: "qwen/qwen3-30b-a3b-instruct-2507", name: "Qwen: Qwen3 30B A3B Instruct 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.04815, output: 0.19305, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 32e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b-thinking-2507": { id: "qwen/qwen3-30b-a3b-thinking-2507", name: "Qwen: Qwen3 30B A3B Thinking 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 81920, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-32b": { id: "qwen/qwen3-32b", name: "Qwen: Qwen3 32B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.08, output: 0.28, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-8b": { id: "qwen/qwen3-8b", name: "Qwen: Qwen3 8B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder": { id: "qwen/qwen3-coder", name: "Qwen: Qwen3 Coder 480B A35B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 1, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-30b-a3b-instruct": { id: "qwen/qwen3-coder-30b-a3b-instruct", name: "Qwen: Qwen3 Coder 30B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.07, output: 0.28, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-flash": { id: "qwen/qwen3-coder-flash", name: "Qwen: Qwen3 Coder Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.195, output: 0.975, cacheRead: 0.039, cacheWrite: 0.24375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-next": { id: "qwen/qwen3-coder-next", name: "Qwen: Qwen3 Coder Next", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.12, output: 0.8, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-plus": { id: "qwen/qwen3-coder-plus", name: "Qwen: Qwen3 Coder Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.65, output: 3.25, cacheRead: 0.13, cacheWrite: 0.8125 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-max": { id: "qwen/qwen3-max", name: "Qwen: Qwen3 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.78, output: 3.9, cacheRead: 0.156, cacheWrite: 0.975 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-max-thinking": { id: "qwen/qwen3-max-thinking", name: "Qwen: Qwen3 Max Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.78, output: 3.9, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-next-80b-a3b-instruct": { id: "qwen/qwen3-next-80b-a3b-instruct", name: "Qwen: Qwen3 Next 80B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 1.1, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-next-80b-a3b-thinking": { id: "qwen/qwen3-next-80b-a3b-thinking", name: "Qwen: Qwen3 Next 80B A3B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.15, output: 1.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-235b-a22b-instruct": { id: "qwen/qwen3-vl-235b-a22b-instruct", name: "Qwen: Qwen3 VL 235B A22B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.21, output: 1.9, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-235b-a22b-thinking": { id: "qwen/qwen3-vl-235b-a22b-thinking", name: "Qwen: Qwen3 VL 235B A22B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-30b-a3b-instruct": { id: "qwen/qwen3-vl-30b-a3b-instruct", name: "Qwen: Qwen3 VL 30B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.13, output: 0.52, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-30b-a3b-thinking": { id: "qwen/qwen3-vl-30b-a3b-thinking", name: "Qwen: Qwen3 VL 30B A3B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-32b-instruct": { id: "qwen/qwen3-vl-32b-instruct", name: "Qwen: Qwen3 VL 32B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.104, output: 0.416, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-8b-instruct": { id: "qwen/qwen3-vl-8b-instruct", name: "Qwen: Qwen3 VL 8B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-8b-thinking": { id: "qwen/qwen3-vl-8b-thinking", name: "Qwen: Qwen3 VL 8B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.18, output: 2.1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-122b-a10b": { id: "qwen/qwen3.5-122b-a10b", name: "Qwen: Qwen3.5-122B-A10B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.26, output: 2.08, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-27b": { id: "qwen/qwen3.5-27b", name: "Qwen: Qwen3.5-27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.195, output: 1.56, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-35b-a3b": { id: "qwen/qwen3.5-35b-a3b", name: "Qwen: Qwen3.5-35B-A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.25, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-397b-a17b": { id: "qwen/qwen3.5-397b-a17b", name: "Qwen: Qwen3.5 397B A17B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.39, output: 2.34, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-9b": { id: "qwen/qwen3.5-9b", name: "Qwen: Qwen3.5-9B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-flash-02-23": { id: "qwen/qwen3.5-flash-02-23", name: "Qwen: Qwen3.5-Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.065, output: 0.26, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-plus-02-15": { id: "qwen/qwen3.5-plus-02-15", name: "Qwen: Qwen3.5 Plus 2026-02-15", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.26, output: 1.56, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-plus-20260420": { id: "qwen/qwen3.5-plus-20260420", name: "Qwen: Qwen3.5 Plus 2026-04-20", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.8, cacheRead: 0, cacheWrite: 0.375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-27b": { id: "qwen/qwen3.6-27b", name: "Qwen: Qwen3.6 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.6, output: 3.6, cacheRead: 0.12, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-35b-a3b": { id: "qwen/qwen3.6-35b-a3b", name: "Qwen: Qwen3.6 35B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 1, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-flash": { id: "qwen/qwen3.6-flash", name: "Qwen: Qwen3.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1875, output: 1.125, cacheRead: 0, cacheWrite: 0.234375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-max-preview": { id: "qwen/qwen3.6-max-preview", name: "Qwen: Qwen3.6 Max Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.027, output: 6.162, cacheRead: 0, cacheWrite: 1.28375 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-plus": { id: "qwen/qwen3.6-plus", name: "Qwen: Qwen3.6 Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.325, output: 1.95, cacheRead: 0, cacheWrite: 0.40625 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-flash": { id: "qwen/qwen3.7-flash", name: "Qwen: Qwen3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.03, output: 0.13, cacheRead: 6e-3, cacheWrite: 0.038 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-max": { id: "qwen/qwen3.7-max", name: "Qwen: Qwen3.7 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.475, output: 4.425, cacheRead: 0.295, cacheWrite: 1.84375 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-plus": { id: "qwen/qwen3.7-plus", name: "Qwen: Qwen3.7 Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.32, output: 1.28, cacheRead: 0.064, cacheWrite: 0.4 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-2.4t-a95b": { id: "qwen/qwen3.8-2.4t-a95b", name: "Qwen: Qwen3.8 2.4T A95B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-27b": { id: "qwen/qwen3.8-27b", name: "Qwen: Qwen3.8 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 3, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-max": { id: "qwen/qwen3.8-max", name: "Qwen: Qwen3.8 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "rekaai/reka-edge": { id: "rekaai/reka-edge", name: "Reka Edge", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16384, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "relace/relace-search": { id: "relace/relace-search", name: "Relace: Relace Search", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 1, output: 3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sakana/fugu-ultra": { id: "sakana/fugu-ultra", name: "Sakana: Fugu Ultra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sakana/sakana-namazu": { id: "sakana/sakana-namazu", name: "Sakana: Sakana Namazu", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sao10k/l3.1-euryale-70b": { id: "sao10k/l3.1-euryale-70b", name: "Sao10K: Llama 3.1 Euryale 70B v2.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.85, output: 0.85, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stealth/ox-alpha": { id: "stealth/ox-alpha", name: "Ox Alpha", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stepfun/step-3.5-flash": { id: "stepfun/step-3.5-flash", name: "StepFun: Step 3.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stepfun/step-3.7-flash": { id: "stepfun/step-3.7-flash", name: "StepFun: Step 3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 256e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "tencent/hy3": { id: "tencent/hy3", name: "Tencent: Hy3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.132, output: 0.528, cacheRead: 0.033, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "tencent/hy3-preview": { id: "tencent/hy3-preview", name: "Tencent: Hy3 preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.18, output: 0.6, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thedrummer/unslopnemo-12b": { id: "thedrummer/unslopnemo-12b", name: "TheDrummer: UnslopNemo 12B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 1024e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling": { id: "thinkingmachines/inkling", name: "Thinking Machines: Inkling", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling-small": { id: "thinkingmachines/inkling-small", name: "Thinking Machines: Inkling Small", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.45, output: 1.2, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling-small:free": { id: "thinkingmachines/inkling-small:free", name: "Thinking Machines: Inkling Small (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling:batch": { id: "thinkingmachines/inkling:batch", name: "Thinking Machines: Inkling (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling:free": { id: "thinkingmachines/inkling:free", name: "Thinking Machines: Inkling (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "upstage/solar-pro-3": { id: "upstage/solar-pro-3", name: "Upstage: Solar Pro 3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "upstage/solar-pro4": { id: "upstage/solar-pro4", name: "Upstage: Solar Pro 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.03, output: 0.12, cacheRead: 6e-3, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.20": { id: "x-ai/grok-4.20", name: "SpaceXAI: Grok 4.20", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.3": { id: "x-ai/grok-4.3", name: "SpaceXAI: Grok 4.3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.5": { id: "x-ai/grok-4.5", name: "SpaceXAI: Grok 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.3, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.6": { id: "x-ai/grok-4.6", name: "SpaceXAI: Grok 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-build-0.1": { id: "x-ai/grok-build-0.1", name: "SpaceXAI: Grok Build 0.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 2, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "xiaomi/mimo-v2.5": { id: "xiaomi/mimo-v2.5", name: "Xiaomi: MiMo-V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "xiaomi/mimo-v2.5-pro": { id: "xiaomi/mimo-v2.5-pro", name: "Xiaomi: MiMo-V2.5-Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 36e-4, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5": { id: "z-ai/glm-4.5", name: "Z.ai: GLM 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 2.2, cacheRead: 0.11, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 98304, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5-air": { id: "z-ai/glm-4.5-air", name: "Z.ai: GLM 4.5 Air", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.13, output: 0.85, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 98304, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5v": { id: "z-ai/glm-4.5v", name: "Z.ai: GLM 4.5V", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.6, output: 1.8, cacheRead: 0.11, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.6": { id: "z-ai/glm-4.6", name: "Z.ai: GLM 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.5, output: 2, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.6v": { id: "z-ai/glm-4.6v", name: "Z.ai: GLM 4.6V", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 0.9, cacheRead: 0.055, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.7": { id: "z-ai/glm-4.7", name: "Z.ai: GLM 4.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.4, output: 1.75, cacheRead: 0.08, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.7-flash": { id: "z-ai/glm-4.7-flash", name: "Z.ai: GLM 4.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.06, output: 0.4, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5": { id: "z-ai/glm-5", name: "Z.ai: GLM 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 1.9, cacheRead: 0.119, cacheWrite: 0 }, contextWindow: 198e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5-turbo": { id: "z-ai/glm-5-turbo", name: "Z.ai: GLM 5 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.1": { id: "z-ai/glm-5.1", name: "Z.ai: GLM 5.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.966, output: 3.036, cacheRead: 0.1794, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.2": { id: "z-ai/glm-5.2", name: "Z.ai: GLM 5.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.966, output: 3.036, cacheRead: 0.1932, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "z-ai/glm-5.2:batch": { id: "z-ai/glm-5.2:batch", name: "Z.ai: GLM 5.2 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048575, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.2:free": { id: "z-ai/glm-5.2:free", name: "Z.ai: GLM 5.2 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 256e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.3": { id: "z-ai/glm-5.3", name: "Z.ai: GLM 5.3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5v-turbo": { id: "z-ai/glm-5v-turbo", name: "Z.ai: GLM 5V Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~anthropic/claude-fable-latest": { id: "~anthropic/claude-fable-latest", name: "Anthropic: Claude Fable Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-haiku-latest": { id: "~anthropic/claude-haiku-latest", name: "Anthropic Claude Haiku Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-opus-latest": { id: "~anthropic/claude-opus-latest", name: "Anthropic: Claude Opus Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-sonnet-latest": { id: "~anthropic/claude-sonnet-latest", name: "Anthropic Claude Sonnet Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~deepseek/deepseek-v4-flash-latest": { id: "~deepseek/deepseek-v4-flash-latest", name: "DeepSeek V4 Flash Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.06, output: 0.18, cacheRead: 0.028, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "~google/gemini-flash-latest": { id: "~google/gemini-flash-latest", name: "Google Gemini Flash Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~google/gemini-pro-latest": { id: "~google/gemini-pro-latest", name: "Google Gemini Pro Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~moonshotai/kimi-latest": { id: "~moonshotai/kimi-latest", name: "MoonshotAI Kimi Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.6, output: 13, cacheRead: 0.29, cacheWrite: 0 }, contextWindow: 974842, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~openai/gpt-latest": { id: "~openai/gpt-latest", name: "OpenAI GPT Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~openai/gpt-mini-latest": { id: "~openai/gpt-mini-latest", name: "OpenAI GPT Mini Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~x-ai/grok-latest": { id: "~x-ai/grok-latest", name: "xAI: Grok Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~z-ai/glm-latest": { id: "~z-ai/glm-latest", name: "Z.ai: GLM Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } } } };
|
|
14392
|
+
var openrouter_default = { "openai-completions": { "aion-labs/aion-2.0": { id: "aion-labs/aion-2.0", name: "AionLabs: Aion-2.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.8, output: 1.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "aion-labs/aion-3.0": { id: "aion-labs/aion-3.0", name: "AionLabs: Aion-3.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 3, output: 6, cacheRead: 0.75, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "aion-labs/aion-3.0-mini": { id: "aion-labs/aion-3.0-mini", name: "AionLabs: Aion-3.0-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.7, output: 1.4, cacheRead: 0.18, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-2-lite-v1": { id: "amazon/nova-2-lite-v1", name: "Amazon: Nova 2 Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-lite-v1": { id: "amazon/nova-lite-v1", name: "Amazon: Nova Lite 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.06, output: 0.24, cacheRead: 0, cacheWrite: 0 }, contextWindow: 3e5, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-micro-v1": { id: "amazon/nova-micro-v1", name: "Amazon: Nova Micro 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.035, output: 0.14, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-premier-v1": { id: "amazon/nova-premier-v1", name: "Amazon: Nova Premier 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.625, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "amazon/nova-pro-v1": { id: "amazon/nova-pro-v1", name: "Amazon: Nova Pro 1.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.8, output: 3.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 3e5, maxTokens: 5120, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "anthropic/claude-3-haiku": { id: "anthropic/claude-3-haiku", name: "Anthropic: Claude 3 Haiku", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 }, contextWindow: 2e5, maxTokens: 4096, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-fable-5": { id: "anthropic/claude-fable-5", name: "Anthropic: Claude Fable 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { off: null, xhigh: "xhigh", max: "max" } }, "anthropic/claude-fable-5:batch": { id: "anthropic/claude-fable-5:batch", name: "Anthropic: Claude Fable 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { off: null, xhigh: "xhigh", max: "max" } }, "anthropic/claude-haiku-4.5": { id: "anthropic/claude-haiku-4.5", name: "Anthropic: Claude Haiku 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-haiku-4.5:batch": { id: "anthropic/claude-haiku-4.5:batch", name: "Anthropic: Claude Haiku 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 2.5, cacheRead: 0.05, cacheWrite: 0.625 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4": { id: "anthropic/claude-opus-4", name: "Anthropic: Claude Opus 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.1": { id: "anthropic/claude-opus-4.1", name: "Anthropic: Claude Opus 4.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.1:batch": { id: "anthropic/claude-opus-4.1:batch", name: "Anthropic: Claude Opus 4.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 37.5, cacheRead: 0.75, cacheWrite: 9.375 }, contextWindow: 2e5, maxTokens: 32e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.5": { id: "anthropic/claude-opus-4.5", name: "Anthropic: Claude Opus 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.5:batch": { id: "anthropic/claude-opus-4.5:batch", name: "Anthropic: Claude Opus 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-opus-4.6": { id: "anthropic/claude-opus-4.6", name: "Anthropic: Claude Opus 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-opus-4.6:batch": { id: "anthropic/claude-opus-4.6:batch", name: "Anthropic: Claude Opus 4.6 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-opus-4.7": { id: "anthropic/claude-opus-4.7", name: "Anthropic: Claude Opus 4.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.7-fast": { id: "anthropic/claude-opus-4.7-fast", name: "Anthropic: Claude Opus 4.7 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 150, cacheRead: 3, cacheWrite: 37.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.7:batch": { id: "anthropic/claude-opus-4.7:batch", name: "Anthropic: Claude Opus 4.7 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8": { id: "anthropic/claude-opus-4.8", name: "Anthropic: Claude Opus 4.8", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8-fast": { id: "anthropic/claude-opus-4.8-fast", name: "Anthropic: Claude Opus 4.8 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-4.8:batch": { id: "anthropic/claude-opus-4.8:batch", name: "Anthropic: Claude Opus 4.8 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5": { id: "anthropic/claude-opus-5", name: "Claude Opus 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5-fast": { id: "anthropic/claude-opus-5-fast", name: "Claude Opus 5 (Fast)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-opus-5:batch": { id: "anthropic/claude-opus-5:batch", name: "Claude Opus 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 12.5, cacheRead: 0.25, cacheWrite: 3.125 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-sonnet-4": { id: "anthropic/claude-sonnet-4", name: "Anthropic: Claude Sonnet 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 2e5, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.5": { id: "anthropic/claude-sonnet-4.5", name: "Anthropic: Claude Sonnet 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 1e6, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.5:batch": { id: "anthropic/claude-sonnet-4.5:batch", name: "Anthropic: Claude Sonnet 4.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 }, contextWindow: 1e6, maxTokens: 64e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "anthropic/claude-sonnet-4.6": { id: "anthropic/claude-sonnet-4.6", name: "Anthropic: Claude Sonnet 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-sonnet-4.6:batch": { id: "anthropic/claude-sonnet-4.6:batch", name: "Anthropic: Claude Sonnet 4.6 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 1.875 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { max: "max" } }, "anthropic/claude-sonnet-5": { id: "anthropic/claude-sonnet-5", name: "Anthropic: Claude Sonnet 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "anthropic/claude-sonnet-5:batch": { id: "anthropic/claude-sonnet-5:batch", name: "Anthropic: Claude Sonnet 5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { thinkingFormat: "openrouter", cacheControlFormat: "anthropic" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "arcee-ai/trinity-large-thinking": { id: "arcee-ai/trinity-large-thinking", name: "Arcee AI: Trinity Large Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.22, output: 0.85, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "arcee-ai/virtuoso-large": { id: "arcee-ai/virtuoso-large", name: "Arcee AI: Virtuoso Large", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.75, output: 1.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, auto: { id: "auto", name: "Auto", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 3e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-1.6": { id: "bytedance-seed/seed-1.6", name: "ByteDance Seed: Seed 1.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-1.6-flash": { id: "bytedance-seed/seed-1.6-flash", name: "ByteDance Seed: Seed 1.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.075, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2-1-turbo": { id: "bytedance-seed/seed-2-1-turbo", name: "ByteDance Seed: Seed 2.1 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-code": { id: "bytedance-seed/seed-2.0-code", name: "ByteDance Seed: Seed-2.0-Code", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-lite": { id: "bytedance-seed/seed-2.0-lite", name: "ByteDance Seed: Seed-2.0-Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "bytedance-seed/seed-2.0-mini": { id: "bytedance-seed/seed-2.0-mini", name: "ByteDance Seed: Seed-2.0-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/command-r-08-2024": { id: "cohere/command-r-08-2024", name: "Cohere: Command R (08-2024)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/command-r-plus-08-2024": { id: "cohere/command-r-plus-08-2024", name: "Cohere: Command R+ (08-2024)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "cohere/north-mini-code:free": { id: "cohere/north-mini-code:free", name: "Cohere: North Mini Code (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat": { id: "deepseek/deepseek-chat", name: "DeepSeek: DeepSeek V3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.2574, output: 1.0287, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat-v3-0324": { id: "deepseek/deepseek-chat-v3-0324", name: "DeepSeek: DeepSeek V3 0324", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.25, output: 1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 163840, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-chat-v3.1": { id: "deepseek/deepseek-chat-v3.1", name: "DeepSeek: DeepSeek V3.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 1.65, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 161e3, maxTokens: 161e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-r1": { id: "deepseek/deepseek-r1", name: "DeepSeek: R1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.7, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 64e3, maxTokens: 16e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-r1-0528": { id: "deepseek/deepseek-r1-0528", name: "DeepSeek: R1 0528", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.5, output: 2.15, cacheRead: 0.35, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.1-terminus": { id: "deepseek/deepseek-v3.1-terminus", name: "DeepSeek: DeepSeek V3.1 Terminus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 1, cacheRead: 0.135, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.2": { id: "deepseek/deepseek-v3.2", name: "DeepSeek: DeepSeek V3.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.26, output: 0.38, cacheRead: 0.13, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 163840, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v3.2-exp": { id: "deepseek/deepseek-v3.2-exp", name: "DeepSeek: DeepSeek V3.2 Exp", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 0.41, cacheRead: 0, cacheWrite: 0 }, contextWindow: 163840, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "deepseek/deepseek-v4-flash": { id: "deepseek/deepseek-v4-flash", name: "DeepSeek: DeepSeek V4 Flash 0423", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.0574, output: 0.1148, cacheRead: 0.01148, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-flash-0731": { id: "deepseek/deepseek-v4-flash-0731", name: "DeepSeek: DeepSeek V4 Flash 0731", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.14, output: 0.28, cacheRead: 0.028, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-flash-vision-exp": { id: "deepseek/deepseek-v4-flash-vision-exp", name: "DeepSeek: DeepSeek V4 Flash Vision Exp", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.22, output: 0.66, cacheRead: 7e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-pro": { id: "deepseek/deepseek-v4-pro", name: "DeepSeek: DeepSeek V4 Pro 0423", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.526176, output: 1.052352, cacheRead: 0.043848, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 384e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "deepseek/deepseek-v4-pro-0813": { id: "deepseek/deepseek-v4-pro-0813", name: "DeepSeek: DeepSeek V4 Pro 0813", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.122, output: 3.366, cacheRead: 0.0374, cacheWrite: 0 }, contextWindow: 1048575, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "dots-studio/dots-3-note-preview:free": { id: "dots-studio/dots-3-note-preview:free", name: "Dots Studio: Dots3-Note Preview (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 512e3, maxTokens: 512e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash": { id: "google/gemini-2.5-flash", name: "Google: Gemini 2.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash-lite": { id: "google/gemini-2.5-flash-lite", name: "Google: Gemini 2.5 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash-lite:batch": { id: "google/gemini-2.5-flash-lite:batch", name: "Google: Gemini 2.5 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.05, output: 0.2, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-flash:batch": { id: "google/gemini-2.5-flash:batch", name: "Google: Gemini 2.5 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 1.25, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro": { id: "google/gemini-2.5-pro", name: "Google: Gemini 2.5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro-preview": { id: "google/gemini-2.5-pro-preview", name: "Google: Gemini 2.5 Pro Preview 06-05", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro-preview-05-06": { id: "google/gemini-2.5-pro-preview-05-06", name: "Google: Gemini 2.5 Pro Preview 05-06", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65535, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-2.5-pro:batch": { id: "google/gemini-2.5-pro:batch", name: "Google: Gemini 2.5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-flash-preview": { id: "google/gemini-3-flash-preview", name: "Google: Gemini 3 Flash Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-flash-preview:batch": { id: "google/gemini-3-flash-preview:batch", name: "Google: Gemini 3 Flash Preview (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3-pro-image": { id: "google/gemini-3-pro-image", name: "Google: Nano Banana Pro (Gemini 3 Pro Image)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 65536, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite": { id: "google/gemini-3.1-flash-lite", name: "Google: Gemini 3.1 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite-preview": { id: "google/gemini-3.1-flash-lite-preview", name: "Google: Gemini 3.1 Flash Lite Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-flash-lite:batch": { id: "google/gemini-3.1-flash-lite:batch", name: "Google: Gemini 3.1 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.125, output: 0.75, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview": { id: "google/gemini-3.1-pro-preview", name: "Google: Gemini 3.1 Pro Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview-customtools": { id: "google/gemini-3.1-pro-preview-customtools", name: "Google: Gemini 3.1 Pro Preview Custom Tools", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.1-pro-preview:batch": { id: "google/gemini-3.1-pro-preview:batch", name: "Google: Gemini 3.1 Pro Preview (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash": { id: "google/gemini-3.5-flash", name: "Google: Gemini 3.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 9, cacheRead: 0.15, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash-lite": { id: "google/gemini-3.5-flash-lite", name: "Google: Gemini 3.5 Flash Lite", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.083333 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash-lite:batch": { id: "google/gemini-3.5-flash-lite:batch", name: "Google: Gemini 3.5 Flash Lite (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 1.25, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.5-flash:batch": { id: "google/gemini-3.5-flash:batch", name: "Google: Gemini 3.5 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.6-flash": { id: "google/gemini-3.6-flash", name: "Google: Gemini 3.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.041667 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.6-flash:batch": { id: "google/gemini-3.6-flash:batch", name: "Google: Gemini 3.6 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.041667 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.7-flash": { id: "google/gemini-3.7-flash", name: "Google: Gemini 3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemini-3.7-flash:batch": { id: "google/gemini-3.7-flash:batch", name: "Google: Gemini 3.7 Flash (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1875, output: 0.9375, cacheRead: 0.01875, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-3-12b-it": { id: "google/gemma-3-12b-it", name: "Google: Gemma 3 12B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.05, output: 0.15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-3-27b-it": { id: "google/gemma-3-27b-it", name: "Google: Gemma 3 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.08, output: 0.45, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-26b-a4b-it": { id: "google/gemma-4-26b-a4b-it", name: "Google: Gemma 4 26B A4B ", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.07, output: 0.34, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-26b-a4b-it:free": { id: "google/gemma-4-26b-a4b-it:free", name: "Google: Gemma 4 26B A4B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-31b-it": { id: "google/gemma-4-31b-it", name: "Google: Gemma 4 31B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.34, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "google/gemma-4-31b-it:free": { id: "google/gemma-4-31b-it:free", name: "Google: Gemma 4 31B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "ibm-granite/granite-4.1-8b": { id: "ibm-granite/granite-4.1-8b", name: "IBM: Granite 4.1 8B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.05, output: 0.1, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "inception/mercury-2": { id: "inception/mercury-2", name: "Inception: Mercury 2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.25, output: 0.75, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 5e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" }, thinkingLevelMap: { off: null } }, "inclusionai/ling-3.0-flash": { id: "inclusionai/ling-3.0-flash", name: "Ling-3.0-flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.021, output: 0.063, cacheRead: 42e-4, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-air-v2.5": { id: "kwaipilot/kat-coder-air-v2.5", name: "Kwaipilot: KAT-Coder-Air V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-pro-v2": { id: "kwaipilot/kat-coder-pro-v2", name: "Kwaipilot: KAT-Coder-Pro V2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "kwaipilot/kat-coder-pro-v2.5": { id: "kwaipilot/kat-coder-pro-v2.5", name: "Kwaipilot: KAT-Coder-Pro V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.74, output: 2.96, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 8e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "liquid/lfm-2.5-2.6b:free": { id: "liquid/lfm-2.5-2.6b:free", name: "LiquidAI: LFM2.5-2.6B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meituan/longcat-2.0": { id: "meituan/longcat-2.0", name: "Meituan: LongCat 2.0", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 6e-3, cacheWrite: 0 }, contextWindow: 1048756, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.1-70b-instruct": { id: "meta-llama/llama-3.1-70b-instruct", name: "Meta: Llama 3.1 70B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.1-8b-instruct": { id: "meta-llama/llama-3.1-8b-instruct", name: "Meta: Llama 3.1 8B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.05, output: 0.08, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-3.3-70b-instruct": { id: "meta-llama/llama-3.3-70b-instruct", name: "Meta: Llama 3.3 70B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.32, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-4-maverick": { id: "meta-llama/llama-4-maverick", name: "Meta: Llama 4 Maverick", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.8, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta-llama/llama-4-scout": { id: "meta-llama/llama-4-scout", name: "Meta: Llama 4 Scout", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 327680, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-glimmer-30b": { id: "meta/muse-glimmer-30b", name: "Meta: Muse Glimmer 30B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.35, output: 1.5, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.1": { id: "meta/muse-spark-1.1", name: "Meta: Muse Spark 1.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.2": { id: "meta/muse-spark-1.2", name: "Meta: Muse Spark 1.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 4.25, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "meta/muse-spark-1.2-contributor": { id: "meta/muse-spark-1.2-contributor", name: "Meta: Muse Spark 1.2 Contributor", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m1": { id: "minimax/minimax-m1", name: "MiniMax: MiniMax M1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 4e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2": { id: "minimax/minimax-m2", name: "MiniMax: MiniMax M2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.255, output: 1.02, cacheRead: 0, cacheWrite: 0 }, contextWindow: 204800, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.1": { id: "minimax/minimax-m2.1", name: "MiniMax: MiniMax M2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 204800, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.5": { id: "minimax/minimax-m2.5", name: "MiniMax: MiniMax M2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.27, output: 1.08, cacheRead: 0.027, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m2.7": { id: "minimax/minimax-m2.7", name: "MiniMax: MiniMax M2.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.24, output: 0.96, cacheRead: 0.048, cacheWrite: 0 }, contextWindow: 196608, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m3": { id: "minimax/minimax-m3", name: "MiniMax: MiniMax M3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 512e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "minimax/minimax-m3:batch": { id: "minimax/minimax-m3:batch", name: "MiniMax: MiniMax M3 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/codestral-2508": { id: "mistralai/codestral-2508", name: "Mistral: Codestral 2508", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 0.9, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-14b-2512": { id: "mistralai/ministral-14b-2512", name: "Mistral: Ministral 3 14B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.2, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-3b-2512": { id: "mistralai/ministral-3b-2512", name: "Mistral: Ministral 3 3B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.1, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/ministral-8b-2512": { id: "mistralai/ministral-8b-2512", name: "Mistral: Ministral 3 8B 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.15, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large": { id: "mistralai/mistral-large", name: "Mistral Large", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large-2407": { id: "mistralai/mistral-large-2407", name: "Mistral Large 2407", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-large-2512": { id: "mistralai/mistral-large-2512", name: "Mistral: Mistral Large 3 2512", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.5, output: 1.5, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3": { id: "mistralai/mistral-medium-3", name: "Mistral: Mistral Medium 3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3-5": { id: "mistralai/mistral-medium-3-5", name: "Mistral: Mistral Medium 3.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.5, output: 7.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-medium-3.1": { id: "mistralai/mistral-medium-3.1", name: "Mistral: Mistral Medium 3.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-nemo": { id: "mistralai/mistral-nemo", name: "Mistral: Mistral Nemo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.019, output: 0.03, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-saba": { id: "mistralai/mistral-saba", name: "Mistral: Saba", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.2, output: 0.6, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-small-2603": { id: "mistralai/mistral-small-2603", name: "Mistral: Mistral Small 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mistral-small-3.2-24b-instruct": { id: "mistralai/mistral-small-3.2-24b-instruct", name: "Mistral: Mistral Small 3.2 24B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.075, output: 0.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/mixtral-8x22b-instruct": { id: "mistralai/mixtral-8x22b-instruct", name: "Mistral: Mixtral 8x22B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "mistralai/voxtral-small-24b-2507": { id: "mistralai/voxtral-small-24b-2507", name: "Mistral: Voxtral Small 24B 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.3, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 32e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2": { id: "moonshotai/kimi-k2", name: "MoonshotAI: Kimi K2 0711", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.57, output: 2.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2-0905": { id: "moonshotai/kimi-k2-0905", name: "MoonshotAI: Kimi K2 0905", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.6, output: 2.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2-thinking": { id: "moonshotai/kimi-k2-thinking", name: "MoonshotAI: Kimi K2 Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 2.5, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 100352, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.5": { id: "moonshotai/kimi-k2.5", name: "MoonshotAI: Kimi K2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.41, output: 2.06, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.6": { id: "moonshotai/kimi-k2.6", name: "MoonshotAI: Kimi K2.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true } }, "moonshotai/kimi-k2.7-code": { id: "moonshotai/kimi-k2.7-code", name: "MoonshotAI: Kimi K2.7 Code", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.67, output: 3.4, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k2.7-code:batch": { id: "moonshotai/kimi-k2.7-code:batch", name: "MoonshotAI: Kimi K2.7 Code (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "moonshotai/kimi-k3": { id: "moonshotai/kimi-k3", name: "MoonshotAI: Kimi K3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nex-agi/nex-n2-mini": { id: "nex-agi/nex-n2-mini", name: "Nex AGI: Nex-N2-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.025, output: 0.1, cacheRead: 25e-4, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nex-agi/nex-n2-pro": { id: "nex-agi/nex-n2-pro", name: "Nex AGI: Nex-N2-Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-30b-a3b": { id: "nvidia/nemotron-3-nano-30b-a3b", name: "NVIDIA: Nemotron 3 Nano 30B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.05, output: 0.2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-30b-a3b:free": { id: "nvidia/nemotron-3-nano-30b-a3b:free", name: "NVIDIA: Nemotron 3 Nano 30B A3B (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free": { id: "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free", name: "NVIDIA: Nemotron 3 Nano Omni (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-super-120b-a12b": { id: "nvidia/nemotron-3-super-120b-a12b", name: "NVIDIA: Nemotron 3 Super", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.085, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-super-120b-a12b:free": { id: "nvidia/nemotron-3-super-120b-a12b:free", name: "NVIDIA: Nemotron 3 Super (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b": { id: "nvidia/nemotron-3-ultra-550b-a55b", name: "NVIDIA: Nemotron 3 Ultra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 3.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 512288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b:batch": { id: "nvidia/nemotron-3-ultra-550b-a55b:batch", name: "NVIDIA: Nemotron 3 Ultra (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 3.6, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 512288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3-ultra-550b-a55b:free": { id: "nvidia/nemotron-3-ultra-550b-a55b:free", name: "NVIDIA: Nemotron 3 Ultra (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3.5-lightning": { id: "nvidia/nemotron-3.5-lightning", name: "NVIDIA: Nemotron 3.5 Lightning", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.08, output: 0.2, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-3.5-lightning:free": { id: "nvidia/nemotron-3.5-lightning:free", name: "NVIDIA: Nemotron 3.5 Lightning (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-nano-12b-v2-vl:free": { id: "nvidia/nemotron-nano-12b-v2-vl:free", name: "NVIDIA: Nemotron Nano 12B 2 VL (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "nvidia/nemotron-nano-9b-v2:free": { id: "nvidia/nemotron-nano-9b-v2:free", name: "NVIDIA: Nemotron Nano 9B V2 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo": { id: "openai/gpt-3.5-turbo", name: "OpenAI: GPT-3.5 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.5, output: 1.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo-0613": { id: "openai/gpt-3.5-turbo-0613", name: "OpenAI: GPT-3.5 Turbo (older v0613)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4095, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo-16k": { id: "openai/gpt-3.5-turbo-16k", name: "OpenAI: GPT-3.5 Turbo 16k", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 3, output: 4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-3.5-turbo:batch": { id: "openai/gpt-3.5-turbo:batch", name: "OpenAI: GPT-3.5 Turbo (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.25, output: 0.75, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16385, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4": { id: "openai/gpt-4", name: "OpenAI: GPT-4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 30, output: 60, cacheRead: 0, cacheWrite: 0 }, contextWindow: 8191, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo": { id: "openai/gpt-4-turbo", name: "OpenAI: GPT-4 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo-preview": { id: "openai/gpt-4-turbo-preview", name: "OpenAI: GPT-4 Turbo Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4-turbo:batch": { id: "openai/gpt-4-turbo:batch", name: "OpenAI: GPT-4 Turbo (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1": { id: "openai/gpt-4.1", name: "OpenAI: GPT-4.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-mini": { id: "openai/gpt-4.1-mini", name: "OpenAI: GPT-4.1 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-mini:batch": { id: "openai/gpt-4.1-mini:batch", name: "OpenAI: GPT-4.1 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.2, output: 0.8, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-nano": { id: "openai/gpt-4.1-nano", name: "OpenAI: GPT-4.1 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1-nano:batch": { id: "openai/gpt-4.1-nano:batch", name: "OpenAI: GPT-4.1 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.05, output: 0.2, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4.1:batch": { id: "openai/gpt-4.1:batch", name: "OpenAI: GPT-4.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o": { id: "openai/gpt-4o", name: "OpenAI: GPT-4o", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-05-13": { id: "openai/gpt-4o-2024-05-13", name: "OpenAI: GPT-4o (2024-05-13)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-08-06": { id: "openai/gpt-4o-2024-08-06", name: "OpenAI: GPT-4o (2024-08-06)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-2024-11-20": { id: "openai/gpt-4o-2024-11-20", name: "OpenAI: GPT-4o (2024-11-20)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini": { id: "openai/gpt-4o-mini", name: "OpenAI: GPT-4o-mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini-2024-07-18": { id: "openai/gpt-4o-mini-2024-07-18", name: "OpenAI: GPT-4o-mini (2024-07-18)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o-mini:batch": { id: "openai/gpt-4o-mini:batch", name: "OpenAI: GPT-4o-mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-4o:batch": { id: "openai/gpt-4o:batch", name: "OpenAI: GPT-4o (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1.25, output: 5, cacheRead: 0.625, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5": { id: "openai/gpt-5", name: "OpenAI: GPT-5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-codex:batch": { id: "openai/gpt-5-codex:batch", name: "OpenAI: GPT-5 Codex (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-mini": { id: "openai/gpt-5-mini", name: "OpenAI: GPT-5 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-mini:batch": { id: "openai/gpt-5-mini:batch", name: "OpenAI: GPT-5 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.125, output: 1, cacheRead: 0.0125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-nano": { id: "openai/gpt-5-nano", name: "OpenAI: GPT-5 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.05, output: 0.4, cacheRead: 5e-3, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-nano:batch": { id: "openai/gpt-5-nano:batch", name: "OpenAI: GPT-5 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.025, output: 0.2, cacheRead: 25e-4, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-pro": { id: "openai/gpt-5-pro", name: "OpenAI: GPT-5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 120, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5-pro:batch": { id: "openai/gpt-5-pro:batch", name: "OpenAI: GPT-5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 60, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1": { id: "openai/gpt-5.1", name: "OpenAI: GPT-5.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex": { id: "openai/gpt-5.1-codex", name: "OpenAI: GPT-5.1-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.13, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex-max": { id: "openai/gpt-5.1-codex-max", name: "OpenAI: GPT-5.1-Codex-Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1-codex-mini": { id: "openai/gpt-5.1-codex-mini", name: "OpenAI: GPT-5.1-Codex-Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.1:batch": { id: "openai/gpt-5.1:batch", name: "OpenAI: GPT-5.1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-5.2": { id: "openai/gpt-5.2", name: "OpenAI: GPT-5.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-chat": { id: "openai/gpt-5.2-chat", name: "OpenAI: GPT-5.2 Chat", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 32e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-codex": { id: "openai/gpt-5.2-codex", name: "OpenAI: GPT-5.2-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-pro": { id: "openai/gpt-5.2-pro", name: "OpenAI: GPT-5.2 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 21, output: 168, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2-pro:batch": { id: "openai/gpt-5.2-pro:batch", name: "OpenAI: GPT-5.2 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10.5, output: 84, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.2:batch": { id: "openai/gpt-5.2:batch", name: "OpenAI: GPT-5.2 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.875, output: 7, cacheRead: 0.0875, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.3-codex": { id: "openai/gpt-5.3-codex", name: "OpenAI: GPT-5.3-Codex", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4": { id: "openai/gpt-5.4", name: "OpenAI: GPT-5.4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-mini": { id: "openai/gpt-5.4-mini", name: "OpenAI: GPT-5.4 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-mini:batch": { id: "openai/gpt-5.4-mini:batch", name: "OpenAI: GPT-5.4 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 2.25, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-nano": { id: "openai/gpt-5.4-nano", name: "OpenAI: GPT-5.4 Nano", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.25, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-nano:batch": { id: "openai/gpt-5.4-nano:batch", name: "OpenAI: GPT-5.4 Nano (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.625, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-pro": { id: "openai/gpt-5.4-pro", name: "OpenAI: GPT-5.4 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4-pro:batch": { id: "openai/gpt-5.4-pro:batch", name: "OpenAI: GPT-5.4 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.4:batch": { id: "openai/gpt-5.4:batch", name: "OpenAI: GPT-5.4 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 7.5, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5": { id: "openai/gpt-5.5", name: "OpenAI: GPT-5.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5-pro": { id: "openai/gpt-5.5-pro", name: "OpenAI: GPT-5.5 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", off: null, minimal: null, low: null } }, "openai/gpt-5.5-pro:batch": { id: "openai/gpt-5.5-pro:batch", name: "OpenAI: GPT-5.5 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 90, cacheRead: 0, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.5:batch": { id: "openai/gpt-5.5:batch", name: "OpenAI: GPT-5.5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "openai/gpt-5.6-luna": { id: "openai/gpt-5.6-luna", name: "OpenAI: GPT-5.6 Luna", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna-pro": { id: "openai/gpt-5.6-luna-pro", name: "OpenAI: GPT-5.6 Luna Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna-pro:batch": { id: "openai/gpt-5.6-luna-pro:batch", name: "OpenAI: GPT-5.6 Luna Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-luna:batch": { id: "openai/gpt-5.6-luna:batch", name: "OpenAI: GPT-5.6 Luna (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.6, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol": { id: "openai/gpt-5.6-sol", name: "OpenAI: GPT-5.6 Sol", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol-pro": { id: "openai/gpt-5.6-sol-pro", name: "OpenAI: GPT-5.6 Sol Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol-pro:batch": { id: "openai/gpt-5.6-sol-pro:batch", name: "OpenAI: GPT-5.6 Sol Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-sol:batch": { id: "openai/gpt-5.6-sol:batch", name: "OpenAI: GPT-5.6 Sol (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra": { id: "openai/gpt-5.6-terra", name: "OpenAI: GPT-5.6 Terra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra-pro": { id: "openai/gpt-5.6-terra-pro", name: "OpenAI: GPT-5.6 Terra Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra-pro:batch": { id: "openai/gpt-5.6-terra-pro:batch", name: "OpenAI: GPT-5.6 Terra Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5.6-terra:batch": { id: "openai/gpt-5.6-terra:batch", name: "OpenAI: GPT-5.6 Terra (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 105e4, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh", max: "max" } }, "openai/gpt-5:batch": { id: "openai/gpt-5:batch", name: "OpenAI: GPT-5 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.625, output: 5, cacheRead: 0.0625, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-audio": { id: "openai/gpt-audio", name: "OpenAI: GPT Audio", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 2.5, output: 10, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-audio-mini": { id: "openai/gpt-audio-mini", name: "OpenAI: GPT Audio Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.6, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-chat-latest": { id: "openai/gpt-chat-latest", name: "OpenAI: GPT Chat Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-120b": { id: "openai/gpt-oss-120b", name: "OpenAI: gpt-oss-120b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.037, output: 0.17, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-20b": { id: "openai/gpt-oss-20b", name: "OpenAI: gpt-oss-20b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.03, output: 0.13, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { thinkingFormat: "openrouter" } }, "openai/gpt-oss-safeguard-20b": { id: "openai/gpt-oss-safeguard-20b", name: "OpenAI: gpt-oss-safeguard-20b", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.075, output: 0.3, cacheRead: 0.0375, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 65536, compat: { thinkingFormat: "openrouter" } }, "openai/o1": { id: "openai/o1", name: "OpenAI: o1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 60, cacheRead: 7.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o1:batch": { id: "openai/o1:batch", name: "OpenAI: o1 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 7.5, output: 30, cacheRead: 3.75, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3": { id: "openai/o3", name: "OpenAI: o3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini": { id: "openai/o3-mini", name: "OpenAI: o3 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini-high": { id: "openai/o3-mini-high", name: "OpenAI: o3 Mini High", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini-high:batch": { id: "openai/o3-mini-high:batch", name: "OpenAI: o3 Mini High (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-mini:batch": { id: "openai/o3-mini:batch", name: "OpenAI: o3 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.55, output: 2.2, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-pro": { id: "openai/o3-pro", name: "OpenAI: o3 Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 20, output: 80, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3-pro:batch": { id: "openai/o3-pro:batch", name: "OpenAI: o3 Pro (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 40, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o3:batch": { id: "openai/o3:batch", name: "OpenAI: o3 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini": { id: "openai/o4-mini", name: "OpenAI: o4 Mini", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini-high": { id: "openai/o4-mini-high", name: "OpenAI: o4 Mini High", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini-high:batch": { id: "openai/o4-mini-high:batch", name: "OpenAI: o4 Mini High (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.55, output: 2.2, cacheRead: 0.1375, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openai/o4-mini:batch": { id: "openai/o4-mini:batch", name: "OpenAI: o4 Mini (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.55, output: 2.2, cacheRead: 0.1375, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, compat: { thinkingFormat: "openrouter" } }, "openrouter/auto": { id: "openrouter/auto", name: "Auto Router", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: -1e6, output: -1e6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/auto-beta": { id: "openrouter/auto-beta", name: "Auto Router (Beta)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: -1e6, output: -1e6, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/free": { id: "openrouter/free", name: "Free Models Router", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "openrouter/fusion": { id: "openrouter/fusion", name: "OpenRouter: Fusion", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 3e4, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-s-2.1": { id: "poolside/laguna-s-2.1", name: "Poolside: Laguna S 2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.09, output: 0.18, cacheRead: 9e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-s-2.1:free": { id: "poolside/laguna-s-2.1:free", name: "Poolside: Laguna S 2.1 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-xs-2.1": { id: "poolside/laguna-xs-2.1", name: "Poolside: Laguna XS 2.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.06, output: 0.12, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "poolside/laguna-xs-2.1:free": { id: "poolside/laguna-xs-2.1:free", name: "Poolside: Laguna XS 2.1 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-2.5-72b-instruct": { id: "qwen/qwen-2.5-72b-instruct", name: "Qwen2.5 72B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.36, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-2.5-7b-instruct": { id: "qwen/qwen-2.5-7b-instruct", name: "Qwen: Qwen2.5 7B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 0.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus": { id: "qwen/qwen-plus", name: "Qwen: Qwen-Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0.052, cacheWrite: 0.325 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus-2025-07-28": { id: "qwen/qwen-plus-2025-07-28", name: "Qwen: Qwen Plus 0728", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen-plus-2025-07-28:thinking": { id: "qwen/qwen-plus-2025-07-28:thinking", name: "Qwen: Qwen Plus 0728 (thinking)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.26, output: 0.78, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-14b": { id: "qwen/qwen3-14b", name: "Qwen: Qwen3 14B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.12, output: 0.24, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b": { id: "qwen/qwen3-235b-a22b", name: "Qwen: Qwen3 235B A22B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.455, output: 1.82, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b-2507": { id: "qwen/qwen3-235b-a22b-2507", name: "Qwen: Qwen3 235B A22B Instruct 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.09, output: 0.55, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-235b-a22b-thinking-2507": { id: "qwen/qwen3-235b-a22b-thinking-2507", name: "Qwen: Qwen3 235B A22B Thinking 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.23, output: 2.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b": { id: "qwen/qwen3-30b-a3b", name: "Qwen: Qwen3 30B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.12, output: 0.5, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b-instruct-2507": { id: "qwen/qwen3-30b-a3b-instruct-2507", name: "Qwen: Qwen3 30B A3B Instruct 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.04815, output: 0.19305, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 32e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-30b-a3b-thinking-2507": { id: "qwen/qwen3-30b-a3b-thinking-2507", name: "Qwen: Qwen3 30B A3B Thinking 2507", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 81920, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-32b": { id: "qwen/qwen3-32b", name: "Qwen: Qwen3 32B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.08, output: 0.28, cacheRead: 0, cacheWrite: 0 }, contextWindow: 40960, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-8b": { id: "qwen/qwen3-8b", name: "Qwen: Qwen3 8B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 8192, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder": { id: "qwen/qwen3-coder", name: "Qwen: Qwen3 Coder 480B A35B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.3, output: 1, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-30b-a3b-instruct": { id: "qwen/qwen3-coder-30b-a3b-instruct", name: "Qwen: Qwen3 Coder 30B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.07, output: 0.28, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-flash": { id: "qwen/qwen3-coder-flash", name: "Qwen: Qwen3 Coder Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.195, output: 0.975, cacheRead: 0.039, cacheWrite: 0.24375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-next": { id: "qwen/qwen3-coder-next", name: "Qwen: Qwen3 Coder Next", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.12, output: 0.8, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-coder-plus": { id: "qwen/qwen3-coder-plus", name: "Qwen: Qwen3 Coder Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.65, output: 3.25, cacheRead: 0.13, cacheWrite: 0.8125 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-max": { id: "qwen/qwen3-max", name: "Qwen: Qwen3 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.78, output: 3.9, cacheRead: 0.156, cacheWrite: 0.975 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-max-thinking": { id: "qwen/qwen3-max-thinking", name: "Qwen: Qwen3 Max Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.78, output: 3.9, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-next-80b-a3b-instruct": { id: "qwen/qwen3-next-80b-a3b-instruct", name: "Qwen: Qwen3 Next 80B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.1, output: 1.1, cacheRead: 0.07, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-next-80b-a3b-thinking": { id: "qwen/qwen3-next-80b-a3b-thinking", name: "Qwen: Qwen3 Next 80B A3B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.15, output: 1.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-235b-a22b-instruct": { id: "qwen/qwen3-vl-235b-a22b-instruct", name: "Qwen: Qwen3 VL 235B A22B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.21, output: 1.9, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-235b-a22b-thinking": { id: "qwen/qwen3-vl-235b-a22b-thinking", name: "Qwen: Qwen3 VL 235B A22B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-30b-a3b-instruct": { id: "qwen/qwen3-vl-30b-a3b-instruct", name: "Qwen: Qwen3 VL 30B A3B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.13, output: 0.52, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-30b-a3b-thinking": { id: "qwen/qwen3-vl-30b-a3b-thinking", name: "Qwen: Qwen3 VL 30B A3B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 2.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-32b-instruct": { id: "qwen/qwen3-vl-32b-instruct", name: "Qwen: Qwen3 VL 32B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.104, output: 0.416, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-8b-instruct": { id: "qwen/qwen3-vl-8b-instruct", name: "Qwen: Qwen3 VL 8B Instruct", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.117, output: 0.455, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3-vl-8b-thinking": { id: "qwen/qwen3-vl-8b-thinking", name: "Qwen: Qwen3 VL 8B Thinking", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.18, output: 2.1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-122b-a10b": { id: "qwen/qwen3.5-122b-a10b", name: "Qwen: Qwen3.5-122B-A10B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.26, output: 2.08, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-27b": { id: "qwen/qwen3.5-27b", name: "Qwen: Qwen3.5-27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.195, output: 1.56, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-35b-a3b": { id: "qwen/qwen3.5-35b-a3b", name: "Qwen: Qwen3.5-35B-A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 1.25, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-397b-a17b": { id: "qwen/qwen3.5-397b-a17b", name: "Qwen: Qwen3.5 397B A17B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.5, output: 3.6, cacheRead: 0.3, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-9b": { id: "qwen/qwen3.5-9b", name: "Qwen: Qwen3.5-9B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-flash-02-23": { id: "qwen/qwen3.5-flash-02-23", name: "Qwen: Qwen3.5-Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.065, output: 0.26, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-plus-02-15": { id: "qwen/qwen3.5-plus-02-15", name: "Qwen: Qwen3.5 Plus 2026-02-15", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.26, output: 1.56, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.5-plus-20260420": { id: "qwen/qwen3.5-plus-20260420", name: "Qwen: Qwen3.5 Plus 2026-04-20", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.8, cacheRead: 0, cacheWrite: 0.375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-27b": { id: "qwen/qwen3.6-27b", name: "Qwen: Qwen3.6 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.32, output: 3.2, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 81920, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-35b-a3b": { id: "qwen/qwen3.6-35b-a3b", name: "Qwen: Qwen3.6 35B A3B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 1, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-flash": { id: "qwen/qwen3.6-flash", name: "Qwen: Qwen3.6 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.1875, output: 1.125, cacheRead: 0, cacheWrite: 0.234375 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-max-preview": { id: "qwen/qwen3.6-max-preview", name: "Qwen: Qwen3.6 Max Preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.027, output: 6.162, cacheRead: 0, cacheWrite: 1.28375 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.6-plus": { id: "qwen/qwen3.6-plus", name: "Qwen: Qwen3.6 Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.325, output: 1.95, cacheRead: 0, cacheWrite: 0.40625 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-flash": { id: "qwen/qwen3.7-flash", name: "Qwen: Qwen3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.03, output: 0.13, cacheRead: 6e-3, cacheWrite: 0.038 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-max": { id: "qwen/qwen3.7-max", name: "Qwen: Qwen3.7 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.475, output: 4.425, cacheRead: 0.295, cacheWrite: 1.84375 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.7-plus": { id: "qwen/qwen3.7-plus", name: "Qwen: Qwen3.7 Plus", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.32, output: 1.28, cacheRead: 0.064, cacheWrite: 0.4 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-2.4t-a95b": { id: "qwen/qwen3.8-2.4t-a95b", name: "Qwen: Qwen3.8 2.4T A95B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-27b": { id: "qwen/qwen3.8-27b", name: "Qwen: Qwen3.8 27B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 3, cacheRead: 0.05, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "qwen/qwen3.8-max": { id: "qwen/qwen3.8-max", name: "Qwen: Qwen3.8 Max", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "rekaai/reka-edge": { id: "rekaai/reka-edge", name: "Reka Edge", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.1, cacheRead: 0, cacheWrite: 0 }, contextWindow: 16384, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "relace/relace-search": { id: "relace/relace-search", name: "Relace: Relace Search", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 1, output: 3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sakana/fugu-ultra": { id: "sakana/fugu-ultra", name: "Sakana: Fugu Ultra", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sakana/sakana-namazu": { id: "sakana/sakana-namazu", name: "Sakana: Sakana Namazu", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.15, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "sao10k/l3.1-euryale-70b": { id: "sao10k/l3.1-euryale-70b", name: "Sao10K: Llama 3.1 Euryale 70B v2.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.85, output: 0.85, cacheRead: 0, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stealth/ox-alpha": { id: "stealth/ox-alpha", name: "Ox Alpha", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stepfun/step-3.5-flash": { id: "stepfun/step-3.5-flash", name: "StepFun: Step 3.5 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.1, output: 0.3, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "stepfun/step-3.7-flash": { id: "stepfun/step-3.7-flash", name: "StepFun: Step 3.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 256e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "tencent/hy3": { id: "tencent/hy3", name: "Tencent: Hy3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.132, output: 0.528, cacheRead: 0.033, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "tencent/hy3-preview": { id: "tencent/hy3-preview", name: "Tencent: Hy3 preview", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.18, output: 0.6, cacheRead: 0.06, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thedrummer/unslopnemo-12b": { id: "thedrummer/unslopnemo-12b", name: "TheDrummer: UnslopNemo 12B", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: false, input: ["text"], cost: { input: 0.4, output: 0.4, cacheRead: 0, cacheWrite: 0 }, contextWindow: 32768, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling": { id: "thinkingmachines/inkling", name: "Thinking Machines: Inkling", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling-small": { id: "thinkingmachines/inkling-small", name: "Thinking Machines: Inkling Small", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.45, output: 1.2, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling-small:free": { id: "thinkingmachines/inkling-small:free", name: "Thinking Machines: Inkling Small (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling:batch": { id: "thinkingmachines/inkling:batch", name: "Thinking Machines: Inkling (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "thinkingmachines/inkling:free": { id: "thinkingmachines/inkling:free", name: "Thinking Machines: Inkling (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "upstage/solar-pro-3": { id: "upstage/solar-pro-3", name: "Upstage: Solar Pro 3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "upstage/solar-pro4": { id: "upstage/solar-pro4", name: "Upstage: Solar Pro 4", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.03, output: 0.12, cacheRead: 6e-3, cacheWrite: 0 }, contextWindow: 524288, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.20": { id: "x-ai/grok-4.20", name: "SpaceXAI: Grok 4.20", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 2e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.3": { id: "x-ai/grok-4.3", name: "SpaceXAI: Grok 4.3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.5": { id: "x-ai/grok-4.5", name: "SpaceXAI: Grok 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.3, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-4.6": { id: "x-ai/grok-4.6", name: "SpaceXAI: Grok 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "x-ai/grok-build-0.1": { id: "x-ai/grok-build-0.1", name: "SpaceXAI: Grok Build 0.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 2, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "xiaomi/mimo-v2.5": { id: "xiaomi/mimo-v2.5", name: "Xiaomi: MiMo-V2.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "xiaomi/mimo-v2.5-pro": { id: "xiaomi/mimo-v2.5-pro", name: "Xiaomi: MiMo-V2.5-Pro", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 36e-4, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5": { id: "z-ai/glm-4.5", name: "Z.ai: GLM 4.5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 2.2, cacheRead: 0.11, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 98304, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5-air": { id: "z-ai/glm-4.5-air", name: "Z.ai: GLM 4.5 Air", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.13, output: 0.85, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 98304, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.5v": { id: "z-ai/glm-4.5v", name: "Z.ai: GLM 4.5V", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.6, output: 1.8, cacheRead: 0.11, cacheWrite: 0 }, contextWindow: 65536, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.6": { id: "z-ai/glm-4.6", name: "Z.ai: GLM 4.6", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.5, output: 2, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.6v": { id: "z-ai/glm-4.6v", name: "Z.ai: GLM 4.6V", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 0.9, cacheRead: 0.055, cacheWrite: 0 }, contextWindow: 131072, maxTokens: 32768, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.7": { id: "z-ai/glm-4.7", name: "Z.ai: GLM 4.7", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.4, output: 1.75, cacheRead: 0.08, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-4.7-flash": { id: "z-ai/glm-4.7-flash", name: "Z.ai: GLM 4.7 Flash", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.06, output: 0.4, cacheRead: 0.01, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 16384, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5": { id: "z-ai/glm-5", name: "Z.ai: GLM 5", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.6, output: 1.9, cacheRead: 0.119, cacheWrite: 0 }, contextWindow: 198e3, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5-turbo": { id: "z-ai/glm-5-turbo", name: "Z.ai: GLM 5 Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.1": { id: "z-ai/glm-5.1", name: "Z.ai: GLM 5.1", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.966, output: 3.036, cacheRead: 0.1794, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.2": { id: "z-ai/glm-5.2", name: "Z.ai: GLM 5.2", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.966, output: 3.036, cacheRead: 0.1932, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" }, thinkingLevelMap: { xhigh: "xhigh" } }, "z-ai/glm-5.2:batch": { id: "z-ai/glm-5.2:batch", name: "Z.ai: GLM 5.2 (batch)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048575, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.2:free": { id: "z-ai/glm-5.2:free", name: "Z.ai: GLM 5.2 (free)", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 256e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5.3": { id: "z-ai/glm-5.3", name: "Z.ai: GLM 5.3", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "z-ai/glm-5v-turbo": { id: "z-ai/glm-5v-turbo", name: "Z.ai: GLM 5V Turbo", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1.2, output: 4, cacheRead: 0.24, cacheWrite: 0 }, contextWindow: 202752, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~anthropic/claude-fable-latest": { id: "~anthropic/claude-fable-latest", name: "Anthropic: Claude Fable Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-haiku-latest": { id: "~anthropic/claude-haiku-latest", name: "Anthropic Claude Haiku Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 }, contextWindow: 2e5, maxTokens: 64e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-opus-latest": { id: "~anthropic/claude-opus-latest", name: "Anthropic: Claude Opus Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~anthropic/claude-sonnet-latest": { id: "~anthropic/claude-sonnet-latest", name: "Anthropic Claude Sonnet Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", cacheControlFormat: "anthropic" } }, "~deepseek/deepseek-v4-flash-latest": { id: "~deepseek/deepseek-v4-flash-latest", name: "DeepSeek V4 Flash Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 0.04, output: 0.08, cacheRead: 8e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 1048576, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter", requiresReasoningContentOnAssistantMessages: true }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: null, xhigh: "xhigh" } }, "~google/gemini-flash-latest": { id: "~google/gemini-flash-latest", name: "Google Gemini Flash Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.375, output: 1.875, cacheRead: 0.0375, cacheWrite: 0.020833 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~google/gemini-pro-latest": { id: "~google/gemini-pro-latest", name: "Google Gemini Pro Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0.375 }, contextWindow: 1048576, maxTokens: 65536, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~moonshotai/kimi-latest": { id: "~moonshotai/kimi-latest", name: "MoonshotAI Kimi Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2.6, output: 13, cacheRead: 0.29, cacheWrite: 0 }, contextWindow: 974842, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~openai/gpt-latest": { id: "~openai/gpt-latest", name: "OpenAI GPT Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }, contextWindow: 105e4, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~openai/gpt-mini-latest": { id: "~openai/gpt-mini-latest", name: "OpenAI GPT Mini Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~x-ai/grok-latest": { id: "~x-ai/grok-latest", name: "xAI: Grok Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 5e5, maxTokens: 4096, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } }, "~z-ai/glm-latest": { id: "~z-ai/glm-latest", name: "Z.ai: GLM Latest", api: "openai-completions", baseUrl: "https://openrouter.ai/api/v1", provider: "openrouter", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsDeveloperRole: false, thinkingFormat: "openrouter" } } } };
|
|
14299
14393
|
|
|
14300
14394
|
// ../ai/src/providers/openrouter.models.ts
|
|
14301
14395
|
var OPENROUTER_MODELS = flattenModelCatalog("openrouter", openrouter_default);
|
|
@@ -14713,7 +14807,7 @@ function cloudflareWorkersAIProvider() {
|
|
|
14713
14807
|
}
|
|
14714
14808
|
|
|
14715
14809
|
// ../ai/src/providers/data/.manifest.json
|
|
14716
|
-
var manifest_default = { schemaVersion: 3, generatedAt: "2026-08-
|
|
14810
|
+
var manifest_default = { schemaVersion: 3, generatedAt: "2026-08-24T11:22:29.095Z", structureHash: "5dce9c34b838a5dd1d7f031d30b0d6d06c6d2902a38098885d75f238ba569c7f", files: { "amazon-bedrock.json": "71441520503c82d14c788a16fdbd5314adc5b7b34abd65a3f260b96f493c2e90", "ant-ling.json": "4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633", "anthropic.json": "e22c277e3a1ffddc3d2701b72787c9e0bd67b835de6b4cb806677b6b6a89a2f7", "azure-openai-responses.json": "5315b6a2299fefbdbb6cc13a720544077c9498132ad5e3a7d76a8c1daa8e9335", "baseten.json": "950433e7fcf9357ae3423b27fc0d32568b6e0990bb35c6e961dcb9740a6bba1b", "cerebras.json": "38272a7525d6680c71bb4bb3c4085e871768b400832e2013b0e7fd92f8fd4f05", "cloudflare-ai-gateway.json": "244af2cfdfaf75c4135ce4c7865220057647c2d8744b52af1d55392879df8d28", "cloudflare-workers-ai.json": "89e63a18886ecedd1d995cc90e4bfe06f73e2a79117b2f54f58fe60cdcf63df5", "deepseek.json": "0dcc807a4e5827b488c6ceac87884ff6e735e01cf4f2ddfec9dd812e6fde041b", "fireworks.json": "b587d1ba3380b5785a52f67b8a5eae11c447e667488fb2b6b0865a89c2692e4a", "github-copilot.json": "ed5b1e17f95adba904a2b9c909bb28a8542ba1185467080f9f56b2ea93b0429b", "google-vertex.json": "fb7586fc955da7b7d7d11d641954f496fbbb42cf3e4cbba66d7116ea3b37d5ed", "google.json": "b5572904165d37ab594eafc3ab7f29774e35747b5dd211144ec01532db9217c1", "groq.json": "f1eb899453e70b5e4479fe6eb78869ee99121fa6d4a019a5a05ab42d2ada8992", "huggingface.json": "b2f15353177738beb5c0865ffcd92cc470e1c8ba6b6a4d2707cda12212a6043b", "kimi-coding.json": "ba42a26a69e5cb2122c0b384ba572efae93f42239ad86f26c2b7320a14aa75a1", "minimax-cn.json": "8ccd71ff838f4b78bb88809babb0dc32a4fcfaec2bc4f4083841000428df4f77", "minimax.json": "253edd4c910a41c8bb252400ba099f3a4de0a8900ce154319288ab091b372987", "mistral.json": "4f9d84bf1ba10cb14ff2c9e23e77d63441756ef3500375dd4ad10094614b215b", "moonshotai-cn.json": "1e6146ff3477883636448c0f44222f0a52b3c4562ef8f4eecf7e941cdd59d12e", "moonshotai.json": "d8d5209873058ddccd37c1f026833e2ea3f9476c3dc9628b4a940d407acc0b2e", "nvidia.json": "f9e2737a9d7ccb77ccc14083422dae03e0b786d169660670f739ddb3f0533eb5", "openai-codex.json": "4a73818291987693fcb53e9e61b4be3429ffd78b3f64ea877a34c5f9928c89e1", "openai.json": "60a1af0fd4c407733079283bb485ab1d8d592abf25f13632d83ba40425e11177", "opencode-go.json": "f7b88230cf767cf1ddefd3acf3ad7e377dab9cbeb55d3dad7b6acf7111a801f8", "opencode.json": "2ef1476a30c692a18d52242e955082a1a122a75c709ba4f10749ef762c54531a", "openrouter.json": "6dbbf84366da2ef97af845baebc719e54a063105d920cb3f55684b351c678c9d", "qwen-token-plan-cn.json": "700cb41cdee4c0ae2a5159eb3ab43f4cedc9d43e87c6fd1bcd410d71431f9856", "qwen-token-plan.json": "f85715f7f2023a162c47d1a84ba73747e2580d0a9aa33799b3232ce19527c1ab", "together.json": "f7c9ba0441c1cbb8af41aaea3cfaa12559e1235a7335898e705d5918dc308c97", "vercel-ai-gateway.json": "7857ae0ce938685455f9b570b55cecdfb9b5e8aa82baff4645669d4d8b7ba9e5", "xai.json": "282838b0546d63106c81f1703cdf5ed31ebfe0c5f13a4bec0d590472cbbe03f2", "xiaomi-token-plan-ams.json": "7ce8ed244672c45737d286ff3ca9c3a2686a5d4b2f0c5f71ab9348c14b14daf3", "xiaomi-token-plan-cn.json": "684892b5fe6fa371d6040d2011c0fa33facd650d2eaf19f5dbee8efb33016200", "xiaomi-token-plan-sgp.json": "b19e79b82ac4fdcb080e6d220106797504c885ed70b27fc2b3c1aa4810f32963", "xiaomi.json": "810368d3828c8bb9498012a0d48639030c0c216b8c13e79da02daa515aa23448", "zai-coding-cn.json": "663466fef5cca84909b9929671a48fefb3721c0990c61bbec05d8b1692247310", "zai.json": "fd81b25003c3e653ee319c2ba0ce353a4f02df1a409246c8d0f96d13dd0ec592" } };
|
|
14717
14811
|
|
|
14718
14812
|
// ../ai/src/providers/deepseek.ts
|
|
14719
14813
|
init_models();
|
|
@@ -15643,16 +15737,16 @@ import { homedir } from "node:os";
|
|
|
15643
15737
|
import { isAbsolute, join, resolve as nodeResolvePath, relative, sep } from "node:path";
|
|
15644
15738
|
import { fileURLToPath } from "node:url";
|
|
15645
15739
|
var UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
15646
|
-
function canonicalizePath(
|
|
15740
|
+
function canonicalizePath(path12) {
|
|
15647
15741
|
try {
|
|
15648
|
-
return realpathSync(
|
|
15742
|
+
return realpathSync(path12);
|
|
15649
15743
|
} catch {
|
|
15650
|
-
return
|
|
15744
|
+
return path12;
|
|
15651
15745
|
}
|
|
15652
15746
|
}
|
|
15653
|
-
function getFileRevision(
|
|
15747
|
+
function getFileRevision(path12) {
|
|
15654
15748
|
try {
|
|
15655
|
-
const stats = statSync(
|
|
15749
|
+
const stats = statSync(path12, { bigint: true });
|
|
15656
15750
|
return `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeNs}:${stats.ctimeNs}`;
|
|
15657
15751
|
} catch {
|
|
15658
15752
|
return void 0;
|
|
@@ -15714,13 +15808,13 @@ function formatPathRelativeToCwdOrAbsolute(filePath, cwd) {
|
|
|
15714
15808
|
const absolutePath = resolvePath(filePath, cwd);
|
|
15715
15809
|
return (getCwdRelativePath(absolutePath, cwd) ?? absolutePath).split(sep).join("/");
|
|
15716
15810
|
}
|
|
15717
|
-
function markPathIgnoredByCloudSync(
|
|
15811
|
+
function markPathIgnoredByCloudSync(path12) {
|
|
15718
15812
|
const attrs = process.platform === "darwin" ? ["com.dropbox.ignored", "com.apple.fileprovider.ignore#P"] : process.platform === "linux" ? ["user.com.dropbox.ignored"] : [];
|
|
15719
15813
|
for (const attr of attrs) {
|
|
15720
15814
|
if (process.platform === "darwin") {
|
|
15721
|
-
spawnProcessSync("xattr", ["-w", attr, "1",
|
|
15815
|
+
spawnProcessSync("xattr", ["-w", attr, "1", path12], { encoding: "utf-8", stdio: "ignore" });
|
|
15722
15816
|
} else {
|
|
15723
|
-
spawnProcessSync("setfattr", ["-n", attr, "-v", "1",
|
|
15817
|
+
spawnProcessSync("setfattr", ["-n", attr, "-v", "1", path12], { encoding: "utf-8", stdio: "ignore" });
|
|
15724
15818
|
}
|
|
15725
15819
|
}
|
|
15726
15820
|
}
|
|
@@ -15773,19 +15867,19 @@ function detectInstallMethod() {
|
|
|
15773
15867
|
}
|
|
15774
15868
|
function getInferredNpmInstall() {
|
|
15775
15869
|
const packageDir = getPackageDir();
|
|
15776
|
-
const
|
|
15777
|
-
const parent =
|
|
15870
|
+
const path12 = process.platform === "win32" || packageDir.includes("\\") ? win32 : { basename, dirname };
|
|
15871
|
+
const parent = path12.dirname(packageDir);
|
|
15778
15872
|
let root;
|
|
15779
|
-
if (
|
|
15780
|
-
root =
|
|
15781
|
-
} else if (
|
|
15873
|
+
if (path12.basename(parent).startsWith("@") && path12.basename(path12.dirname(parent)) === "node_modules") {
|
|
15874
|
+
root = path12.dirname(parent);
|
|
15875
|
+
} else if (path12.basename(parent) === "node_modules") {
|
|
15782
15876
|
root = parent;
|
|
15783
15877
|
}
|
|
15784
15878
|
if (!root)
|
|
15785
15879
|
return void 0;
|
|
15786
|
-
const rootParent =
|
|
15787
|
-
if (
|
|
15788
|
-
return { root, prefix:
|
|
15880
|
+
const rootParent = path12.dirname(root);
|
|
15881
|
+
if (path12.basename(rootParent) === "lib")
|
|
15882
|
+
return { root, prefix: path12.dirname(rootParent) };
|
|
15789
15883
|
return void 0;
|
|
15790
15884
|
}
|
|
15791
15885
|
function getSelfUpdateCommandForMethod(method, installedPackageName, updatePackageTarget = installedPackageName, npmCommand) {
|
|
@@ -15892,8 +15986,8 @@ function getGlobalPackageRoots(method, _packageName, npmCommand) {
|
|
|
15892
15986
|
return [];
|
|
15893
15987
|
}
|
|
15894
15988
|
}
|
|
15895
|
-
function normalizeExistingPathForComparison(
|
|
15896
|
-
const resolvedPath = resolve(
|
|
15989
|
+
function normalizeExistingPathForComparison(path12, resolveSymlinks) {
|
|
15990
|
+
const resolvedPath = resolve(path12);
|
|
15897
15991
|
if (!existsSync(resolvedPath)) {
|
|
15898
15992
|
return void 0;
|
|
15899
15993
|
}
|
|
@@ -15910,8 +16004,8 @@ function normalizeExistingPathForComparison(path11, resolveSymlinks) {
|
|
|
15910
16004
|
}
|
|
15911
16005
|
return normalizedPath;
|
|
15912
16006
|
}
|
|
15913
|
-
function getPathComparisonCandidates(
|
|
15914
|
-
return Array.from(new Set([normalizeExistingPathForComparison(
|
|
16007
|
+
function getPathComparisonCandidates(path12) {
|
|
16008
|
+
return Array.from(new Set([normalizeExistingPathForComparison(path12, false), normalizeExistingPathForComparison(path12, true)].filter((candidate) => !!candidate)));
|
|
15915
16009
|
}
|
|
15916
16010
|
function getEntrypointPackageDir() {
|
|
15917
16011
|
const entrypoint = process.argv[1];
|
|
@@ -16055,8 +16149,8 @@ function deleteAppEnv(suffix, env = process.env) {
|
|
|
16055
16149
|
delete env[name];
|
|
16056
16150
|
}
|
|
16057
16151
|
}
|
|
16058
|
-
function expandTildePath(
|
|
16059
|
-
return normalizePath(
|
|
16152
|
+
function expandTildePath(path12) {
|
|
16153
|
+
return normalizePath(path12);
|
|
16060
16154
|
}
|
|
16061
16155
|
function getShareViewerUrl(gistId) {
|
|
16062
16156
|
const baseUrl = readAppEnv("SHARE_VIEWER_URL");
|
|
@@ -16695,15 +16789,15 @@ function parsePathPrefix(prefix) {
|
|
|
16695
16789
|
}
|
|
16696
16790
|
return { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };
|
|
16697
16791
|
}
|
|
16698
|
-
function buildCompletionValue(
|
|
16699
|
-
const needsQuotes = options.isQuotedPrefix ||
|
|
16792
|
+
function buildCompletionValue(path12, options) {
|
|
16793
|
+
const needsQuotes = options.isQuotedPrefix || path12.includes(" ");
|
|
16700
16794
|
const prefix = options.isAtPrefix ? "@" : "";
|
|
16701
16795
|
if (!needsQuotes) {
|
|
16702
|
-
return `${prefix}${
|
|
16796
|
+
return `${prefix}${path12}`;
|
|
16703
16797
|
}
|
|
16704
16798
|
const openQuote = `${prefix}"`;
|
|
16705
16799
|
const closeQuote = '"';
|
|
16706
|
-
return `${openQuote}${
|
|
16800
|
+
return `${openQuote}${path12}${closeQuote}`;
|
|
16707
16801
|
}
|
|
16708
16802
|
async function walkDirectoryWithFd(baseDir, fdPath, query, maxResults, signal) {
|
|
16709
16803
|
const args = [
|
|
@@ -16952,14 +17046,14 @@ var CombinedAutocompleteProvider = class {
|
|
|
16952
17046
|
return null;
|
|
16953
17047
|
}
|
|
16954
17048
|
// Expand home directory (~/) to actual home path
|
|
16955
|
-
expandHomePath(
|
|
16956
|
-
if (
|
|
16957
|
-
const expandedPath = join3(homedir3(),
|
|
16958
|
-
return
|
|
16959
|
-
} else if (
|
|
17049
|
+
expandHomePath(path12) {
|
|
17050
|
+
if (path12.startsWith("~/")) {
|
|
17051
|
+
const expandedPath = join3(homedir3(), path12.slice(2));
|
|
17052
|
+
return path12.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
|
|
17053
|
+
} else if (path12 === "~") {
|
|
16960
17054
|
return homedir3();
|
|
16961
17055
|
}
|
|
16962
|
-
return
|
|
17056
|
+
return path12;
|
|
16963
17057
|
}
|
|
16964
17058
|
resolveScopedFuzzyQuery(rawQuery) {
|
|
16965
17059
|
const normalizedQuery = toDisplayPath(rawQuery);
|
|
@@ -27751,9 +27845,9 @@ function closeWatcher(watcher) {
|
|
|
27751
27845
|
} catch {
|
|
27752
27846
|
}
|
|
27753
27847
|
}
|
|
27754
|
-
function watchWithErrorHandler(
|
|
27848
|
+
function watchWithErrorHandler(path12, listener, onError) {
|
|
27755
27849
|
try {
|
|
27756
|
-
const watcher = watch(
|
|
27850
|
+
const watcher = watch(path12, listener);
|
|
27757
27851
|
watcher.on("error", onError);
|
|
27758
27852
|
return watcher;
|
|
27759
27853
|
} catch {
|
|
@@ -28321,8 +28415,8 @@ function parseThemeJson(label, json) {
|
|
|
28321
28415
|
}
|
|
28322
28416
|
continue;
|
|
28323
28417
|
}
|
|
28324
|
-
const
|
|
28325
|
-
otherErrors.push(` - ${
|
|
28418
|
+
const path12 = error.instancePath || "/";
|
|
28419
|
+
otherErrors.push(` - ${path12}: ${error.message}`);
|
|
28326
28420
|
}
|
|
28327
28421
|
let errorMessage = `Invalid theme "${label}":
|
|
28328
28422
|
`;
|
|
@@ -29631,8 +29725,8 @@ function stripAnsi(value) {
|
|
|
29631
29725
|
import { existsSync as existsSync4 } from "node:fs";
|
|
29632
29726
|
import { delimiter } from "node:path";
|
|
29633
29727
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
29634
|
-
function isLegacyWslBashPath(
|
|
29635
|
-
const normalized =
|
|
29728
|
+
function isLegacyWslBashPath(path12) {
|
|
29729
|
+
const normalized = path12.replace(/\//g, "\\").toLowerCase();
|
|
29636
29730
|
return /^[a-z]:\\windows\\(?:system32|sysnative)\\bash\.exe$/.test(normalized);
|
|
29637
29731
|
}
|
|
29638
29732
|
function getBashShellConfig(shell) {
|
|
@@ -29685,9 +29779,9 @@ function getShellConfig(customShellPath) {
|
|
|
29685
29779
|
if (programFilesX86) {
|
|
29686
29780
|
paths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
|
|
29687
29781
|
}
|
|
29688
|
-
for (const
|
|
29689
|
-
if (existsSync4(
|
|
29690
|
-
return getBashShellConfig(
|
|
29782
|
+
for (const path12 of paths) {
|
|
29783
|
+
if (existsSync4(path12)) {
|
|
29784
|
+
return getBashShellConfig(path12);
|
|
29691
29785
|
}
|
|
29692
29786
|
}
|
|
29693
29787
|
const bashOnPath2 = findBashOnPath();
|
|
@@ -30253,19 +30347,19 @@ function buildSessionPath(entries, leafId, byId) {
|
|
|
30253
30347
|
if (!leaf) {
|
|
30254
30348
|
return [];
|
|
30255
30349
|
}
|
|
30256
|
-
const
|
|
30350
|
+
const path12 = [];
|
|
30257
30351
|
let current = leaf;
|
|
30258
30352
|
while (current) {
|
|
30259
|
-
|
|
30353
|
+
path12.push(current);
|
|
30260
30354
|
current = current.parentId ? index.get(current.parentId) : void 0;
|
|
30261
30355
|
}
|
|
30262
|
-
|
|
30263
|
-
return
|
|
30356
|
+
path12.reverse();
|
|
30357
|
+
return path12;
|
|
30264
30358
|
}
|
|
30265
|
-
function getSessionContextSettings(
|
|
30359
|
+
function getSessionContextSettings(path12) {
|
|
30266
30360
|
let thinkingLevel = "off";
|
|
30267
30361
|
let model = null;
|
|
30268
|
-
for (const entry of
|
|
30362
|
+
for (const entry of path12) {
|
|
30269
30363
|
if (entry.type === "thinking_level_change") {
|
|
30270
30364
|
thinkingLevel = entry.thinkingLevel;
|
|
30271
30365
|
} else if (entry.type === "model_change") {
|
|
@@ -30298,24 +30392,24 @@ function sessionEntryToContextMessages(entry) {
|
|
|
30298
30392
|
return [];
|
|
30299
30393
|
}
|
|
30300
30394
|
function buildContextEntries(entries, leafId, byId) {
|
|
30301
|
-
const
|
|
30395
|
+
const path12 = buildSessionPath(entries, leafId, byId);
|
|
30302
30396
|
let compaction = null;
|
|
30303
|
-
for (const entry of
|
|
30397
|
+
for (const entry of path12) {
|
|
30304
30398
|
if (entry.type === "compaction") {
|
|
30305
30399
|
compaction = entry;
|
|
30306
30400
|
}
|
|
30307
30401
|
}
|
|
30308
30402
|
if (!compaction) {
|
|
30309
|
-
return
|
|
30403
|
+
return path12;
|
|
30310
30404
|
}
|
|
30311
|
-
const compactionIdx =
|
|
30405
|
+
const compactionIdx = path12.findIndex((entry) => entry.id === compaction.id);
|
|
30312
30406
|
if (compactionIdx < 0) {
|
|
30313
|
-
return
|
|
30407
|
+
return path12;
|
|
30314
30408
|
}
|
|
30315
30409
|
const contextEntries = [compaction];
|
|
30316
30410
|
let foundFirstKept = false;
|
|
30317
30411
|
for (let i = 0; i < compactionIdx; i++) {
|
|
30318
|
-
const entry =
|
|
30412
|
+
const entry = path12[i];
|
|
30319
30413
|
if (entry.id === compaction.firstKeptEntryId) {
|
|
30320
30414
|
foundFirstKept = true;
|
|
30321
30415
|
}
|
|
@@ -30323,12 +30417,12 @@ function buildContextEntries(entries, leafId, byId) {
|
|
|
30323
30417
|
contextEntries.push(entry);
|
|
30324
30418
|
}
|
|
30325
30419
|
}
|
|
30326
|
-
contextEntries.push(...
|
|
30420
|
+
contextEntries.push(...path12.slice(compactionIdx + 1));
|
|
30327
30421
|
return contextEntries;
|
|
30328
30422
|
}
|
|
30329
30423
|
function buildSessionContext(entries, leafId, byId) {
|
|
30330
|
-
const
|
|
30331
|
-
const { thinkingLevel, model } = getSessionContextSettings(
|
|
30424
|
+
const path12 = buildSessionPath(entries, leafId, byId);
|
|
30425
|
+
const { thinkingLevel, model } = getSessionContextSettings(path12);
|
|
30332
30426
|
const messages = buildContextEntries(entries, leafId, byId).flatMap(sessionEntryToContextMessages);
|
|
30333
30427
|
return { messages, thinkingLevel, model };
|
|
30334
30428
|
}
|
|
@@ -30471,7 +30565,7 @@ function findMostRecentSession(sessionDir, cwd) {
|
|
|
30471
30565
|
const resolvedSessionDir = normalizePath(sessionDir);
|
|
30472
30566
|
const resolvedCwd = cwd ? resolvePath(cwd) : void 0;
|
|
30473
30567
|
try {
|
|
30474
|
-
const files = readdirSync3(resolvedSessionDir).filter((f) => f.endsWith(".jsonl")).map((f) => join13(resolvedSessionDir, f)).map((
|
|
30568
|
+
const files = readdirSync3(resolvedSessionDir).filter((f) => f.endsWith(".jsonl")).map((f) => join13(resolvedSessionDir, f)).map((path12) => ({ path: path12, header: readSessionHeaderForDiscovery(path12) })).filter((file) => file.header !== null && (!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd))).map(({ path: path12 }) => ({ path: path12, mtime: statSync4(path12).mtime })).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
30475
30569
|
return files[0]?.path || null;
|
|
30476
30570
|
} catch {
|
|
30477
30571
|
return null;
|
|
@@ -30973,15 +31067,15 @@ var SessionManager = class _SessionManager {
|
|
|
30973
31067
|
* Use buildSessionContext() to get the resolved messages for the LLM.
|
|
30974
31068
|
*/
|
|
30975
31069
|
getBranch(fromId) {
|
|
30976
|
-
const
|
|
31070
|
+
const path12 = [];
|
|
30977
31071
|
const startId = fromId ?? this.leafId;
|
|
30978
31072
|
let current = startId ? this.byId.get(startId) : void 0;
|
|
30979
31073
|
while (current) {
|
|
30980
|
-
|
|
31074
|
+
path12.push(current);
|
|
30981
31075
|
current = current.parentId ? this.byId.get(current.parentId) : void 0;
|
|
30982
31076
|
}
|
|
30983
|
-
|
|
30984
|
-
return
|
|
31077
|
+
path12.reverse();
|
|
31078
|
+
return path12;
|
|
30985
31079
|
}
|
|
30986
31080
|
/**
|
|
30987
31081
|
* Build the active, compaction-aware entry list for context/rendering.
|
|
@@ -31101,13 +31195,13 @@ var SessionManager = class _SessionManager {
|
|
|
31101
31195
|
*/
|
|
31102
31196
|
createBranchedSession(leafId) {
|
|
31103
31197
|
const previousSessionFile = this.sessionFile;
|
|
31104
|
-
const
|
|
31105
|
-
if (
|
|
31198
|
+
const path12 = this.getBranch(leafId);
|
|
31199
|
+
if (path12.length === 0) {
|
|
31106
31200
|
throw new Error(`Entry ${leafId} not found`);
|
|
31107
31201
|
}
|
|
31108
31202
|
const pathWithoutLabels = [];
|
|
31109
31203
|
let pathParentId = null;
|
|
31110
|
-
for (const entry of
|
|
31204
|
+
for (const entry of path12) {
|
|
31111
31205
|
if (entry.type === "label")
|
|
31112
31206
|
continue;
|
|
31113
31207
|
pathWithoutLabels.push({ ...entry, parentId: pathParentId });
|
|
@@ -31196,8 +31290,8 @@ var SessionManager = class _SessionManager {
|
|
|
31196
31290
|
* @param sessionDir Optional session directory for /new or /branch. If omitted, derives from file's parent.
|
|
31197
31291
|
* @param cwdOverride Optional cwd override instead of the session header cwd.
|
|
31198
31292
|
*/
|
|
31199
|
-
static open(
|
|
31200
|
-
const resolvedPath = resolvePath(
|
|
31293
|
+
static open(path12, sessionDir, cwdOverride) {
|
|
31294
|
+
const resolvedPath = resolvePath(path12);
|
|
31201
31295
|
let header = null;
|
|
31202
31296
|
let preloadedFileEntries;
|
|
31203
31297
|
if (cwdOverride === void 0 && existsSync5(resolvedPath)) {
|
|
@@ -31363,18 +31457,18 @@ function extractFileOpsFromMessage(message, fileOps) {
|
|
|
31363
31457
|
const args = block.arguments;
|
|
31364
31458
|
if (!args)
|
|
31365
31459
|
continue;
|
|
31366
|
-
const
|
|
31367
|
-
if (!
|
|
31460
|
+
const path12 = typeof args.path === "string" ? args.path : void 0;
|
|
31461
|
+
if (!path12)
|
|
31368
31462
|
continue;
|
|
31369
31463
|
switch (block.name) {
|
|
31370
31464
|
case "read":
|
|
31371
|
-
fileOps.read.add(
|
|
31465
|
+
fileOps.read.add(path12);
|
|
31372
31466
|
break;
|
|
31373
31467
|
case "write":
|
|
31374
|
-
fileOps.written.add(
|
|
31468
|
+
fileOps.written.add(path12);
|
|
31375
31469
|
break;
|
|
31376
31470
|
case "edit":
|
|
31377
|
-
fileOps.edited.add(
|
|
31471
|
+
fileOps.edited.add(path12);
|
|
31378
31472
|
break;
|
|
31379
31473
|
}
|
|
31380
31474
|
}
|
|
@@ -34346,8 +34440,8 @@ function fileResult(result, message) {
|
|
|
34346
34440
|
}
|
|
34347
34441
|
return result.value;
|
|
34348
34442
|
}
|
|
34349
|
-
function invalidFile(
|
|
34350
|
-
return new SessionError("invalid_entry", `Invalid JSONL v4 session ${
|
|
34443
|
+
function invalidFile(path12, line, message, cause) {
|
|
34444
|
+
return new SessionError("invalid_entry", `Invalid JSONL v4 session ${path12}: line ${line} ${message}`, cause);
|
|
34351
34445
|
}
|
|
34352
34446
|
|
|
34353
34447
|
// ../agent/src/harness/session/jsonl/codec.ts
|
|
@@ -34375,58 +34469,58 @@ var OPERATION_KINDS = /* @__PURE__ */ new Set(["run", "compaction", "navigation"
|
|
|
34375
34469
|
function isObject(value) {
|
|
34376
34470
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34377
34471
|
}
|
|
34378
|
-
function parseObject(line,
|
|
34472
|
+
function parseObject(line, path12, lineNumber) {
|
|
34379
34473
|
let value;
|
|
34380
34474
|
try {
|
|
34381
34475
|
value = JSON.parse(line);
|
|
34382
34476
|
} catch (error) {
|
|
34383
|
-
throw invalidFile(
|
|
34477
|
+
throw invalidFile(path12, lineNumber, "is not valid JSON", error instanceof Error ? error : void 0);
|
|
34384
34478
|
}
|
|
34385
|
-
if (!isObject(value)) throw invalidFile(
|
|
34479
|
+
if (!isObject(value)) throw invalidFile(path12, lineNumber, "is not a JSON object");
|
|
34386
34480
|
return value;
|
|
34387
34481
|
}
|
|
34388
|
-
function requireString(value,
|
|
34389
|
-
if (typeof value !== "string") throw invalidFile(
|
|
34482
|
+
function requireString(value, path12, line, field) {
|
|
34483
|
+
if (typeof value !== "string") throw invalidFile(path12, line, `has invalid ${field}`);
|
|
34390
34484
|
return value;
|
|
34391
34485
|
}
|
|
34392
|
-
function requireSequence(value,
|
|
34393
|
-
if (!Number.isSafeInteger(value) || value <= 0) throw invalidFile(
|
|
34486
|
+
function requireSequence(value, path12, line) {
|
|
34487
|
+
if (!Number.isSafeInteger(value) || value <= 0) throw invalidFile(path12, line, "has invalid seq");
|
|
34394
34488
|
return value;
|
|
34395
34489
|
}
|
|
34396
|
-
function requireTimestamp(value,
|
|
34397
|
-
if (!Number.isSafeInteger(value) || value < 0) throw invalidFile(
|
|
34490
|
+
function requireTimestamp(value, path12, line) {
|
|
34491
|
+
if (!Number.isSafeInteger(value) || value < 0) throw invalidFile(path12, line, "has invalid timestamp");
|
|
34398
34492
|
return value;
|
|
34399
34493
|
}
|
|
34400
|
-
function requireNullableId(value,
|
|
34494
|
+
function requireNullableId(value, path12, line, field) {
|
|
34401
34495
|
if (value !== null && typeof value !== "string") {
|
|
34402
|
-
throw invalidFile(
|
|
34496
|
+
throw invalidFile(path12, line, `has invalid ${field}`);
|
|
34403
34497
|
}
|
|
34404
34498
|
return value;
|
|
34405
34499
|
}
|
|
34406
|
-
function parseHeader(line,
|
|
34407
|
-
const value = parseObject(line,
|
|
34408
|
-
if (value.kind !== "header") throw invalidFile(
|
|
34409
|
-
if (value.version !== 4) throw invalidFile(
|
|
34500
|
+
function parseHeader(line, path12) {
|
|
34501
|
+
const value = parseObject(line, path12, 1);
|
|
34502
|
+
if (value.kind !== "header") throw invalidFile(path12, 1, "is not a header");
|
|
34503
|
+
if (value.version !== 4) throw invalidFile(path12, 1, "has unsupported session version");
|
|
34410
34504
|
const parentSessionId = value.parentSessionId;
|
|
34411
34505
|
if (parentSessionId !== void 0 && typeof parentSessionId !== "string") {
|
|
34412
|
-
throw invalidFile(
|
|
34506
|
+
throw invalidFile(path12, 1, "has invalid parentSessionId");
|
|
34413
34507
|
}
|
|
34414
34508
|
const legacyParentSessionPath = value.legacyParentSessionPath;
|
|
34415
34509
|
if (legacyParentSessionPath !== void 0 && typeof legacyParentSessionPath !== "string") {
|
|
34416
|
-
throw invalidFile(
|
|
34510
|
+
throw invalidFile(path12, 1, "has invalid legacyParentSessionPath");
|
|
34417
34511
|
}
|
|
34418
34512
|
if (parentSessionId !== void 0 && legacyParentSessionPath !== void 0) {
|
|
34419
|
-
throw invalidFile(
|
|
34513
|
+
throw invalidFile(path12, 1, "has both parentSessionId and legacyParentSessionPath");
|
|
34420
34514
|
}
|
|
34421
34515
|
const metadataValue = value.metadata;
|
|
34422
|
-
if (metadataValue !== void 0 && !isObject(metadataValue)) throw invalidFile(
|
|
34516
|
+
if (metadataValue !== void 0 && !isObject(metadataValue)) throw invalidFile(path12, 1, "has invalid metadata");
|
|
34423
34517
|
const metadata = metadataValue;
|
|
34424
34518
|
return {
|
|
34425
34519
|
kind: "header",
|
|
34426
34520
|
version: 4,
|
|
34427
|
-
id: requireString(value.id,
|
|
34428
|
-
createdAt: requireTimestamp(value.createdAt,
|
|
34429
|
-
cwd: requireString(value.cwd,
|
|
34521
|
+
id: requireString(value.id, path12, 1, "id"),
|
|
34522
|
+
createdAt: requireTimestamp(value.createdAt, path12, 1),
|
|
34523
|
+
cwd: requireString(value.cwd, path12, 1, "cwd"),
|
|
34430
34524
|
parentSessionId,
|
|
34431
34525
|
legacyParentSessionPath,
|
|
34432
34526
|
metadata
|
|
@@ -34436,12 +34530,12 @@ function encodeHeader(header) {
|
|
|
34436
34530
|
return `${JSON.stringify(header)}
|
|
34437
34531
|
`;
|
|
34438
34532
|
}
|
|
34439
|
-
function metadataFromHeader(header,
|
|
34533
|
+
function metadataFromHeader(header, path12, modifiedAt) {
|
|
34440
34534
|
return {
|
|
34441
34535
|
id: header.id,
|
|
34442
34536
|
createdAt: header.createdAt,
|
|
34443
34537
|
cwd: header.cwd,
|
|
34444
|
-
path:
|
|
34538
|
+
path: path12,
|
|
34445
34539
|
modifiedAt,
|
|
34446
34540
|
sourceFormat: 4,
|
|
34447
34541
|
...header.parentSessionId === void 0 ? {} : { parentSessionId: header.parentSessionId },
|
|
@@ -34449,38 +34543,38 @@ function metadataFromHeader(header, path11, modifiedAt) {
|
|
|
34449
34543
|
...header.metadata === void 0 ? {} : { metadata: header.metadata }
|
|
34450
34544
|
};
|
|
34451
34545
|
}
|
|
34452
|
-
function parseMutation(line,
|
|
34453
|
-
const value = parseObject(line,
|
|
34454
|
-
const seq = requireSequence(value.seq,
|
|
34546
|
+
function parseMutation(line, path12, lineNumber) {
|
|
34547
|
+
const value = parseObject(line, path12, lineNumber);
|
|
34548
|
+
const seq = requireSequence(value.seq, path12, lineNumber);
|
|
34455
34549
|
switch (value.kind) {
|
|
34456
34550
|
case "entry": {
|
|
34457
|
-
const lane = value.lane === void 0 ? void 0 : requireString(value.lane,
|
|
34458
|
-
const id = requireString(value.id,
|
|
34459
|
-
const type = requireString(value.type,
|
|
34551
|
+
const lane = value.lane === void 0 ? void 0 : requireString(value.lane, path12, lineNumber, "lane");
|
|
34552
|
+
const id = requireString(value.id, path12, lineNumber, "id");
|
|
34553
|
+
const type = requireString(value.type, path12, lineNumber, "entry type");
|
|
34460
34554
|
if (!ENTRY_TYPES.has(type))
|
|
34461
|
-
throw invalidFile(
|
|
34462
|
-
const parentId = requireNullableId(value.parentId,
|
|
34463
|
-
const timestamp = requireTimestamp(value.timestamp,
|
|
34464
|
-
if (type === "custom") requireString(value.customType,
|
|
34555
|
+
throw invalidFile(path12, lineNumber, `has unknown entry type ${type}`);
|
|
34556
|
+
const parentId = requireNullableId(value.parentId, path12, lineNumber, "parentId");
|
|
34557
|
+
const timestamp = requireTimestamp(value.timestamp, path12, lineNumber);
|
|
34558
|
+
if (type === "custom") requireString(value.customType, path12, lineNumber, "customType");
|
|
34465
34559
|
const { kind: _kind, lane: _lane, ...entryFields } = value;
|
|
34466
34560
|
const entry = { ...entryFields, id, type, parentId, seq, timestamp };
|
|
34467
34561
|
return lane === void 0 ? { kind: "entry", entry } : { kind: "entry", lane, entry };
|
|
34468
34562
|
}
|
|
34469
34563
|
case "record": {
|
|
34470
|
-
const id = requireString(value.id,
|
|
34471
|
-
const lane = requireString(value.lane,
|
|
34472
|
-
const type = requireString(value.type,
|
|
34564
|
+
const id = requireString(value.id, path12, lineNumber, "id");
|
|
34565
|
+
const lane = requireString(value.lane, path12, lineNumber, "lane");
|
|
34566
|
+
const type = requireString(value.type, path12, lineNumber, "record type");
|
|
34473
34567
|
if (!RECORD_TYPES.has(type))
|
|
34474
|
-
throw invalidFile(
|
|
34475
|
-
const timestamp = requireTimestamp(value.timestamp,
|
|
34568
|
+
throw invalidFile(path12, lineNumber, `has unknown record type ${type}`);
|
|
34569
|
+
const timestamp = requireTimestamp(value.timestamp, path12, lineNumber);
|
|
34476
34570
|
if (type === "operation_started") {
|
|
34477
|
-
if (!isObject(value.intent)) throw invalidFile(
|
|
34478
|
-
const operationKind = requireString(value.intent.kind,
|
|
34571
|
+
if (!isObject(value.intent)) throw invalidFile(path12, lineNumber, "has invalid intent");
|
|
34572
|
+
const operationKind = requireString(value.intent.kind, path12, lineNumber, "operation kind");
|
|
34479
34573
|
if (!OPERATION_KINDS.has(operationKind)) {
|
|
34480
|
-
throw invalidFile(
|
|
34574
|
+
throw invalidFile(path12, lineNumber, `has unknown operation kind ${operationKind}`);
|
|
34481
34575
|
}
|
|
34482
34576
|
}
|
|
34483
|
-
if (type === "operation_finished") requireString(value.runId,
|
|
34577
|
+
if (type === "operation_finished") requireString(value.runId, path12, lineNumber, "runId");
|
|
34484
34578
|
const { kind: _kind, ...recordFields } = value;
|
|
34485
34579
|
return {
|
|
34486
34580
|
kind: "record",
|
|
@@ -34491,28 +34585,28 @@ function parseMutation(line, path11, lineNumber) {
|
|
|
34491
34585
|
return {
|
|
34492
34586
|
kind: "lane",
|
|
34493
34587
|
seq,
|
|
34494
|
-
lane: requireString(value.lane,
|
|
34495
|
-
leafId: requireNullableId(value.leafId,
|
|
34588
|
+
lane: requireString(value.lane, path12, lineNumber, "lane"),
|
|
34589
|
+
leafId: requireNullableId(value.leafId, path12, lineNumber, "leafId")
|
|
34496
34590
|
};
|
|
34497
34591
|
case "fact":
|
|
34498
34592
|
if (value.fact === "name") {
|
|
34499
|
-
return { kind: "fact", seq, fact: "name", name: requireString(value.name,
|
|
34593
|
+
return { kind: "fact", seq, fact: "name", name: requireString(value.name, path12, lineNumber, "name") };
|
|
34500
34594
|
}
|
|
34501
34595
|
if (value.fact === "label") {
|
|
34502
34596
|
if (value.label !== void 0 && typeof value.label !== "string") {
|
|
34503
|
-
throw invalidFile(
|
|
34597
|
+
throw invalidFile(path12, lineNumber, "has invalid label");
|
|
34504
34598
|
}
|
|
34505
34599
|
return {
|
|
34506
34600
|
kind: "fact",
|
|
34507
34601
|
seq,
|
|
34508
34602
|
fact: "label",
|
|
34509
|
-
targetId: requireString(value.targetId,
|
|
34603
|
+
targetId: requireString(value.targetId, path12, lineNumber, "targetId"),
|
|
34510
34604
|
label: value.label
|
|
34511
34605
|
};
|
|
34512
34606
|
}
|
|
34513
|
-
throw invalidFile(
|
|
34607
|
+
throw invalidFile(path12, lineNumber, "has unknown fact type");
|
|
34514
34608
|
default:
|
|
34515
|
-
throw invalidFile(
|
|
34609
|
+
throw invalidFile(path12, lineNumber, "has unknown mutation kind");
|
|
34516
34610
|
}
|
|
34517
34611
|
}
|
|
34518
34612
|
function encodeMutation(mutation) {
|
|
@@ -34768,37 +34862,37 @@ var SessionState = class {
|
|
|
34768
34862
|
|
|
34769
34863
|
// ../agent/src/harness/session/jsonl/storage.ts
|
|
34770
34864
|
var JsonlSessionStorage = class _JsonlSessionStorage {
|
|
34771
|
-
constructor(
|
|
34865
|
+
constructor(fs8, metadata) {
|
|
34772
34866
|
this.state = new SessionState();
|
|
34773
34867
|
this.tail = Promise.resolve();
|
|
34774
|
-
this.fs =
|
|
34868
|
+
this.fs = fs8;
|
|
34775
34869
|
this.metadata = structuredClone(metadata);
|
|
34776
34870
|
}
|
|
34777
|
-
static async load(
|
|
34778
|
-
const content = fileResult(await
|
|
34871
|
+
static async load(fs8, path12) {
|
|
34872
|
+
const content = fileResult(await fs8.readTextFile(path12), `Failed to read session ${path12}`);
|
|
34779
34873
|
const physicalLines = content.split("\n");
|
|
34780
34874
|
if (physicalLines.at(-1) === "") physicalLines.pop();
|
|
34781
|
-
if (physicalLines.length === 0 || !physicalLines[0]) throw invalidFile(
|
|
34782
|
-
const header = parseHeader(physicalLines[0],
|
|
34783
|
-
const fileInfo = fileResult(await
|
|
34784
|
-
const storage = new _JsonlSessionStorage(
|
|
34875
|
+
if (physicalLines.length === 0 || !physicalLines[0]) throw invalidFile(path12, 1, "is missing a header");
|
|
34876
|
+
const header = parseHeader(physicalLines[0], path12);
|
|
34877
|
+
const fileInfo = fileResult(await fs8.fileInfo(path12), `Failed to read session metadata ${path12}`);
|
|
34878
|
+
const storage = new _JsonlSessionStorage(fs8, metadataFromHeader(header, path12, fileInfo.mtimeMs));
|
|
34785
34879
|
for (let index = 1; index < physicalLines.length; index++) {
|
|
34786
34880
|
const line = physicalLines[index];
|
|
34787
34881
|
let mutation;
|
|
34788
34882
|
try {
|
|
34789
|
-
mutation = parseMutation(line,
|
|
34883
|
+
mutation = parseMutation(line, path12, index + 1);
|
|
34790
34884
|
} catch (error) {
|
|
34791
34885
|
if (index !== physicalLines.length - 1 || !(error instanceof SessionError) || error.cause === void 0)
|
|
34792
34886
|
throw error;
|
|
34793
34887
|
const validPrefix = `${physicalLines.slice(0, index).join("\n")}
|
|
34794
34888
|
`;
|
|
34795
|
-
fileResult(await
|
|
34889
|
+
fileResult(await fs8.writeFile(path12, validPrefix), `Failed to truncate torn session tail ${path12}`);
|
|
34796
34890
|
return storage;
|
|
34797
34891
|
}
|
|
34798
|
-
storage.applyMutation(mutation,
|
|
34892
|
+
storage.applyMutation(mutation, path12, index + 1);
|
|
34799
34893
|
}
|
|
34800
34894
|
if (!content.endsWith("\n")) {
|
|
34801
|
-
fileResult(await
|
|
34895
|
+
fileResult(await fs8.appendFile(path12, "\n"), `Failed to repair unterminated session tail ${path12}`);
|
|
34802
34896
|
}
|
|
34803
34897
|
return storage;
|
|
34804
34898
|
}
|
|
@@ -34949,9 +35043,9 @@ var JsonlSessionStorage = class _JsonlSessionStorage {
|
|
|
34949
35043
|
`Failed to append session ${this.metadata.path}`
|
|
34950
35044
|
);
|
|
34951
35045
|
}
|
|
34952
|
-
applyMutation(mutation,
|
|
35046
|
+
applyMutation(mutation, path12 = this.metadata.path, line = this.state.nextSequence + 1) {
|
|
34953
35047
|
this.state.applyMutation(mutation, (message) => {
|
|
34954
|
-
throw invalidFile(
|
|
35048
|
+
throw invalidFile(path12, line, message);
|
|
34955
35049
|
});
|
|
34956
35050
|
}
|
|
34957
35051
|
};
|
|
@@ -35045,7 +35139,7 @@ var JsonlSessionRepo = class {
|
|
|
35045
35139
|
const cwd = fileResult(await this.fs.absolutePath(options.cwd), `Failed to resolve session cwd ${options.cwd}`);
|
|
35046
35140
|
const createdAt = Date.now();
|
|
35047
35141
|
const sessionDirectory = await this.sessionDirectory(cwd);
|
|
35048
|
-
const
|
|
35142
|
+
const path12 = fileResult(
|
|
35049
35143
|
await this.fs.joinPath([sessionDirectory, sessionFileName(createdAt, id)]),
|
|
35050
35144
|
`Failed to resolve path for session ${id}`
|
|
35051
35145
|
);
|
|
@@ -35060,9 +35154,9 @@ var JsonlSessionRepo = class {
|
|
|
35060
35154
|
metadata: options.metadata
|
|
35061
35155
|
};
|
|
35062
35156
|
fileResult(await this.fs.createDir(sessionDirectory, { recursive: true }), `Failed to create sessions directory`);
|
|
35063
|
-
fileResult(await this.fs.writeFile(
|
|
35064
|
-
const fileInfo = fileResult(await this.fs.fileInfo(
|
|
35065
|
-
const storage = new JsonlSessionStorage(this.fs, metadataFromHeader(header,
|
|
35157
|
+
fileResult(await this.fs.writeFile(path12, encodeHeader(header)), `Failed to create session ${path12}`);
|
|
35158
|
+
const fileInfo = fileResult(await this.fs.fileInfo(path12), `Failed to read session metadata ${path12}`);
|
|
35159
|
+
const storage = new JsonlSessionStorage(this.fs, metadataFromHeader(header, path12, fileInfo.mtimeMs));
|
|
35066
35160
|
return { session: new Session(storage), storage };
|
|
35067
35161
|
}
|
|
35068
35162
|
async listDirect(options) {
|
|
@@ -35325,11 +35419,11 @@ function toError(error) {
|
|
|
35325
35419
|
}
|
|
35326
35420
|
}
|
|
35327
35421
|
var FileError = class extends Error {
|
|
35328
|
-
constructor(code, message,
|
|
35422
|
+
constructor(code, message, path12, cause) {
|
|
35329
35423
|
super(message, cause === void 0 ? void 0 : { cause });
|
|
35330
35424
|
this.name = "FileError";
|
|
35331
35425
|
this.code = code;
|
|
35332
|
-
this.path =
|
|
35426
|
+
this.path = path12;
|
|
35333
35427
|
}
|
|
35334
35428
|
};
|
|
35335
35429
|
var ExecutionError = class extends Error {
|
|
@@ -35371,17 +35465,17 @@ function extractFileOpsFromMessage2(message, fileOps) {
|
|
|
35371
35465
|
if (!("arguments" in block) || !("name" in block)) continue;
|
|
35372
35466
|
const args = block.arguments;
|
|
35373
35467
|
if (!args) continue;
|
|
35374
|
-
const
|
|
35375
|
-
if (!
|
|
35468
|
+
const path12 = typeof args.path === "string" ? args.path : void 0;
|
|
35469
|
+
if (!path12) continue;
|
|
35376
35470
|
switch (block.name) {
|
|
35377
35471
|
case "read":
|
|
35378
|
-
fileOps.read.add(
|
|
35472
|
+
fileOps.read.add(path12);
|
|
35379
35473
|
break;
|
|
35380
35474
|
case "write":
|
|
35381
|
-
fileOps.written.add(
|
|
35475
|
+
fileOps.written.add(path12);
|
|
35382
35476
|
break;
|
|
35383
35477
|
case "edit":
|
|
35384
|
-
fileOps.edited.add(
|
|
35478
|
+
fileOps.edited.add(path12);
|
|
35385
35479
|
break;
|
|
35386
35480
|
}
|
|
35387
35481
|
}
|
|
@@ -36277,15 +36371,15 @@ import { parse as parse2 } from "yaml";
|
|
|
36277
36371
|
async function loadPromptTemplates(env, paths) {
|
|
36278
36372
|
const promptTemplates = [];
|
|
36279
36373
|
const diagnostics = [];
|
|
36280
|
-
for (const
|
|
36281
|
-
const infoResult = await env.fileInfo(
|
|
36374
|
+
for (const path12 of Array.isArray(paths) ? paths : [paths]) {
|
|
36375
|
+
const infoResult = await env.fileInfo(path12);
|
|
36282
36376
|
if (!infoResult.ok) {
|
|
36283
36377
|
if (infoResult.error.code !== "not_found") {
|
|
36284
36378
|
diagnostics.push({
|
|
36285
36379
|
type: "warning",
|
|
36286
36380
|
code: "file_info_failed",
|
|
36287
36381
|
message: infoResult.error.message,
|
|
36288
|
-
path:
|
|
36382
|
+
path: path12
|
|
36289
36383
|
});
|
|
36290
36384
|
}
|
|
36291
36385
|
continue;
|
|
@@ -36759,15 +36853,15 @@ async function resolveKind2(env, info, diagnostics) {
|
|
|
36759
36853
|
}
|
|
36760
36854
|
return target.value.kind === "file" || target.value.kind === "directory" ? target.value.kind : void 0;
|
|
36761
36855
|
}
|
|
36762
|
-
function dirnameEnvPath(
|
|
36763
|
-
const normalized =
|
|
36856
|
+
function dirnameEnvPath(path12) {
|
|
36857
|
+
const normalized = path12.replace(/[\\/]+$/, "");
|
|
36764
36858
|
const separatorIndex = Math.max(normalized.lastIndexOf("/"), normalized.lastIndexOf("\\"));
|
|
36765
36859
|
if (separatorIndex === 2 && normalized[1] === ":") return normalized.slice(0, 3);
|
|
36766
36860
|
return separatorIndex <= 0 ? "/" : normalized.slice(0, separatorIndex);
|
|
36767
36861
|
}
|
|
36768
|
-
function relativeEnvPath(root,
|
|
36862
|
+
function relativeEnvPath(root, path12) {
|
|
36769
36863
|
const normalizedRoot = root.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
36770
|
-
const normalizedPath =
|
|
36864
|
+
const normalizedPath = path12.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
36771
36865
|
if (normalizedPath === normalizedRoot) return "";
|
|
36772
36866
|
return normalizedPath.startsWith(`${normalizedRoot}/`) ? normalizedPath.slice(normalizedRoot.length + 1) : normalizedPath.replace(/^\/+/, "");
|
|
36773
36867
|
}
|
|
@@ -37891,48 +37985,48 @@ function countOccurrences(content, oldText) {
|
|
|
37891
37985
|
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
|
|
37892
37986
|
return fuzzyContent.split(fuzzyOldText).length - 1;
|
|
37893
37987
|
}
|
|
37894
|
-
function getNotFoundError(
|
|
37988
|
+
function getNotFoundError(path12, editIndex, totalEdits) {
|
|
37895
37989
|
if (totalEdits === 1) {
|
|
37896
37990
|
return new Error(
|
|
37897
|
-
`Could not find the exact text in ${
|
|
37991
|
+
`Could not find the exact text in ${path12}. The old text must match exactly including all whitespace and newlines.`
|
|
37898
37992
|
);
|
|
37899
37993
|
}
|
|
37900
37994
|
return new Error(
|
|
37901
|
-
`Could not find edits[${editIndex}] in ${
|
|
37995
|
+
`Could not find edits[${editIndex}] in ${path12}. The oldText must match exactly including all whitespace and newlines.`
|
|
37902
37996
|
);
|
|
37903
37997
|
}
|
|
37904
|
-
function getDuplicateError(
|
|
37998
|
+
function getDuplicateError(path12, editIndex, totalEdits, occurrences) {
|
|
37905
37999
|
if (totalEdits === 1) {
|
|
37906
38000
|
return new Error(
|
|
37907
|
-
`Found ${occurrences} occurrences of the text in ${
|
|
38001
|
+
`Found ${occurrences} occurrences of the text in ${path12}. The text must be unique. Please provide more context to make it unique.`
|
|
37908
38002
|
);
|
|
37909
38003
|
}
|
|
37910
38004
|
return new Error(
|
|
37911
|
-
`Found ${occurrences} occurrences of edits[${editIndex}] in ${
|
|
38005
|
+
`Found ${occurrences} occurrences of edits[${editIndex}] in ${path12}. Each oldText must be unique. Please provide more context to make it unique.`
|
|
37912
38006
|
);
|
|
37913
38007
|
}
|
|
37914
|
-
function getEmptyOldTextError(
|
|
38008
|
+
function getEmptyOldTextError(path12, editIndex, totalEdits) {
|
|
37915
38009
|
if (totalEdits === 1) {
|
|
37916
|
-
return new Error(`oldText must not be empty in ${
|
|
38010
|
+
return new Error(`oldText must not be empty in ${path12}.`);
|
|
37917
38011
|
}
|
|
37918
|
-
return new Error(`edits[${editIndex}].oldText must not be empty in ${
|
|
38012
|
+
return new Error(`edits[${editIndex}].oldText must not be empty in ${path12}.`);
|
|
37919
38013
|
}
|
|
37920
|
-
function getNoChangeError(
|
|
38014
|
+
function getNoChangeError(path12, totalEdits) {
|
|
37921
38015
|
if (totalEdits === 1) {
|
|
37922
38016
|
return new Error(
|
|
37923
|
-
`No changes made to ${
|
|
38017
|
+
`No changes made to ${path12}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`
|
|
37924
38018
|
);
|
|
37925
38019
|
}
|
|
37926
|
-
return new Error(`No changes made to ${
|
|
38020
|
+
return new Error(`No changes made to ${path12}. The replacements produced identical content.`);
|
|
37927
38021
|
}
|
|
37928
|
-
function applyEditsToNormalizedContent(normalizedContent, edits,
|
|
38022
|
+
function applyEditsToNormalizedContent(normalizedContent, edits, path12) {
|
|
37929
38023
|
const normalizedEdits = edits.map((edit) => ({
|
|
37930
38024
|
oldText: normalizeToLF(edit.oldText),
|
|
37931
38025
|
newText: normalizeToLF(edit.newText)
|
|
37932
38026
|
}));
|
|
37933
38027
|
for (let i = 0; i < normalizedEdits.length; i++) {
|
|
37934
38028
|
if (normalizedEdits[i].oldText.length === 0) {
|
|
37935
|
-
throw getEmptyOldTextError(
|
|
38029
|
+
throw getEmptyOldTextError(path12, i, normalizedEdits.length);
|
|
37936
38030
|
}
|
|
37937
38031
|
}
|
|
37938
38032
|
const initialMatches = normalizedEdits.map((edit) => fuzzyFindText(normalizedContent, edit.oldText));
|
|
@@ -37943,11 +38037,11 @@ function applyEditsToNormalizedContent(normalizedContent, edits, path11) {
|
|
|
37943
38037
|
const edit = normalizedEdits[i];
|
|
37944
38038
|
const matchResult = fuzzyFindText(replacementBaseContent, edit.oldText);
|
|
37945
38039
|
if (!matchResult.found) {
|
|
37946
|
-
throw getNotFoundError(
|
|
38040
|
+
throw getNotFoundError(path12, i, normalizedEdits.length);
|
|
37947
38041
|
}
|
|
37948
38042
|
const occurrences = countOccurrences(replacementBaseContent, edit.oldText);
|
|
37949
38043
|
if (occurrences > 1) {
|
|
37950
|
-
throw getDuplicateError(
|
|
38044
|
+
throw getDuplicateError(path12, i, normalizedEdits.length, occurrences);
|
|
37951
38045
|
}
|
|
37952
38046
|
matchedEdits.push({
|
|
37953
38047
|
editIndex: i,
|
|
@@ -37962,19 +38056,19 @@ function applyEditsToNormalizedContent(normalizedContent, edits, path11) {
|
|
|
37962
38056
|
const current = matchedEdits[i];
|
|
37963
38057
|
if (previous.matchIndex + previous.matchLength > current.matchIndex) {
|
|
37964
38058
|
throw new Error(
|
|
37965
|
-
`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${
|
|
38059
|
+
`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${path12}. Merge them into one edit or target disjoint regions.`
|
|
37966
38060
|
);
|
|
37967
38061
|
}
|
|
37968
38062
|
}
|
|
37969
38063
|
const baseContent = normalizedContent;
|
|
37970
38064
|
const newContent = usedFuzzyMatch ? applyReplacementsPreservingUnchangedLines(normalizedContent, replacementBaseContent, matchedEdits) : applyReplacements(replacementBaseContent, matchedEdits);
|
|
37971
38065
|
if (baseContent === newContent) {
|
|
37972
|
-
throw getNoChangeError(
|
|
38066
|
+
throw getNoChangeError(path12, normalizedEdits.length);
|
|
37973
38067
|
}
|
|
37974
38068
|
return { baseContent, newContent };
|
|
37975
38069
|
}
|
|
37976
|
-
function generateUnifiedPatch(
|
|
37977
|
-
return Diff.createTwoFilesPatch(
|
|
38070
|
+
function generateUnifiedPatch(path12, oldContent, newContent, contextLines = 4) {
|
|
38071
|
+
return Diff.createTwoFilesPatch(path12, path12, oldContent, newContent, void 0, void 0, {
|
|
37978
38072
|
context: contextLines,
|
|
37979
38073
|
headerOptions: Diff.FILE_HEADERS_ONLY
|
|
37980
38074
|
});
|
|
@@ -38091,17 +38185,17 @@ function getState(env) {
|
|
|
38091
38185
|
}
|
|
38092
38186
|
return state2;
|
|
38093
38187
|
}
|
|
38094
|
-
async function getMutationQueueKey(env,
|
|
38095
|
-
const absolutePath = getOrThrow(await env.absolutePath(
|
|
38188
|
+
async function getMutationQueueKey(env, path12) {
|
|
38189
|
+
const absolutePath = getOrThrow(await env.absolutePath(path12));
|
|
38096
38190
|
const canonicalPath = await env.canonicalPath(absolutePath);
|
|
38097
38191
|
if (canonicalPath.ok) return canonicalPath.value;
|
|
38098
38192
|
if (canonicalPath.error.code === "not_found" || canonicalPath.error.code === "not_supported") return absolutePath;
|
|
38099
38193
|
throw canonicalPath.error;
|
|
38100
38194
|
}
|
|
38101
|
-
async function withFileMutationQueue(env,
|
|
38195
|
+
async function withFileMutationQueue(env, path12, fn) {
|
|
38102
38196
|
const state2 = getState(env);
|
|
38103
38197
|
const registration = state2.registration.then(async () => {
|
|
38104
|
-
const key2 = await getMutationQueueKey(env,
|
|
38198
|
+
const key2 = await getMutationQueueKey(env, path12);
|
|
38105
38199
|
const currentQueue2 = state2.queues.get(key2) ?? Promise.resolve();
|
|
38106
38200
|
let releaseNext2 = () => {
|
|
38107
38201
|
};
|
|
@@ -38129,15 +38223,15 @@ async function withFileMutationQueue(env, path11, fn) {
|
|
|
38129
38223
|
// ../agent/src/harness/tools/path-utils.ts
|
|
38130
38224
|
var UNICODE_SPACES2 = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
38131
38225
|
var NARROW_NO_BREAK_SPACE = "\u202F";
|
|
38132
|
-
function normalizeToolPath(
|
|
38133
|
-
const normalized =
|
|
38226
|
+
function normalizeToolPath(path12) {
|
|
38227
|
+
const normalized = path12.replace(UNICODE_SPACES2, " ");
|
|
38134
38228
|
return normalized.startsWith("@") ? normalized.slice(1) : normalized;
|
|
38135
38229
|
}
|
|
38136
|
-
async function resolveToolPath(env,
|
|
38137
|
-
return getOrThrow(await env.absolutePath(normalizeToolPath(
|
|
38230
|
+
async function resolveToolPath(env, path12, signal) {
|
|
38231
|
+
return getOrThrow(await env.absolutePath(normalizeToolPath(path12), signal));
|
|
38138
38232
|
}
|
|
38139
|
-
async function resolveReadToolPath(env,
|
|
38140
|
-
const resolved = await resolveToolPath(env,
|
|
38233
|
+
async function resolveReadToolPath(env, path12, signal) {
|
|
38234
|
+
const resolved = await resolveToolPath(env, path12, signal);
|
|
38141
38235
|
const variants = [
|
|
38142
38236
|
resolved,
|
|
38143
38237
|
resolved.replace(/ (AM|PM)\./gi, `${NARROW_NO_BREAK_SPACE}$1.`),
|
|
@@ -38193,8 +38287,8 @@ function validateEditInput(input) {
|
|
|
38193
38287
|
}
|
|
38194
38288
|
return { path: input.path, edits: input.edits };
|
|
38195
38289
|
}
|
|
38196
|
-
function editAccessError(
|
|
38197
|
-
return new Error(`Could not edit file: ${
|
|
38290
|
+
function editAccessError(path12, error) {
|
|
38291
|
+
return new Error(`Could not edit file: ${path12}. Error code: ${error.code}.`, { cause: error });
|
|
38198
38292
|
}
|
|
38199
38293
|
function createEditTool() {
|
|
38200
38294
|
return {
|
|
@@ -38204,33 +38298,33 @@ function createEditTool() {
|
|
|
38204
38298
|
parameters: editSchema,
|
|
38205
38299
|
prepareArguments: prepareEditArguments,
|
|
38206
38300
|
async execute(_toolCallId, input, signal, _onUpdate, { env }) {
|
|
38207
|
-
const { path:
|
|
38208
|
-
const absolutePath = await resolveToolPath(env,
|
|
38301
|
+
const { path: path12, edits } = validateEditInput(input);
|
|
38302
|
+
const absolutePath = await resolveToolPath(env, path12, signal);
|
|
38209
38303
|
return withFileMutationQueue(env, absolutePath, async () => {
|
|
38210
38304
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38211
38305
|
const info = await env.fileInfo(absolutePath, signal);
|
|
38212
|
-
if (!info.ok) throw editAccessError(
|
|
38306
|
+
if (!info.ok) throw editAccessError(path12, info.error);
|
|
38213
38307
|
if (info.value.kind !== "file" && info.value.kind !== "symlink") {
|
|
38214
|
-
throw new Error(`Could not edit file: ${
|
|
38308
|
+
throw new Error(`Could not edit file: ${path12}. Path is not a file.`);
|
|
38215
38309
|
}
|
|
38216
38310
|
const readResult = await env.readTextFile(absolutePath, signal);
|
|
38217
|
-
if (!readResult.ok) throw editAccessError(
|
|
38311
|
+
if (!readResult.ok) throw editAccessError(path12, readResult.error);
|
|
38218
38312
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38219
38313
|
const { bom, text: content } = stripBom(readResult.value);
|
|
38220
38314
|
const originalEnding = detectLineEnding(content);
|
|
38221
38315
|
const normalizedContent = normalizeToLF(content);
|
|
38222
|
-
const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits,
|
|
38316
|
+
const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path12);
|
|
38223
38317
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38224
38318
|
const finalContent = bom + restoreLineEndings(newContent, originalEnding);
|
|
38225
38319
|
const writeResult = await env.writeFile(absolutePath, finalContent, signal);
|
|
38226
|
-
if (!writeResult.ok) throw editAccessError(
|
|
38320
|
+
if (!writeResult.ok) throw editAccessError(path12, writeResult.error);
|
|
38227
38321
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38228
38322
|
const diffResult = generateDiffString(baseContent, newContent);
|
|
38229
38323
|
return {
|
|
38230
|
-
content: [{ type: "text", text: `Successfully replaced ${edits.length} block(s) in ${
|
|
38324
|
+
content: [{ type: "text", text: `Successfully replaced ${edits.length} block(s) in ${path12}.` }],
|
|
38231
38325
|
details: {
|
|
38232
38326
|
diff: diffResult.diff,
|
|
38233
|
-
patch: generateUnifiedPatch(
|
|
38327
|
+
patch: generateUnifiedPatch(path12, baseContent, newContent),
|
|
38234
38328
|
firstChangedLine: diffResult.firstChangedLine
|
|
38235
38329
|
}
|
|
38236
38330
|
};
|
|
@@ -38337,8 +38431,8 @@ function createReadTool(options) {
|
|
|
38337
38431
|
label: "read",
|
|
38338
38432
|
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES2} lines or ${DEFAULT_MAX_BYTES3 / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
|
|
38339
38433
|
parameters: readSchema,
|
|
38340
|
-
async execute(_toolCallId, { path:
|
|
38341
|
-
const absolutePath = await resolveReadToolPath(env,
|
|
38434
|
+
async execute(_toolCallId, { path: path12, offset, limit }, signal, _onUpdate, { env }) {
|
|
38435
|
+
const absolutePath = await resolveReadToolPath(env, path12, signal);
|
|
38342
38436
|
const bytes = getOrThrow(await env.readBinaryFile(absolutePath, signal));
|
|
38343
38437
|
const mimeType = detectSupportedImageMimeType(bytes);
|
|
38344
38438
|
if (mimeType) {
|
|
@@ -38404,7 +38498,7 @@ ${processed.hints.join("\n")}` : "";
|
|
|
38404
38498
|
let details;
|
|
38405
38499
|
if (truncation.firstLineExceedsLimit) {
|
|
38406
38500
|
const firstLineSize = formatSize2(new TextEncoder().encode(allLines[startLine]).byteLength);
|
|
38407
|
-
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize2(DEFAULT_MAX_BYTES3)} limit. Use bash: sed -n '${startLineDisplay}p' ${
|
|
38501
|
+
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize2(DEFAULT_MAX_BYTES3)} limit. Use bash: sed -n '${startLineDisplay}p' ${path12} | head -c ${DEFAULT_MAX_BYTES3}]`;
|
|
38408
38502
|
details = { truncation };
|
|
38409
38503
|
} else if (truncation.truncated) {
|
|
38410
38504
|
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
|
|
@@ -38446,14 +38540,14 @@ function createWriteTool() {
|
|
|
38446
38540
|
label: "write",
|
|
38447
38541
|
description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
|
|
38448
38542
|
parameters: writeSchema,
|
|
38449
|
-
async execute(_toolCallId, { path:
|
|
38450
|
-
const absolutePath = await resolveToolPath(env,
|
|
38543
|
+
async execute(_toolCallId, { path: path12, content }, signal, _onUpdate, { env }) {
|
|
38544
|
+
const absolutePath = await resolveToolPath(env, path12, signal);
|
|
38451
38545
|
return withFileMutationQueue(env, absolutePath, async () => {
|
|
38452
38546
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38453
38547
|
getOrThrow(await env.writeFile(absolutePath, content, signal));
|
|
38454
38548
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
38455
38549
|
return {
|
|
38456
|
-
content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${
|
|
38550
|
+
content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path12}` }],
|
|
38457
38551
|
details: void 0
|
|
38458
38552
|
};
|
|
38459
38553
|
});
|
|
@@ -38828,18 +38922,18 @@ function readPiManifest(packageJsonPath) {
|
|
|
38828
38922
|
}
|
|
38829
38923
|
|
|
38830
38924
|
// dist/core/source-info.js
|
|
38831
|
-
function createSourceInfo(
|
|
38925
|
+
function createSourceInfo(path12, metadata) {
|
|
38832
38926
|
return {
|
|
38833
|
-
path:
|
|
38927
|
+
path: path12,
|
|
38834
38928
|
source: metadata.source,
|
|
38835
38929
|
scope: metadata.scope,
|
|
38836
38930
|
origin: metadata.origin,
|
|
38837
38931
|
baseDir: metadata.baseDir
|
|
38838
38932
|
};
|
|
38839
38933
|
}
|
|
38840
|
-
function createSyntheticSourceInfo(
|
|
38934
|
+
function createSyntheticSourceInfo(path12, options) {
|
|
38841
38935
|
return {
|
|
38842
|
-
path:
|
|
38936
|
+
path: path12,
|
|
38843
38937
|
source: options.source,
|
|
38844
38938
|
scope: options.scope ?? "temporary",
|
|
38845
38939
|
origin: options.origin ?? "top-level",
|
|
@@ -40222,13 +40316,13 @@ var ExtensionRunner = class {
|
|
|
40222
40316
|
const handlerResult = await handler(event, ctx);
|
|
40223
40317
|
const result = handlerResult;
|
|
40224
40318
|
if (result?.skillPaths?.length) {
|
|
40225
|
-
skillPaths.push(...result.skillPaths.map((
|
|
40319
|
+
skillPaths.push(...result.skillPaths.map((path12) => ({ path: path12, extensionPath: ext.path })));
|
|
40226
40320
|
}
|
|
40227
40321
|
if (result?.promptPaths?.length) {
|
|
40228
|
-
promptPaths.push(...result.promptPaths.map((
|
|
40322
|
+
promptPaths.push(...result.promptPaths.map((path12) => ({ path: path12, extensionPath: ext.path })));
|
|
40229
40323
|
}
|
|
40230
40324
|
if (result?.themePaths?.length) {
|
|
40231
|
-
themePaths.push(...result.themePaths.map((
|
|
40325
|
+
themePaths.push(...result.themePaths.map((path12) => ({ path: path12, extensionPath: ext.path })));
|
|
40232
40326
|
}
|
|
40233
40327
|
} catch (err2) {
|
|
40234
40328
|
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
@@ -41878,14 +41972,14 @@ var OutputAccumulator = class {
|
|
|
41878
41972
|
// dist/core/tools/render-utils.js
|
|
41879
41973
|
import * as os2 from "node:os";
|
|
41880
41974
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
41881
|
-
function shortenPath(
|
|
41882
|
-
if (typeof
|
|
41975
|
+
function shortenPath(path12) {
|
|
41976
|
+
if (typeof path12 !== "string")
|
|
41883
41977
|
return "";
|
|
41884
41978
|
const home = os2.homedir();
|
|
41885
|
-
if (
|
|
41886
|
-
return `~${
|
|
41979
|
+
if (path12.startsWith(home)) {
|
|
41980
|
+
return `~${path12.slice(home.length)}`;
|
|
41887
41981
|
}
|
|
41888
|
-
return
|
|
41982
|
+
return path12;
|
|
41889
41983
|
}
|
|
41890
41984
|
function linkPath(styledText, rawPath, cwd) {
|
|
41891
41985
|
if (!getCapabilities().hyperlinks)
|
|
@@ -42621,38 +42715,38 @@ function countOccurrences2(content, oldText) {
|
|
|
42621
42715
|
const fuzzyOldText = normalizeForFuzzyMatch2(oldText);
|
|
42622
42716
|
return fuzzyContent.split(fuzzyOldText).length - 1;
|
|
42623
42717
|
}
|
|
42624
|
-
function getNotFoundError2(
|
|
42718
|
+
function getNotFoundError2(path12, editIndex, totalEdits) {
|
|
42625
42719
|
if (totalEdits === 1) {
|
|
42626
|
-
return new Error(`Could not find the exact text in ${
|
|
42720
|
+
return new Error(`Could not find the exact text in ${path12}. The old text must match exactly including all whitespace and newlines.`);
|
|
42627
42721
|
}
|
|
42628
|
-
return new Error(`Could not find edits[${editIndex}] in ${
|
|
42722
|
+
return new Error(`Could not find edits[${editIndex}] in ${path12}. The oldText must match exactly including all whitespace and newlines.`);
|
|
42629
42723
|
}
|
|
42630
|
-
function getDuplicateError2(
|
|
42724
|
+
function getDuplicateError2(path12, editIndex, totalEdits, occurrences) {
|
|
42631
42725
|
if (totalEdits === 1) {
|
|
42632
|
-
return new Error(`Found ${occurrences} occurrences of the text in ${
|
|
42726
|
+
return new Error(`Found ${occurrences} occurrences of the text in ${path12}. The text must be unique. Please provide more context to make it unique.`);
|
|
42633
42727
|
}
|
|
42634
|
-
return new Error(`Found ${occurrences} occurrences of edits[${editIndex}] in ${
|
|
42728
|
+
return new Error(`Found ${occurrences} occurrences of edits[${editIndex}] in ${path12}. Each oldText must be unique. Please provide more context to make it unique.`);
|
|
42635
42729
|
}
|
|
42636
|
-
function getEmptyOldTextError2(
|
|
42730
|
+
function getEmptyOldTextError2(path12, editIndex, totalEdits) {
|
|
42637
42731
|
if (totalEdits === 1) {
|
|
42638
|
-
return new Error(`oldText must not be empty in ${
|
|
42732
|
+
return new Error(`oldText must not be empty in ${path12}.`);
|
|
42639
42733
|
}
|
|
42640
|
-
return new Error(`edits[${editIndex}].oldText must not be empty in ${
|
|
42734
|
+
return new Error(`edits[${editIndex}].oldText must not be empty in ${path12}.`);
|
|
42641
42735
|
}
|
|
42642
|
-
function getNoChangeError2(
|
|
42736
|
+
function getNoChangeError2(path12, totalEdits) {
|
|
42643
42737
|
if (totalEdits === 1) {
|
|
42644
|
-
return new Error(`No changes made to ${
|
|
42738
|
+
return new Error(`No changes made to ${path12}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`);
|
|
42645
42739
|
}
|
|
42646
|
-
return new Error(`No changes made to ${
|
|
42740
|
+
return new Error(`No changes made to ${path12}. The replacements produced identical content.`);
|
|
42647
42741
|
}
|
|
42648
|
-
function applyEditsToNormalizedContent2(normalizedContent, edits,
|
|
42742
|
+
function applyEditsToNormalizedContent2(normalizedContent, edits, path12) {
|
|
42649
42743
|
const normalizedEdits = edits.map((edit) => ({
|
|
42650
42744
|
oldText: normalizeToLF2(edit.oldText),
|
|
42651
42745
|
newText: normalizeToLF2(edit.newText)
|
|
42652
42746
|
}));
|
|
42653
42747
|
for (let i = 0; i < normalizedEdits.length; i++) {
|
|
42654
42748
|
if (normalizedEdits[i].oldText.length === 0) {
|
|
42655
|
-
throw getEmptyOldTextError2(
|
|
42749
|
+
throw getEmptyOldTextError2(path12, i, normalizedEdits.length);
|
|
42656
42750
|
}
|
|
42657
42751
|
}
|
|
42658
42752
|
const initialMatches = normalizedEdits.map((edit) => fuzzyFindText2(normalizedContent, edit.oldText));
|
|
@@ -42663,11 +42757,11 @@ function applyEditsToNormalizedContent2(normalizedContent, edits, path11) {
|
|
|
42663
42757
|
const edit = normalizedEdits[i];
|
|
42664
42758
|
const matchResult = fuzzyFindText2(replacementBaseContent, edit.oldText);
|
|
42665
42759
|
if (!matchResult.found) {
|
|
42666
|
-
throw getNotFoundError2(
|
|
42760
|
+
throw getNotFoundError2(path12, i, normalizedEdits.length);
|
|
42667
42761
|
}
|
|
42668
42762
|
const occurrences = countOccurrences2(replacementBaseContent, edit.oldText);
|
|
42669
42763
|
if (occurrences > 1) {
|
|
42670
|
-
throw getDuplicateError2(
|
|
42764
|
+
throw getDuplicateError2(path12, i, normalizedEdits.length, occurrences);
|
|
42671
42765
|
}
|
|
42672
42766
|
matchedEdits.push({
|
|
42673
42767
|
editIndex: i,
|
|
@@ -42681,18 +42775,18 @@ function applyEditsToNormalizedContent2(normalizedContent, edits, path11) {
|
|
|
42681
42775
|
const previous = matchedEdits[i - 1];
|
|
42682
42776
|
const current = matchedEdits[i];
|
|
42683
42777
|
if (previous.matchIndex + previous.matchLength > current.matchIndex) {
|
|
42684
|
-
throw new Error(`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${
|
|
42778
|
+
throw new Error(`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${path12}. Merge them into one edit or target disjoint regions.`);
|
|
42685
42779
|
}
|
|
42686
42780
|
}
|
|
42687
42781
|
const baseContent = normalizedContent;
|
|
42688
42782
|
const newContent = usedFuzzyMatch ? applyReplacementsPreservingUnchangedLines2(normalizedContent, replacementBaseContent, matchedEdits) : applyReplacements2(replacementBaseContent, matchedEdits);
|
|
42689
42783
|
if (baseContent === newContent) {
|
|
42690
|
-
throw getNoChangeError2(
|
|
42784
|
+
throw getNoChangeError2(path12, normalizedEdits.length);
|
|
42691
42785
|
}
|
|
42692
42786
|
return { baseContent, newContent };
|
|
42693
42787
|
}
|
|
42694
|
-
function generateUnifiedPatch2(
|
|
42695
|
-
return Diff3.createTwoFilesPatch(
|
|
42788
|
+
function generateUnifiedPatch2(path12, oldContent, newContent, contextLines = 4) {
|
|
42789
|
+
return Diff3.createTwoFilesPatch(path12, path12, oldContent, newContent, void 0, void 0, {
|
|
42696
42790
|
context: contextLines,
|
|
42697
42791
|
headerOptions: Diff3.FILE_HEADERS_ONLY
|
|
42698
42792
|
});
|
|
@@ -42798,19 +42892,19 @@ function generateDiffString2(oldContent, newContent, contextLines = 4) {
|
|
|
42798
42892
|
}
|
|
42799
42893
|
return { diff: output.join("\n"), firstChangedLine };
|
|
42800
42894
|
}
|
|
42801
|
-
async function computeEditsDiff(
|
|
42802
|
-
const absolutePath = resolveToCwd(
|
|
42895
|
+
async function computeEditsDiff(path12, edits, cwd) {
|
|
42896
|
+
const absolutePath = resolveToCwd(path12, cwd);
|
|
42803
42897
|
try {
|
|
42804
42898
|
try {
|
|
42805
42899
|
await access2(absolutePath, constants4.R_OK);
|
|
42806
42900
|
} catch (error) {
|
|
42807
42901
|
const errorMessage = error instanceof Error && "code" in error ? `Error code: ${error.code}` : String(error);
|
|
42808
|
-
return { error: `Could not edit file: ${
|
|
42902
|
+
return { error: `Could not edit file: ${path12}. ${errorMessage}.` };
|
|
42809
42903
|
}
|
|
42810
42904
|
const rawContent = await readFile(absolutePath, "utf-8");
|
|
42811
42905
|
const { text: content } = stripBom2(rawContent);
|
|
42812
42906
|
const normalizedContent = normalizeToLF2(content);
|
|
42813
|
-
const { baseContent, newContent } = applyEditsToNormalizedContent2(normalizedContent, edits,
|
|
42907
|
+
const { baseContent, newContent } = applyEditsToNormalizedContent2(normalizedContent, edits, path12);
|
|
42814
42908
|
return generateDiffString2(baseContent, newContent);
|
|
42815
42909
|
} catch (err2) {
|
|
42816
42910
|
return { error: err2 instanceof Error ? err2.message : String(err2) };
|
|
@@ -42875,9 +42969,9 @@ var editSchema2 = Type9.Object({
|
|
|
42875
42969
|
})
|
|
42876
42970
|
}, {});
|
|
42877
42971
|
var defaultEditOperations = {
|
|
42878
|
-
readFile: (
|
|
42879
|
-
writeFile: (
|
|
42880
|
-
access: (
|
|
42972
|
+
readFile: (path12) => fsReadFile(path12),
|
|
42973
|
+
writeFile: (path12, content) => fsWriteFile(path12, content, "utf-8"),
|
|
42974
|
+
access: (path12) => fsAccess2(path12, constants5.R_OK | constants5.W_OK)
|
|
42881
42975
|
};
|
|
42882
42976
|
function prepareEditArguments2(input) {
|
|
42883
42977
|
if (!input || typeof input !== "object") {
|
|
@@ -42932,15 +43026,15 @@ function getRenderablePreviewInput(args) {
|
|
|
42932
43026
|
if (!args) {
|
|
42933
43027
|
return null;
|
|
42934
43028
|
}
|
|
42935
|
-
const
|
|
42936
|
-
if (!
|
|
43029
|
+
const path12 = typeof args.path === "string" ? args.path : typeof args.file_path === "string" ? args.file_path : null;
|
|
43030
|
+
if (!path12) {
|
|
42937
43031
|
return null;
|
|
42938
43032
|
}
|
|
42939
43033
|
if (Array.isArray(args.edits) && args.edits.length > 0 && args.edits.every((edit) => typeof edit?.oldText === "string" && typeof edit?.newText === "string")) {
|
|
42940
|
-
return { path:
|
|
43034
|
+
return { path: path12, edits: args.edits };
|
|
42941
43035
|
}
|
|
42942
43036
|
if (typeof args.oldText === "string" && typeof args.newText === "string") {
|
|
42943
|
-
return { path:
|
|
43037
|
+
return { path: path12, edits: [{ oldText: args.oldText, newText: args.newText }] };
|
|
42944
43038
|
}
|
|
42945
43039
|
return null;
|
|
42946
43040
|
}
|
|
@@ -43014,8 +43108,8 @@ function createEditToolDefinition(cwd, options) {
|
|
|
43014
43108
|
renderShell: "self",
|
|
43015
43109
|
prepareArguments: prepareEditArguments2,
|
|
43016
43110
|
async execute(_toolCallId, input, signal, _onUpdate, _ctx) {
|
|
43017
|
-
const { path:
|
|
43018
|
-
const absolutePath = resolveToCwd(
|
|
43111
|
+
const { path: path12, edits } = validateEditInput2(input);
|
|
43112
|
+
const absolutePath = resolveToCwd(path12, cwd);
|
|
43019
43113
|
return withFileMutationQueue2(absolutePath, async () => {
|
|
43020
43114
|
const throwIfAborted = () => {
|
|
43021
43115
|
if (signal?.aborted)
|
|
@@ -43027,7 +43121,7 @@ function createEditToolDefinition(cwd, options) {
|
|
|
43027
43121
|
} catch (error) {
|
|
43028
43122
|
throwIfAborted();
|
|
43029
43123
|
const errorMessage = error instanceof Error && "code" in error ? `Error code: ${error.code}` : String(error);
|
|
43030
|
-
throw new Error(`Could not edit file: ${
|
|
43124
|
+
throw new Error(`Could not edit file: ${path12}. ${errorMessage}.`);
|
|
43031
43125
|
}
|
|
43032
43126
|
throwIfAborted();
|
|
43033
43127
|
const buffer = await ops.readFile(absolutePath);
|
|
@@ -43036,18 +43130,18 @@ function createEditToolDefinition(cwd, options) {
|
|
|
43036
43130
|
const { bom, text: content } = stripBom2(rawContent);
|
|
43037
43131
|
const originalEnding = detectLineEnding2(content);
|
|
43038
43132
|
const normalizedContent = normalizeToLF2(content);
|
|
43039
|
-
const { baseContent, newContent } = applyEditsToNormalizedContent2(normalizedContent, edits,
|
|
43133
|
+
const { baseContent, newContent } = applyEditsToNormalizedContent2(normalizedContent, edits, path12);
|
|
43040
43134
|
throwIfAborted();
|
|
43041
43135
|
const finalContent = bom + restoreLineEndings2(newContent, originalEnding);
|
|
43042
43136
|
await ops.writeFile(absolutePath, finalContent);
|
|
43043
43137
|
throwIfAborted();
|
|
43044
43138
|
const diffResult = generateDiffString2(baseContent, newContent);
|
|
43045
|
-
const patch = generateUnifiedPatch2(
|
|
43139
|
+
const patch = generateUnifiedPatch2(path12, baseContent, newContent);
|
|
43046
43140
|
return {
|
|
43047
43141
|
content: [
|
|
43048
43142
|
{
|
|
43049
43143
|
type: "text",
|
|
43050
|
-
text: `Successfully replaced ${edits.length} block(s) in ${
|
|
43144
|
+
text: `Successfully replaced ${edits.length} block(s) in ${path12}.`
|
|
43051
43145
|
}
|
|
43052
43146
|
],
|
|
43053
43147
|
details: { diff: diffResult.diff, patch, firstChangedLine: diffResult.firstChangedLine }
|
|
@@ -43421,11 +43515,11 @@ async function ensureTool(tool, silent = false) {
|
|
|
43421
43515
|
console.log(chalk3.dim(`${config.name} not found. Downloading...`));
|
|
43422
43516
|
}
|
|
43423
43517
|
try {
|
|
43424
|
-
const
|
|
43518
|
+
const path12 = await downloadTool(tool);
|
|
43425
43519
|
if (!silent) {
|
|
43426
|
-
console.log(chalk3.dim(`${config.name} installed to ${
|
|
43520
|
+
console.log(chalk3.dim(`${config.name} installed to ${path12}`));
|
|
43427
43521
|
}
|
|
43428
|
-
return
|
|
43522
|
+
return path12;
|
|
43429
43523
|
} catch (e) {
|
|
43430
43524
|
if (!silent) {
|
|
43431
43525
|
console.log(chalk3.yellow(`Failed to download ${config.name}: ${e instanceof Error ? e.message : e}`));
|
|
@@ -43457,10 +43551,10 @@ var defaultFindOperations = {
|
|
|
43457
43551
|
function formatFindCall(args, theme2) {
|
|
43458
43552
|
const pattern = str(args?.pattern);
|
|
43459
43553
|
const rawPath = str(args?.path);
|
|
43460
|
-
const
|
|
43554
|
+
const path12 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
43461
43555
|
const limit = args?.limit;
|
|
43462
43556
|
const invalidArg = invalidArgText(theme2);
|
|
43463
|
-
let text = theme2.fg("toolTitle", theme2.bold("find")) + " " + (pattern === null ? invalidArg : theme2.fg("accent", pattern || "")) + theme2.fg("toolOutput", ` in ${
|
|
43557
|
+
let text = theme2.fg("toolTitle", theme2.bold("find")) + " " + (pattern === null ? invalidArg : theme2.fg("accent", pattern || "")) + theme2.fg("toolOutput", ` in ${path12 === null ? invalidArg : path12}`);
|
|
43464
43558
|
if (limit !== void 0) {
|
|
43465
43559
|
text += theme2.fg("toolOutput", ` (limit ${limit})`);
|
|
43466
43560
|
}
|
|
@@ -43736,11 +43830,11 @@ var defaultGrepOperations = {
|
|
|
43736
43830
|
function formatGrepCall(args, theme2) {
|
|
43737
43831
|
const pattern = str(args?.pattern);
|
|
43738
43832
|
const rawPath = str(args?.path);
|
|
43739
|
-
const
|
|
43833
|
+
const path12 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
43740
43834
|
const glob = str(args?.glob);
|
|
43741
43835
|
const limit = args?.limit;
|
|
43742
43836
|
const invalidArg = invalidArgText(theme2);
|
|
43743
|
-
let text = theme2.fg("toolTitle", theme2.bold("grep")) + " " + (pattern === null ? invalidArg : theme2.fg("accent", `/${pattern || ""}/`)) + theme2.fg("toolOutput", ` in ${
|
|
43837
|
+
let text = theme2.fg("toolTitle", theme2.bold("grep")) + " " + (pattern === null ? invalidArg : theme2.fg("accent", `/${pattern || ""}/`)) + theme2.fg("toolOutput", ` in ${path12 === null ? invalidArg : path12}`);
|
|
43744
43838
|
if (glob)
|
|
43745
43839
|
text += theme2.fg("toolOutput", ` (${glob})`);
|
|
43746
43840
|
if (limit !== void 0)
|
|
@@ -44059,7 +44153,7 @@ function createLsToolDefinition(cwd, options) {
|
|
|
44059
44153
|
description: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT3} entries or ${DEFAULT_MAX_BYTES2 / 1024}KB (whichever is hit first).`,
|
|
44060
44154
|
promptSnippet: "List directory contents",
|
|
44061
44155
|
parameters: lsSchema,
|
|
44062
|
-
async execute(_toolCallId, { path:
|
|
44156
|
+
async execute(_toolCallId, { path: path12, limit }, signal, _onUpdate, _ctx) {
|
|
44063
44157
|
return new Promise((resolve15, reject) => {
|
|
44064
44158
|
if (signal?.aborted) {
|
|
44065
44159
|
reject(new Error("Operation aborted"));
|
|
@@ -44069,7 +44163,7 @@ function createLsToolDefinition(cwd, options) {
|
|
|
44069
44163
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
44070
44164
|
(async () => {
|
|
44071
44165
|
try {
|
|
44072
|
-
const dirPath = resolveToCwd(
|
|
44166
|
+
const dirPath = resolveToCwd(path12 || ".", cwd);
|
|
44073
44167
|
const effectiveLimit = limit ?? DEFAULT_LIMIT3;
|
|
44074
44168
|
if (!await ops.exists(dirPath)) {
|
|
44075
44169
|
reject(new Error(`Path not found: ${dirPath}`));
|
|
@@ -44272,8 +44366,8 @@ var readSchema2 = Type13.Object({
|
|
|
44272
44366
|
});
|
|
44273
44367
|
var COMPACT_RESOURCE_FILE_NAMES = /* @__PURE__ */ new Set(["AGENTS.override.md", "AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"]);
|
|
44274
44368
|
var defaultReadOperations = {
|
|
44275
|
-
readFile: (
|
|
44276
|
-
access: (
|
|
44369
|
+
readFile: (path12) => fsReadFile3(path12),
|
|
44370
|
+
access: (path12) => fsAccess3(path12, constants6.R_OK),
|
|
44277
44371
|
detectImageMimeType: detectSupportedImageMimeTypeFromFile
|
|
44278
44372
|
};
|
|
44279
44373
|
function formatReadLineRange(args, theme2) {
|
|
@@ -44387,7 +44481,7 @@ function createReadToolDefinition(cwd, options) {
|
|
|
44387
44481
|
promptSnippet: "Read file contents",
|
|
44388
44482
|
promptGuidelines: ["Use read to examine files instead of cat or sed."],
|
|
44389
44483
|
parameters: readSchema2,
|
|
44390
|
-
async execute(_toolCallId, { path:
|
|
44484
|
+
async execute(_toolCallId, { path: path12, offset, limit }, signal, _onUpdate, ctx) {
|
|
44391
44485
|
return new Promise((resolve15, reject) => {
|
|
44392
44486
|
if (signal?.aborted) {
|
|
44393
44487
|
reject(new Error("Operation aborted"));
|
|
@@ -44401,7 +44495,7 @@ function createReadToolDefinition(cwd, options) {
|
|
|
44401
44495
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
44402
44496
|
(async () => {
|
|
44403
44497
|
try {
|
|
44404
|
-
const absolutePath = await resolveReadPathAsync(
|
|
44498
|
+
const absolutePath = await resolveReadPathAsync(path12, cwd);
|
|
44405
44499
|
if (aborted)
|
|
44406
44500
|
return;
|
|
44407
44501
|
await ops.access(absolutePath);
|
|
@@ -44457,7 +44551,7 @@ ${nonVisionImageNote}`;
|
|
|
44457
44551
|
let outputText;
|
|
44458
44552
|
if (truncation.firstLineExceedsLimit) {
|
|
44459
44553
|
const firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], "utf-8"));
|
|
44460
|
-
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES2)} limit. Use bash: sed -n '${startLineDisplay}p' ${
|
|
44554
|
+
outputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES2)} limit. Use bash: sed -n '${startLineDisplay}p' ${path12} | head -c ${DEFAULT_MAX_BYTES2}]`;
|
|
44461
44555
|
details = { truncation };
|
|
44462
44556
|
} else if (truncation.truncated) {
|
|
44463
44557
|
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
|
|
@@ -44642,7 +44736,7 @@ var writeSchema2 = Type15.Object({
|
|
|
44642
44736
|
content: Type15.String({ description: "Content to write to the file" })
|
|
44643
44737
|
});
|
|
44644
44738
|
var defaultWriteOperations = {
|
|
44645
|
-
writeFile: (
|
|
44739
|
+
writeFile: (path12, content) => fsWriteFile2(path12, content, "utf-8"),
|
|
44646
44740
|
mkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {
|
|
44647
44741
|
})
|
|
44648
44742
|
};
|
|
@@ -44766,8 +44860,8 @@ function createWriteToolDefinition(cwd, options) {
|
|
|
44766
44860
|
promptSnippet: "Create or overwrite files",
|
|
44767
44861
|
promptGuidelines: ["Use write only for new files or complete rewrites."],
|
|
44768
44862
|
parameters: writeSchema2,
|
|
44769
|
-
async execute(_toolCallId, { path:
|
|
44770
|
-
const absolutePath = resolveToCwd(
|
|
44863
|
+
async execute(_toolCallId, { path: path12, content }, signal, _onUpdate, _ctx) {
|
|
44864
|
+
const absolutePath = resolveToCwd(path12, cwd);
|
|
44771
44865
|
const dir = dirname11(absolutePath);
|
|
44772
44866
|
return withFileMutationQueue2(absolutePath, async () => {
|
|
44773
44867
|
const throwIfAborted = () => {
|
|
@@ -44780,7 +44874,7 @@ function createWriteToolDefinition(cwd, options) {
|
|
|
44780
44874
|
await ops.writeFile(absolutePath, content);
|
|
44781
44875
|
throwIfAborted();
|
|
44782
44876
|
return {
|
|
44783
|
-
content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${
|
|
44877
|
+
content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path12}` }],
|
|
44784
44878
|
details: void 0
|
|
44785
44879
|
};
|
|
44786
44880
|
});
|
|
@@ -47370,13 +47464,13 @@ var FileAuthStorageBackend = class {
|
|
|
47370
47464
|
chmodSync2(this.authPath, 384);
|
|
47371
47465
|
}
|
|
47372
47466
|
}
|
|
47373
|
-
acquireLockSyncWithRetry(
|
|
47467
|
+
acquireLockSyncWithRetry(path12) {
|
|
47374
47468
|
const maxAttempts = 10;
|
|
47375
47469
|
const delayMs = 20;
|
|
47376
47470
|
let lastError;
|
|
47377
47471
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
47378
47472
|
try {
|
|
47379
|
-
return lockfile.lockSync(
|
|
47473
|
+
return lockfile.lockSync(path12, { realpath: false });
|
|
47380
47474
|
} catch (error) {
|
|
47381
47475
|
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
47382
47476
|
if (code !== "ELOCKED" || attempt === maxAttempts) {
|
|
@@ -48279,8 +48373,8 @@ function formatValidationPath2(error) {
|
|
|
48279
48373
|
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
48280
48374
|
}
|
|
48281
48375
|
}
|
|
48282
|
-
const
|
|
48283
|
-
return
|
|
48376
|
+
const path12 = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
48377
|
+
return path12 || "root";
|
|
48284
48378
|
}
|
|
48285
48379
|
function deepFreeze(value) {
|
|
48286
48380
|
if (typeof value !== "object" || value === null || Object.isFrozen(value))
|
|
@@ -48299,16 +48393,16 @@ var ModelConfig = class _ModelConfig {
|
|
|
48299
48393
|
static async load(modelsJsonPath) {
|
|
48300
48394
|
if (!modelsJsonPath)
|
|
48301
48395
|
return new _ModelConfig(/* @__PURE__ */ new Map());
|
|
48302
|
-
const
|
|
48396
|
+
const path12 = normalizePath(modelsJsonPath);
|
|
48303
48397
|
let content;
|
|
48304
48398
|
try {
|
|
48305
|
-
content = await readFile2(
|
|
48399
|
+
content = await readFile2(path12, "utf-8");
|
|
48306
48400
|
} catch (error) {
|
|
48307
48401
|
if (error.code === "ENOENT")
|
|
48308
48402
|
return new _ModelConfig(/* @__PURE__ */ new Map());
|
|
48309
48403
|
return new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to load models.json: ${error instanceof Error ? error.message : error}
|
|
48310
48404
|
|
|
48311
|
-
File: ${
|
|
48405
|
+
File: ${path12}`);
|
|
48312
48406
|
}
|
|
48313
48407
|
let parsed;
|
|
48314
48408
|
try {
|
|
@@ -48316,14 +48410,14 @@ File: ${path11}`);
|
|
|
48316
48410
|
} catch (error) {
|
|
48317
48411
|
return new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to parse models.json: ${error instanceof Error ? error.message : error}
|
|
48318
48412
|
|
|
48319
|
-
File: ${
|
|
48413
|
+
File: ${path12}`);
|
|
48320
48414
|
}
|
|
48321
48415
|
if (!validateModelsConfig.Check(parsed)) {
|
|
48322
48416
|
const errors = validateModelsConfig.Errors(parsed).map((error) => ` - ${formatValidationPath2(error)}: ${error.message}`).join("\n") || "Unknown schema error";
|
|
48323
48417
|
return new _ModelConfig(/* @__PURE__ */ new Map(), `Invalid models.json schema:
|
|
48324
48418
|
${errors}
|
|
48325
48419
|
|
|
48326
|
-
File: ${
|
|
48420
|
+
File: ${path12}`);
|
|
48327
48421
|
}
|
|
48328
48422
|
const config = parsed;
|
|
48329
48423
|
const providers = /* @__PURE__ */ new Map();
|
|
@@ -48366,8 +48460,8 @@ var FileModelsStore = class {
|
|
|
48366
48460
|
storage;
|
|
48367
48461
|
path;
|
|
48368
48462
|
readState;
|
|
48369
|
-
constructor(
|
|
48370
|
-
this.path = normalizePath(
|
|
48463
|
+
constructor(path12 = join21(getAgentDir(), "models-store.json")) {
|
|
48464
|
+
this.path = normalizePath(path12);
|
|
48371
48465
|
this.storage = new FileAuthStorageBackend(this.path);
|
|
48372
48466
|
this.readState = sharedModelsFileReadState?.path === this.path ? sharedModelsFileReadState.readState : { data: {} };
|
|
48373
48467
|
if (!sharedModelsFileReadState) {
|
|
@@ -49318,16 +49412,16 @@ function parseGenericGitUrl(url) {
|
|
|
49318
49412
|
const { repo: repoWithoutRef, ref } = splitRef(url);
|
|
49319
49413
|
let repo = repoWithoutRef;
|
|
49320
49414
|
let host = "";
|
|
49321
|
-
let
|
|
49415
|
+
let path12 = "";
|
|
49322
49416
|
const scpLikeMatch = repoWithoutRef.match(/^git@([^:]+):(.+)$/);
|
|
49323
49417
|
if (scpLikeMatch) {
|
|
49324
49418
|
host = scpLikeMatch[1] ?? "";
|
|
49325
|
-
|
|
49419
|
+
path12 = scpLikeMatch[2] ?? "";
|
|
49326
49420
|
} else if (repoWithoutRef.startsWith("https://") || repoWithoutRef.startsWith("http://") || repoWithoutRef.startsWith("ssh://") || repoWithoutRef.startsWith("git://")) {
|
|
49327
49421
|
try {
|
|
49328
49422
|
const parsed = new URL(repoWithoutRef);
|
|
49329
49423
|
host = parsed.hostname;
|
|
49330
|
-
|
|
49424
|
+
path12 = parsed.pathname.replace(/^\/+/, "");
|
|
49331
49425
|
} catch {
|
|
49332
49426
|
return null;
|
|
49333
49427
|
}
|
|
@@ -49337,13 +49431,13 @@ function parseGenericGitUrl(url) {
|
|
|
49337
49431
|
return null;
|
|
49338
49432
|
}
|
|
49339
49433
|
host = repoWithoutRef.slice(0, slashIndex);
|
|
49340
|
-
|
|
49434
|
+
path12 = repoWithoutRef.slice(slashIndex + 1);
|
|
49341
49435
|
if (!host.includes(".") && host !== "localhost") {
|
|
49342
49436
|
return null;
|
|
49343
49437
|
}
|
|
49344
49438
|
repo = `https://${repoWithoutRef}`;
|
|
49345
49439
|
}
|
|
49346
|
-
return buildGitSource({ repo, host, path:
|
|
49440
|
+
return buildGitSource({ repo, host, path: path12, ref });
|
|
49347
49441
|
}
|
|
49348
49442
|
function parseGitUrl(source) {
|
|
49349
49443
|
const trimmed = source.trim();
|
|
@@ -50051,17 +50145,17 @@ var DefaultPackageManager = class {
|
|
|
50051
50145
|
getInstalledPath(source, scope) {
|
|
50052
50146
|
const parsed = this.parseSource(source);
|
|
50053
50147
|
if (parsed.type === "npm") {
|
|
50054
|
-
const
|
|
50055
|
-
return existsSync13(
|
|
50148
|
+
const path12 = this.getNpmInstallPath(parsed, scope);
|
|
50149
|
+
return existsSync13(path12) ? path12 : void 0;
|
|
50056
50150
|
}
|
|
50057
50151
|
if (parsed.type === "git") {
|
|
50058
|
-
const
|
|
50059
|
-
return existsSync13(
|
|
50152
|
+
const path12 = this.getGitInstallPath(parsed, scope);
|
|
50153
|
+
return existsSync13(path12) ? path12 : void 0;
|
|
50060
50154
|
}
|
|
50061
50155
|
if (parsed.type === "local") {
|
|
50062
50156
|
const baseDir = this.getBaseDirForScope(scope);
|
|
50063
|
-
const
|
|
50064
|
-
return existsSync13(
|
|
50157
|
+
const path12 = this.resolvePathFromBase(parsed.path, baseDir);
|
|
50158
|
+
return existsSync13(path12) ? path12 : void 0;
|
|
50065
50159
|
}
|
|
50066
50160
|
return void 0;
|
|
50067
50161
|
}
|
|
@@ -51063,9 +51157,9 @@ var DefaultPackageManager = class {
|
|
|
51063
51157
|
const output = this.runNpmCommandSync(["list", "-g", "--depth", "0", "--json"]);
|
|
51064
51158
|
const entries = JSON.parse(output);
|
|
51065
51159
|
for (const entry of entries) {
|
|
51066
|
-
const
|
|
51067
|
-
if (
|
|
51068
|
-
return
|
|
51160
|
+
const path12 = entry.dependencies?.[packageName]?.path;
|
|
51161
|
+
if (path12)
|
|
51162
|
+
return path12;
|
|
51069
51163
|
}
|
|
51070
51164
|
return void 0;
|
|
51071
51165
|
}
|
|
@@ -51319,9 +51413,9 @@ var DefaultPackageManager = class {
|
|
|
51319
51413
|
const projectAgentsSkillDirs = projectTrusted ? collectAncestorAgentsSkillDirs(this.cwd).filter((dir) => resolve7(dir) !== resolve7(userAgentsSkillsDir)) : [];
|
|
51320
51414
|
const addResources = (resourceType, paths, metadata, overrides, baseDir) => {
|
|
51321
51415
|
const target = this.getTargetMap(accumulator, resourceType);
|
|
51322
|
-
for (const
|
|
51323
|
-
const enabled = isEnabledByOverrides(
|
|
51324
|
-
this.addResource(target,
|
|
51416
|
+
for (const path12 of paths) {
|
|
51417
|
+
const enabled = isEnabledByOverrides(path12, overrides, baseDir);
|
|
51418
|
+
this.addResource(target, path12, metadata, enabled);
|
|
51325
51419
|
}
|
|
51326
51420
|
};
|
|
51327
51421
|
if (projectTrusted) {
|
|
@@ -51382,11 +51476,11 @@ var DefaultPackageManager = class {
|
|
|
51382
51476
|
throw new Error(`Unknown resource type: ${resourceType}`);
|
|
51383
51477
|
}
|
|
51384
51478
|
}
|
|
51385
|
-
addResource(map,
|
|
51386
|
-
if (!
|
|
51479
|
+
addResource(map, path12, metadata, enabled) {
|
|
51480
|
+
if (!path12)
|
|
51387
51481
|
return;
|
|
51388
|
-
if (!map.has(
|
|
51389
|
-
map.set(
|
|
51482
|
+
if (!map.has(path12)) {
|
|
51483
|
+
map.set(path12, { metadata, enabled });
|
|
51390
51484
|
}
|
|
51391
51485
|
}
|
|
51392
51486
|
createAccumulator() {
|
|
@@ -51399,8 +51493,8 @@ var DefaultPackageManager = class {
|
|
|
51399
51493
|
}
|
|
51400
51494
|
toResolvedPaths(accumulator) {
|
|
51401
51495
|
const mapToResolved = (entries) => {
|
|
51402
|
-
const resolved = Array.from(entries.entries()).map(([
|
|
51403
|
-
path:
|
|
51496
|
+
const resolved = Array.from(entries.entries()).map(([path12, { metadata, enabled }]) => ({
|
|
51497
|
+
path: path12,
|
|
51404
51498
|
enabled,
|
|
51405
51499
|
metadata
|
|
51406
51500
|
}));
|
|
@@ -51948,13 +52042,13 @@ var FileSettingsStorage = class {
|
|
|
51948
52042
|
this.globalSettingsPath = join25(resolvedAgentDir, "settings.json");
|
|
51949
52043
|
this.projectSettingsPath = join25(resolvedCwd, CONFIG_DIR_NAME, "settings.json");
|
|
51950
52044
|
}
|
|
51951
|
-
acquireLockSyncWithRetry(
|
|
52045
|
+
acquireLockSyncWithRetry(path12) {
|
|
51952
52046
|
const maxAttempts = 10;
|
|
51953
52047
|
const delayMs = 20;
|
|
51954
52048
|
let lastError;
|
|
51955
52049
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
51956
52050
|
try {
|
|
51957
|
-
return lockfile2.lockSync(
|
|
52051
|
+
return lockfile2.lockSync(path12, { realpath: false });
|
|
51958
52052
|
} catch (error) {
|
|
51959
52053
|
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
51960
52054
|
if (code !== "ELOCKED" || attempt === maxAttempts) {
|
|
@@ -51969,24 +52063,24 @@ var FileSettingsStorage = class {
|
|
|
51969
52063
|
throw lastError ?? new Error("Failed to acquire settings lock");
|
|
51970
52064
|
}
|
|
51971
52065
|
withLock(scope, fn) {
|
|
51972
|
-
const
|
|
51973
|
-
const dir = dirname17(
|
|
52066
|
+
const path12 = scope === "global" ? this.globalSettingsPath : this.projectSettingsPath;
|
|
52067
|
+
const dir = dirname17(path12);
|
|
51974
52068
|
let release;
|
|
51975
52069
|
try {
|
|
51976
|
-
const fileExists2 = existsSync15(
|
|
52070
|
+
const fileExists2 = existsSync15(path12);
|
|
51977
52071
|
if (fileExists2) {
|
|
51978
|
-
release = this.acquireLockSyncWithRetry(
|
|
52072
|
+
release = this.acquireLockSyncWithRetry(path12);
|
|
51979
52073
|
}
|
|
51980
|
-
const current = fileExists2 ? readFileSync12(
|
|
52074
|
+
const current = fileExists2 ? readFileSync12(path12, "utf-8") : void 0;
|
|
51981
52075
|
const next = fn(current);
|
|
51982
52076
|
if (next !== void 0) {
|
|
51983
52077
|
if (!existsSync15(dir)) {
|
|
51984
52078
|
mkdirSync8(dir, { recursive: true });
|
|
51985
52079
|
}
|
|
51986
52080
|
if (!release) {
|
|
51987
|
-
release = this.acquireLockSyncWithRetry(
|
|
52081
|
+
release = this.acquireLockSyncWithRetry(path12);
|
|
51988
52082
|
}
|
|
51989
|
-
writeFileSync8(
|
|
52083
|
+
writeFileSync8(path12, next, "utf-8");
|
|
51990
52084
|
}
|
|
51991
52085
|
} finally {
|
|
51992
52086
|
if (release) {
|
|
@@ -52476,8 +52570,8 @@ var SettingsManager = class _SettingsManager {
|
|
|
52476
52570
|
const shellPath = this.settings.shellPath;
|
|
52477
52571
|
return shellPath ? normalizePath(shellPath) : shellPath;
|
|
52478
52572
|
}
|
|
52479
|
-
setShellPath(
|
|
52480
|
-
this.globalSettings.shellPath =
|
|
52573
|
+
setShellPath(path12) {
|
|
52574
|
+
this.globalSettings.shellPath = path12;
|
|
52481
52575
|
this.markModified("shellPath");
|
|
52482
52576
|
this.save();
|
|
52483
52577
|
}
|
|
@@ -52980,7 +53074,7 @@ var DefaultResourceLoader = class {
|
|
|
52980
53074
|
return this.appendSystemPrompt;
|
|
52981
53075
|
}
|
|
52982
53076
|
getAppendSystemPromptSources() {
|
|
52983
|
-
return this.appendSystemPromptSourcePaths.map((
|
|
53077
|
+
return this.appendSystemPromptSourcePaths.map((path12) => ({ path: path12 }));
|
|
52984
53078
|
}
|
|
52985
53079
|
extendResources(paths) {
|
|
52986
53080
|
const skillPaths = this.normalizeExtensionPaths(paths.skillPaths ?? []);
|
|
@@ -53148,8 +53242,8 @@ var DefaultResourceLoader = class {
|
|
|
53148
53242
|
extensionsResult.errors.push(...inlineExtensions.errors);
|
|
53149
53243
|
return extensionsResult;
|
|
53150
53244
|
}
|
|
53151
|
-
resolveExtensionLoadPath(
|
|
53152
|
-
return resolvePath(
|
|
53245
|
+
resolveExtensionLoadPath(path12) {
|
|
53246
|
+
return resolvePath(path12, this.cwd, { normalizeUnicodeSpaces: true });
|
|
53153
53247
|
}
|
|
53154
53248
|
async loadFinalExtensionSet(extensionPaths, preTrustExtensions) {
|
|
53155
53249
|
if (!preTrustExtensions) {
|
|
@@ -53162,8 +53256,8 @@ var DefaultResourceLoader = class {
|
|
|
53162
53256
|
}
|
|
53163
53257
|
const preloadedByPath = new Map(preTrustExtensions.extensions.filter((extension) => !extension.path.startsWith("<inline:")).map((extension) => [extension.resolvedPath, extension]));
|
|
53164
53258
|
const failedPreloadPaths = new Set(preTrustExtensions.errors.map((error) => this.resolveExtensionLoadPath(error.path)));
|
|
53165
|
-
const remainingPaths = extensionPaths.filter((
|
|
53166
|
-
const resolvedPath = this.resolveExtensionLoadPath(
|
|
53259
|
+
const remainingPaths = extensionPaths.filter((path12) => {
|
|
53260
|
+
const resolvedPath = this.resolveExtensionLoadPath(path12);
|
|
53167
53261
|
return !preloadedByPath.has(resolvedPath) && !failedPreloadPaths.has(resolvedPath);
|
|
53168
53262
|
});
|
|
53169
53263
|
const remainingExtensions = await loadExtensionsCached(remainingPaths, this.cwd, this.eventBus, preTrustExtensions.runtime);
|
|
@@ -53172,7 +53266,7 @@ var DefaultResourceLoader = class {
|
|
|
53172
53266
|
loadedByPath.set(extension.resolvedPath, extension);
|
|
53173
53267
|
}
|
|
53174
53268
|
const inlineExtensions = preTrustExtensions.extensions.filter((extension) => extension.path.startsWith("<inline:"));
|
|
53175
|
-
const orderedExtensions = extensionPaths.map((
|
|
53269
|
+
const orderedExtensions = extensionPaths.map((path12) => loadedByPath.get(this.resolveExtensionLoadPath(path12))).filter((extension) => extension !== void 0);
|
|
53176
53270
|
orderedExtensions.push(...inlineExtensions);
|
|
53177
53271
|
const extensionsResult = {
|
|
53178
53272
|
extensions: orderedExtensions,
|
|
@@ -54334,30 +54428,30 @@ function getProjectTrustOptions(cwd, options) {
|
|
|
54334
54428
|
}
|
|
54335
54429
|
return trustOptions;
|
|
54336
54430
|
}
|
|
54337
|
-
function readTrustFile(
|
|
54338
|
-
if (!existsSync19(
|
|
54431
|
+
function readTrustFile(path12) {
|
|
54432
|
+
if (!existsSync19(path12)) {
|
|
54339
54433
|
return {};
|
|
54340
54434
|
}
|
|
54341
54435
|
let parsed;
|
|
54342
54436
|
try {
|
|
54343
|
-
parsed = JSON.parse(readFileSync14(
|
|
54437
|
+
parsed = JSON.parse(readFileSync14(path12, "utf-8"));
|
|
54344
54438
|
} catch (error) {
|
|
54345
54439
|
const message = error instanceof Error ? error.message : String(error);
|
|
54346
|
-
throw new Error(`Failed to read trust store ${
|
|
54440
|
+
throw new Error(`Failed to read trust store ${path12}: ${message}`);
|
|
54347
54441
|
}
|
|
54348
54442
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
54349
|
-
throw new Error(`Invalid trust store ${
|
|
54443
|
+
throw new Error(`Invalid trust store ${path12}: expected an object`);
|
|
54350
54444
|
}
|
|
54351
54445
|
const data = {};
|
|
54352
54446
|
for (const [key, value] of Object.entries(parsed)) {
|
|
54353
54447
|
if (value !== true && value !== false && value !== null) {
|
|
54354
|
-
throw new Error(`Invalid trust store ${
|
|
54448
|
+
throw new Error(`Invalid trust store ${path12}: value for ${JSON.stringify(key)} must be true, false, or null`);
|
|
54355
54449
|
}
|
|
54356
54450
|
data[key] = value;
|
|
54357
54451
|
}
|
|
54358
54452
|
return data;
|
|
54359
54453
|
}
|
|
54360
|
-
function writeTrustFile(
|
|
54454
|
+
function writeTrustFile(path12, data) {
|
|
54361
54455
|
const sorted = {};
|
|
54362
54456
|
for (const key of Object.keys(data).sort()) {
|
|
54363
54457
|
const value = data[key];
|
|
@@ -54365,19 +54459,19 @@ function writeTrustFile(path11, data) {
|
|
|
54365
54459
|
sorted[key] = value;
|
|
54366
54460
|
}
|
|
54367
54461
|
}
|
|
54368
|
-
mkdirSync10(dirname19(
|
|
54369
|
-
writeFileSync9(
|
|
54462
|
+
mkdirSync10(dirname19(path12), { recursive: true });
|
|
54463
|
+
writeFileSync9(path12, `${JSON.stringify(sorted, null, 2)}
|
|
54370
54464
|
`, "utf-8");
|
|
54371
54465
|
}
|
|
54372
|
-
function acquireTrustLockSync(
|
|
54373
|
-
const trustDir = dirname19(
|
|
54466
|
+
function acquireTrustLockSync(path12) {
|
|
54467
|
+
const trustDir = dirname19(path12);
|
|
54374
54468
|
mkdirSync10(trustDir, { recursive: true });
|
|
54375
54469
|
const maxAttempts = 10;
|
|
54376
54470
|
const delayMs = 20;
|
|
54377
54471
|
let lastError;
|
|
54378
54472
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
54379
54473
|
try {
|
|
54380
|
-
return lockfile3.lockSync(trustDir, { realpath: false, lockfilePath: `${
|
|
54474
|
+
return lockfile3.lockSync(trustDir, { realpath: false, lockfilePath: `${path12}.lock` });
|
|
54381
54475
|
} catch (error) {
|
|
54382
54476
|
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
54383
54477
|
if (code !== "ELOCKED" || attempt === maxAttempts) {
|
|
@@ -54394,8 +54488,8 @@ function acquireTrustLockSync(path11) {
|
|
|
54394
54488
|
}
|
|
54395
54489
|
throw new Error("Failed to acquire trust store lock");
|
|
54396
54490
|
}
|
|
54397
|
-
function withTrustFileLock(
|
|
54398
|
-
const release = acquireTrustLockSync(
|
|
54491
|
+
function withTrustFileLock(path12, fn) {
|
|
54492
|
+
const release = acquireTrustLockSync(path12);
|
|
54399
54493
|
try {
|
|
54400
54494
|
return fn();
|
|
54401
54495
|
} finally {
|
|
@@ -54442,8 +54536,8 @@ var ProjectTrustStore = class {
|
|
|
54442
54536
|
setMany(decisions) {
|
|
54443
54537
|
withTrustFileLock(this.trustPath, () => {
|
|
54444
54538
|
const data = readTrustFile(this.trustPath);
|
|
54445
|
-
for (const { path:
|
|
54446
|
-
const key = normalizeCwd(
|
|
54539
|
+
for (const { path: path12, decision } of decisions) {
|
|
54540
|
+
const key = normalizeCwd(path12);
|
|
54447
54541
|
if (decision === null) {
|
|
54448
54542
|
delete data[key];
|
|
54449
54543
|
} else {
|
|
@@ -54995,11 +55089,11 @@ function orderKeybindingsConfig(config) {
|
|
|
54995
55089
|
}
|
|
54996
55090
|
return ordered2;
|
|
54997
55091
|
}
|
|
54998
|
-
function loadRawConfig(
|
|
54999
|
-
if (!existsSync20(
|
|
55092
|
+
function loadRawConfig(path12) {
|
|
55093
|
+
if (!existsSync20(path12))
|
|
55000
55094
|
return void 0;
|
|
55001
55095
|
try {
|
|
55002
|
-
const parsed = JSON.parse(readFileSync15(
|
|
55096
|
+
const parsed = JSON.parse(readFileSync15(path12, "utf-8"));
|
|
55003
55097
|
if (typeof parsed !== "object" || parsed === null)
|
|
55004
55098
|
return void 0;
|
|
55005
55099
|
return parsed;
|
|
@@ -55026,8 +55120,8 @@ var KeybindingsManager2 = class _KeybindingsManager extends KeybindingsManager {
|
|
|
55026
55120
|
getEffectiveConfig() {
|
|
55027
55121
|
return this.getResolvedBindings();
|
|
55028
55122
|
}
|
|
55029
|
-
static loadFromFile(
|
|
55030
|
-
const rawConfig = loadRawConfig(
|
|
55123
|
+
static loadFromFile(path12) {
|
|
55124
|
+
const rawConfig = loadRawConfig(path12);
|
|
55031
55125
|
if (!rawConfig)
|
|
55032
55126
|
return {};
|
|
55033
55127
|
return toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);
|
|
@@ -55994,9 +56088,9 @@ Sign in to GitNexus to use ${APP_NAME}.
|
|
|
55994
56088
|
deviceName
|
|
55995
56089
|
};
|
|
55996
56090
|
await new GitNexusClient(config).callTool("list_repos", {}, AbortSignal.timeout(15e3));
|
|
55997
|
-
const
|
|
56091
|
+
const path12 = saveGitNexusConfig(config);
|
|
55998
56092
|
io.write(`
|
|
55999
|
-
Signed in. Credential saved to ${
|
|
56093
|
+
Signed in. Credential saved to ${path12}
|
|
56000
56094
|
|
|
56001
56095
|
`);
|
|
56002
56096
|
return true;
|
|
@@ -56173,14 +56267,14 @@ function filterAndSortSessions(sessions, query, sortMode, nameFilter = "all") {
|
|
|
56173
56267
|
}
|
|
56174
56268
|
|
|
56175
56269
|
// dist/modes/interactive/components/session-selector.js
|
|
56176
|
-
function shortenPath2(
|
|
56270
|
+
function shortenPath2(path12) {
|
|
56177
56271
|
const home = os3.homedir();
|
|
56178
|
-
if (!
|
|
56179
|
-
return
|
|
56180
|
-
if (
|
|
56181
|
-
return `~${
|
|
56272
|
+
if (!path12)
|
|
56273
|
+
return path12;
|
|
56274
|
+
if (path12.startsWith(home)) {
|
|
56275
|
+
return `~${path12.slice(home.length)}`;
|
|
56182
56276
|
}
|
|
56183
|
-
return
|
|
56277
|
+
return path12;
|
|
56184
56278
|
}
|
|
56185
56279
|
function formatSessionDate(date) {
|
|
56186
56280
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -56202,10 +56296,10 @@ function formatSessionDate(date) {
|
|
|
56202
56296
|
return `${Math.floor(diffDays / 30)}mo`;
|
|
56203
56297
|
return `${Math.floor(diffDays / 365)}y`;
|
|
56204
56298
|
}
|
|
56205
|
-
function canonicalizePath2(
|
|
56206
|
-
if (!
|
|
56207
|
-
return
|
|
56208
|
-
return canonicalizePath(
|
|
56299
|
+
function canonicalizePath2(path12) {
|
|
56300
|
+
if (!path12)
|
|
56301
|
+
return path12;
|
|
56302
|
+
return canonicalizePath(path12);
|
|
56209
56303
|
}
|
|
56210
56304
|
var SessionSelectorHeader = class {
|
|
56211
56305
|
scope;
|
|
@@ -56247,8 +56341,8 @@ var SessionSelectorHeader = class {
|
|
|
56247
56341
|
setShowRenameHint(show) {
|
|
56248
56342
|
this.showRenameHint = show;
|
|
56249
56343
|
}
|
|
56250
|
-
setConfirmingDeletePath(
|
|
56251
|
-
this.confirmingDeletePath =
|
|
56344
|
+
setConfirmingDeletePath(path12) {
|
|
56345
|
+
this.confirmingDeletePath = path12;
|
|
56252
56346
|
}
|
|
56253
56347
|
clearStatusTimeout() {
|
|
56254
56348
|
if (!this.statusTimeout)
|
|
@@ -56476,9 +56570,9 @@ var SessionList = class {
|
|
|
56476
56570
|
}
|
|
56477
56571
|
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredSessions.length - 1));
|
|
56478
56572
|
}
|
|
56479
|
-
setConfirmingDeletePath(
|
|
56480
|
-
this.confirmingDeletePath =
|
|
56481
|
-
this.onDeleteConfirmationChange?.(
|
|
56573
|
+
setConfirmingDeletePath(path12) {
|
|
56574
|
+
this.confirmingDeletePath = path12;
|
|
56575
|
+
this.onDeleteConfirmationChange?.(path12);
|
|
56482
56576
|
}
|
|
56483
56577
|
startDeleteConfirmationForSelectedSession() {
|
|
56484
56578
|
const selected = this.filteredSessions[this.selectedIndex];
|
|
@@ -56490,10 +56584,10 @@ var SessionList = class {
|
|
|
56490
56584
|
}
|
|
56491
56585
|
this.setConfirmingDeletePath(selected.session.path);
|
|
56492
56586
|
}
|
|
56493
|
-
isCurrentSessionPath(
|
|
56587
|
+
isCurrentSessionPath(path12) {
|
|
56494
56588
|
if (!this.currentSessionCanonicalPath)
|
|
56495
56589
|
return false;
|
|
56496
|
-
return (canonicalizePath2(
|
|
56590
|
+
return (canonicalizePath2(path12) ?? path12) === this.currentSessionCanonicalPath;
|
|
56497
56591
|
}
|
|
56498
56592
|
invalidate() {
|
|
56499
56593
|
}
|
|
@@ -56794,8 +56888,8 @@ var SessionSelectorComponent = class extends Container {
|
|
|
56794
56888
|
this.header.setShowPath(showPath);
|
|
56795
56889
|
this.requestRender();
|
|
56796
56890
|
};
|
|
56797
|
-
this.sessionList.onDeleteConfirmationChange = (
|
|
56798
|
-
this.header.setConfirmingDeletePath(
|
|
56891
|
+
this.sessionList.onDeleteConfirmationChange = (path12) => {
|
|
56892
|
+
this.header.setConfirmingDeletePath(path12);
|
|
56799
56893
|
this.requestRender();
|
|
56800
56894
|
};
|
|
56801
56895
|
this.sessionList.onError = (msg) => {
|
|
@@ -56971,11 +57065,11 @@ async function selectSession(currentSessionsLoader, allSessionsLoader, settingsM
|
|
|
56971
57065
|
const keybindings = KeybindingsManager2.create();
|
|
56972
57066
|
setKeybindings(keybindings);
|
|
56973
57067
|
let resolved = false;
|
|
56974
|
-
const selector = new SessionSelectorComponent(currentSessionsLoader, allSessionsLoader, (
|
|
57068
|
+
const selector = new SessionSelectorComponent(currentSessionsLoader, allSessionsLoader, (path12) => {
|
|
56975
57069
|
if (!resolved) {
|
|
56976
57070
|
resolved = true;
|
|
56977
57071
|
ui.stop();
|
|
56978
|
-
resolve15(
|
|
57072
|
+
resolve15(path12);
|
|
56979
57073
|
}
|
|
56980
57074
|
}, () => {
|
|
56981
57075
|
if (!resolved) {
|
|
@@ -57068,6 +57162,21 @@ function parseUsage2(value) {
|
|
|
57068
57162
|
...typeof usage.remaining === "number" ? { remaining: usage.remaining } : {}
|
|
57069
57163
|
};
|
|
57070
57164
|
}
|
|
57165
|
+
function parseDelegation(value) {
|
|
57166
|
+
if (!value || typeof value !== "object")
|
|
57167
|
+
return void 0;
|
|
57168
|
+
const delegation = value;
|
|
57169
|
+
if (delegation.enabled !== true || delegation.version !== 1 || typeof delegation.maxParallel !== "number" || !Number.isSafeInteger(delegation.maxParallel) || delegation.maxParallel < 1 || typeof delegation.maxTaskBytes !== "number" || !Number.isSafeInteger(delegation.maxTaskBytes) || delegation.maxTaskBytes < 1 || typeof delegation.workerTimeoutMs !== "number" || !Number.isSafeInteger(delegation.workerTimeoutMs) || delegation.workerTimeoutMs < 1) {
|
|
57170
|
+
return void 0;
|
|
57171
|
+
}
|
|
57172
|
+
return {
|
|
57173
|
+
enabled: true,
|
|
57174
|
+
version: 1,
|
|
57175
|
+
maxParallel: delegation.maxParallel,
|
|
57176
|
+
maxTaskBytes: delegation.maxTaskBytes,
|
|
57177
|
+
workerTimeoutMs: delegation.workerTimeoutMs
|
|
57178
|
+
};
|
|
57179
|
+
}
|
|
57071
57180
|
function formatCreditBalance(policy) {
|
|
57072
57181
|
if (!policy?.usage)
|
|
57073
57182
|
return void 0;
|
|
@@ -57077,16 +57186,17 @@ function formatCreditBalance(policy) {
|
|
|
57077
57186
|
function gatewayCachePath() {
|
|
57078
57187
|
return join32(dirname20(gitNexusConfigPath()), "gateway.json");
|
|
57079
57188
|
}
|
|
57080
|
-
function readGatewayCache(
|
|
57189
|
+
function readGatewayCache(path12 = gatewayCachePath()) {
|
|
57081
57190
|
try {
|
|
57082
|
-
const parsed = JSON.parse(readFileSync16(
|
|
57191
|
+
const parsed = JSON.parse(readFileSync16(path12, "utf8"));
|
|
57083
57192
|
if (typeof parsed.contextWindow !== "number" || typeof parsed.maxTokens !== "number")
|
|
57084
57193
|
return void 0;
|
|
57085
57194
|
return {
|
|
57086
57195
|
configured: parsed.configured === true,
|
|
57087
57196
|
contextWindow: parsed.contextWindow,
|
|
57088
57197
|
maxTokens: parsed.maxTokens,
|
|
57089
|
-
usage: parseUsage2(parsed.usage)
|
|
57198
|
+
usage: parseUsage2(parsed.usage),
|
|
57199
|
+
delegation: parseDelegation(parsed.delegation)
|
|
57090
57200
|
};
|
|
57091
57201
|
} catch {
|
|
57092
57202
|
return void 0;
|
|
@@ -57123,7 +57233,8 @@ async function refreshGatewayPolicy(config, options = {}) {
|
|
|
57123
57233
|
configured: body.configured === true,
|
|
57124
57234
|
contextWindow: body.contextWindow,
|
|
57125
57235
|
maxTokens: body.maxTokens,
|
|
57126
|
-
usage: parseUsage2(body.usage)
|
|
57236
|
+
usage: parseUsage2(body.usage),
|
|
57237
|
+
delegation: parseDelegation(body.delegation)
|
|
57127
57238
|
};
|
|
57128
57239
|
if (!existsSync23(dirname20(cachePath)))
|
|
57129
57240
|
mkdirSync11(dirname20(cachePath), { recursive: true, mode: 448 });
|
|
@@ -57176,9 +57287,9 @@ function registerAutoProvider(pi, config, policy) {
|
|
|
57176
57287
|
}
|
|
57177
57288
|
|
|
57178
57289
|
// dist/extensions/gitnexus/index.js
|
|
57179
|
-
import { existsSync as
|
|
57290
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
57180
57291
|
import { homedir as homedir11 } from "node:os";
|
|
57181
|
-
import { join as
|
|
57292
|
+
import { join as join35 } from "node:path";
|
|
57182
57293
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
57183
57294
|
|
|
57184
57295
|
// dist/core/graph-rail-store.js
|
|
@@ -57232,13 +57343,13 @@ var graphRailStore = {
|
|
|
57232
57343
|
state.query = query;
|
|
57233
57344
|
emit();
|
|
57234
57345
|
},
|
|
57235
|
-
recordChange(
|
|
57236
|
-
const existing = state.changes.find((c) => c.path ===
|
|
57346
|
+
recordChange(path12, added, removed) {
|
|
57347
|
+
const existing = state.changes.find((c) => c.path === path12);
|
|
57237
57348
|
if (existing) {
|
|
57238
57349
|
existing.added += added;
|
|
57239
57350
|
existing.removed += removed;
|
|
57240
57351
|
} else {
|
|
57241
|
-
state.changes.push({ path:
|
|
57352
|
+
state.changes.push({ path: path12, added, removed });
|
|
57242
57353
|
if (state.changes.length > 6)
|
|
57243
57354
|
state.changes.shift();
|
|
57244
57355
|
}
|
|
@@ -57258,6 +57369,546 @@ var graphRailStore = {
|
|
|
57258
57369
|
}
|
|
57259
57370
|
};
|
|
57260
57371
|
|
|
57372
|
+
// dist/extensions/subagent/index.js
|
|
57373
|
+
import { execFile as execFile2, spawn as spawn8 } from "node:child_process";
|
|
57374
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
57375
|
+
import * as fs6 from "node:fs";
|
|
57376
|
+
import * as os4 from "node:os";
|
|
57377
|
+
import * as path10 from "node:path";
|
|
57378
|
+
import { Type as Type17 } from "typebox";
|
|
57379
|
+
var DELEGATE_TASK_TOOL_NAME = "delegate_task";
|
|
57380
|
+
var INTERNAL_WORKER_MARKER_ENV = "NEXUS_INTERNAL_DELEGATED_WORKER";
|
|
57381
|
+
var INTERNAL_WORKER_SESSION_ENV = "NEXUS_INTERNAL_WORKER_SESSION_ID";
|
|
57382
|
+
var INTERNAL_WORKER_TASK_ENV = "NEXUS_INTERNAL_WORKER_TASK_ID";
|
|
57383
|
+
var INTERNAL_WORKER_RUN_ENV = "NEXUS_INTERNAL_WORKER_RUN_ID";
|
|
57384
|
+
var INTERNAL_WORKER_ROOT_REQUEST_ENV = "NEXUS_INTERNAL_WORKER_ROOT_REQUEST_ID";
|
|
57385
|
+
var INTERNAL_WORKER_PARENT_REQUEST_ENV = "NEXUS_INTERNAL_WORKER_PARENT_REQUEST_ID";
|
|
57386
|
+
var INTERNAL_WORKER_GRANT_HEADER = "x-nexus-worker-grant";
|
|
57387
|
+
var INTERNAL_WORKER_TASK_HEADER = "x-nexus-worker-task-id";
|
|
57388
|
+
var SESSION_AFFINITY_HEADER = "x-session-affinity";
|
|
57389
|
+
var RUN_ID_HEADER = "x-nexus-run-id";
|
|
57390
|
+
var REQUEST_ID_HEADER = "x-nexus-request-id";
|
|
57391
|
+
var ROOT_REQUEST_ID_HEADER = "x-nexus-root-request-id";
|
|
57392
|
+
var PARENT_REQUEST_ID_HEADER = "x-nexus-parent-request-id";
|
|
57393
|
+
var DELEGATION_ID_HEADER = "x-nexus-delegation-id";
|
|
57394
|
+
var REQUEST_SCOPE_HEADER = "x-nexus-request-scope";
|
|
57395
|
+
var MAX_DELEGATED_TURNS = 12;
|
|
57396
|
+
var MAX_DELEGATIONS_PER_RUN = 3;
|
|
57397
|
+
var DELEGATED_WORKER_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
57398
|
+
var DELEGATED_OUTPUT_CAP_BYTES = 32 * 1024;
|
|
57399
|
+
var DELEGATED_EVENT_CAP_BYTES = 1024 * 1024;
|
|
57400
|
+
var MAX_DELEGATED_TASK_BYTES = 32 * 1024;
|
|
57401
|
+
var WORKER_GRANT_TIMEOUT_MS = 1e4;
|
|
57402
|
+
var INVALID_WORKER_GRANT = "unavailable";
|
|
57403
|
+
var MAX_ROOT_REVIEW_TOOL_CALLS = 8;
|
|
57404
|
+
var MAX_PARALLEL_MUTATING_WORKERS = 1;
|
|
57405
|
+
var ROOT_REVIEW_TOOLS = /* @__PURE__ */ new Set([
|
|
57406
|
+
"read",
|
|
57407
|
+
"grep",
|
|
57408
|
+
"find",
|
|
57409
|
+
"ls",
|
|
57410
|
+
"gitnexus_query",
|
|
57411
|
+
"gitnexus_context",
|
|
57412
|
+
"gitnexus_impact",
|
|
57413
|
+
"gitnexus_detect_changes",
|
|
57414
|
+
"gitnexus_cypher",
|
|
57415
|
+
"gitnexus_list_repos",
|
|
57416
|
+
"web_search",
|
|
57417
|
+
"web_fetch"
|
|
57418
|
+
]);
|
|
57419
|
+
var DELEGATED_WORKER_TOOLS = [
|
|
57420
|
+
"read",
|
|
57421
|
+
"grep",
|
|
57422
|
+
"find",
|
|
57423
|
+
"ls",
|
|
57424
|
+
"bash",
|
|
57425
|
+
"write",
|
|
57426
|
+
"edit",
|
|
57427
|
+
"gitnexus_query",
|
|
57428
|
+
"gitnexus_context",
|
|
57429
|
+
"gitnexus_impact",
|
|
57430
|
+
"gitnexus_detect_changes",
|
|
57431
|
+
"gitnexus_cypher",
|
|
57432
|
+
"gitnexus_list_repos"
|
|
57433
|
+
];
|
|
57434
|
+
var WORKER_SYSTEM_PROMPT = `You are an internal implementation worker for Nexus Agent.
|
|
57435
|
+
|
|
57436
|
+
Complete only the narrowly delegated task. Inspect the repository before editing, follow its local instructions, and verify the changed behavior. Do not delegate work or broaden scope. Do not discuss model names, providers, routing, credits, or internal architecture.
|
|
57437
|
+
|
|
57438
|
+
Finish with a concise report containing:
|
|
57439
|
+
- changes made
|
|
57440
|
+
- verification run and results
|
|
57441
|
+
- blockers or remaining risks`;
|
|
57442
|
+
function isRecord(value) {
|
|
57443
|
+
return typeof value === "object" && value !== null;
|
|
57444
|
+
}
|
|
57445
|
+
function parseAssistantSnapshot(value) {
|
|
57446
|
+
if (!isRecord(value) || value.role !== "assistant" || !Array.isArray(value.content))
|
|
57447
|
+
return void 0;
|
|
57448
|
+
const text = value.content.filter(isRecord).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n");
|
|
57449
|
+
return {
|
|
57450
|
+
text,
|
|
57451
|
+
...typeof value.stopReason === "string" ? { stopReason: value.stopReason } : {}
|
|
57452
|
+
};
|
|
57453
|
+
}
|
|
57454
|
+
function composeDelegatedTask(task, acceptanceCriteria, relevantPaths) {
|
|
57455
|
+
const sections = [`Task:
|
|
57456
|
+
${task.trim()}`];
|
|
57457
|
+
if (acceptanceCriteria.length > 0) {
|
|
57458
|
+
sections.push(`Acceptance criteria:
|
|
57459
|
+
${acceptanceCriteria.map((criterion) => `- ${criterion}`).join("\n")}`);
|
|
57460
|
+
}
|
|
57461
|
+
if (relevantPaths.length > 0) {
|
|
57462
|
+
sections.push(`Relevant paths:
|
|
57463
|
+
${relevantPaths.map((filePath) => `- ${filePath}`).join("\n")}`);
|
|
57464
|
+
}
|
|
57465
|
+
return sections.join("\n\n");
|
|
57466
|
+
}
|
|
57467
|
+
function buildDelegatedWorkerArgs(task, promptPath) {
|
|
57468
|
+
return [
|
|
57469
|
+
"--mode",
|
|
57470
|
+
"json",
|
|
57471
|
+
"-p",
|
|
57472
|
+
"--no-session",
|
|
57473
|
+
"--model",
|
|
57474
|
+
`${AUTO_PROVIDER_ID}/${AUTO_MODEL_ID}`,
|
|
57475
|
+
"--tools",
|
|
57476
|
+
DELEGATED_WORKER_TOOLS.join(","),
|
|
57477
|
+
"--exclude-tools",
|
|
57478
|
+
`${DELEGATE_TASK_TOOL_NAME},subagent`,
|
|
57479
|
+
"--append-system-prompt",
|
|
57480
|
+
promptPath,
|
|
57481
|
+
task
|
|
57482
|
+
];
|
|
57483
|
+
}
|
|
57484
|
+
function getNexusInvocation(args) {
|
|
57485
|
+
const currentScript = process.argv[1];
|
|
57486
|
+
const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/");
|
|
57487
|
+
if (currentScript && !isBunVirtualScript && fs6.existsSync(currentScript)) {
|
|
57488
|
+
return { command: process.execPath, args: [currentScript, ...args] };
|
|
57489
|
+
}
|
|
57490
|
+
const execName = path10.basename(process.execPath).toLowerCase();
|
|
57491
|
+
const isGenericRuntime = /^(node|bun)(\.exe)?$/.test(execName);
|
|
57492
|
+
return isGenericRuntime ? { command: "nexus", args } : { command: process.execPath, args };
|
|
57493
|
+
}
|
|
57494
|
+
async function writeWorkerPrompt() {
|
|
57495
|
+
const dir = await fs6.promises.mkdtemp(path10.join(os4.tmpdir(), "nexus-worker-"));
|
|
57496
|
+
const filePath = path10.join(dir, "system.md");
|
|
57497
|
+
await withFileMutationQueue2(filePath, async () => {
|
|
57498
|
+
await fs6.promises.writeFile(filePath, WORKER_SYSTEM_PROMPT, { encoding: "utf8", mode: 384 });
|
|
57499
|
+
});
|
|
57500
|
+
return { dir, filePath };
|
|
57501
|
+
}
|
|
57502
|
+
function truncateUtf8(value, cap) {
|
|
57503
|
+
if (Buffer.byteLength(value, "utf8") <= cap)
|
|
57504
|
+
return { value, truncated: false };
|
|
57505
|
+
const suffix = "\n\n[Report truncated]";
|
|
57506
|
+
let truncated = value.slice(0, Math.max(0, cap - Buffer.byteLength(suffix, "utf8")));
|
|
57507
|
+
while (Buffer.byteLength(`${truncated}${suffix}`, "utf8") > cap)
|
|
57508
|
+
truncated = truncated.slice(0, -1);
|
|
57509
|
+
return { value: `${truncated}${suffix}`, truncated: true };
|
|
57510
|
+
}
|
|
57511
|
+
function createHubDelegationController(config, options = {}) {
|
|
57512
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
57513
|
+
return {
|
|
57514
|
+
async createWorkerGrant(request) {
|
|
57515
|
+
const controller = new AbortController();
|
|
57516
|
+
const onAbort = () => controller.abort();
|
|
57517
|
+
if (request.signal?.aborted)
|
|
57518
|
+
controller.abort();
|
|
57519
|
+
else
|
|
57520
|
+
request.signal?.addEventListener("abort", onAbort, { once: true });
|
|
57521
|
+
const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? WORKER_GRANT_TIMEOUT_MS);
|
|
57522
|
+
try {
|
|
57523
|
+
const response = await fetchImpl(`${hubApiBase(config.hubUrl)}/llm/worker-grants`, {
|
|
57524
|
+
method: "POST",
|
|
57525
|
+
headers: {
|
|
57526
|
+
"content-type": "application/json",
|
|
57527
|
+
accept: "application/json",
|
|
57528
|
+
authorization: `Bearer ${config.token}`,
|
|
57529
|
+
[RUN_ID_HEADER]: request.runId,
|
|
57530
|
+
[REQUEST_ID_HEADER]: request.requestId,
|
|
57531
|
+
[ROOT_REQUEST_ID_HEADER]: request.rootRequestId,
|
|
57532
|
+
[PARENT_REQUEST_ID_HEADER]: request.parentRequestId,
|
|
57533
|
+
[DELEGATION_ID_HEADER]: request.taskId,
|
|
57534
|
+
[REQUEST_SCOPE_HEADER]: "worker",
|
|
57535
|
+
...config.deviceFingerprint ? { "x-device-fingerprint": config.deviceFingerprint } : {},
|
|
57536
|
+
...config.deviceName ? { "x-device-name": config.deviceName } : {}
|
|
57537
|
+
},
|
|
57538
|
+
body: JSON.stringify({ sessionId: request.sessionId, taskId: request.taskId }),
|
|
57539
|
+
signal: controller.signal
|
|
57540
|
+
});
|
|
57541
|
+
if (!response.ok) {
|
|
57542
|
+
await response.body?.cancel().catch(() => {
|
|
57543
|
+
});
|
|
57544
|
+
throw new Error("Worker authorization unavailable");
|
|
57545
|
+
}
|
|
57546
|
+
const body = await response.json();
|
|
57547
|
+
if (!isRecord(body) || typeof body.grant !== "string" || !body.grant.trim() || typeof body.expiresAt !== "string" || !body.expiresAt.trim() || !Number.isFinite(Date.parse(body.expiresAt))) {
|
|
57548
|
+
throw new Error("Invalid worker authorization response");
|
|
57549
|
+
}
|
|
57550
|
+
return { token: body.grant, expiresAt: body.expiresAt };
|
|
57551
|
+
} finally {
|
|
57552
|
+
clearTimeout(timeout);
|
|
57553
|
+
request.signal?.removeEventListener("abort", onAbort);
|
|
57554
|
+
}
|
|
57555
|
+
}
|
|
57556
|
+
};
|
|
57557
|
+
}
|
|
57558
|
+
function isDelegatedWorkerProcess(env = process.env) {
|
|
57559
|
+
return env[INTERNAL_WORKER_MARKER_ENV] === "1";
|
|
57560
|
+
}
|
|
57561
|
+
function consumeWorkerContext(env = process.env) {
|
|
57562
|
+
if (!isDelegatedWorkerProcess(env))
|
|
57563
|
+
return void 0;
|
|
57564
|
+
const sessionId = env[INTERNAL_WORKER_SESSION_ENV]?.trim();
|
|
57565
|
+
const taskId = env[INTERNAL_WORKER_TASK_ENV]?.trim();
|
|
57566
|
+
const runId = env[INTERNAL_WORKER_RUN_ENV]?.trim();
|
|
57567
|
+
const rootRequestId = env[INTERNAL_WORKER_ROOT_REQUEST_ENV]?.trim();
|
|
57568
|
+
const parentRequestId = env[INTERNAL_WORKER_PARENT_REQUEST_ENV]?.trim();
|
|
57569
|
+
delete env[INTERNAL_WORKER_SESSION_ENV];
|
|
57570
|
+
delete env[INTERNAL_WORKER_TASK_ENV];
|
|
57571
|
+
delete env[INTERNAL_WORKER_RUN_ENV];
|
|
57572
|
+
delete env[INTERNAL_WORKER_ROOT_REQUEST_ENV];
|
|
57573
|
+
delete env[INTERNAL_WORKER_PARENT_REQUEST_ENV];
|
|
57574
|
+
if (!sessionId || !taskId || !runId || !rootRequestId || !parentRequestId)
|
|
57575
|
+
return void 0;
|
|
57576
|
+
return { sessionId, taskId, runId, rootRequestId, parentRequestId };
|
|
57577
|
+
}
|
|
57578
|
+
function killProcessTree2(pid, signal) {
|
|
57579
|
+
if (pid === void 0)
|
|
57580
|
+
return;
|
|
57581
|
+
if (process.platform === "win32") {
|
|
57582
|
+
execFile2("taskkill", ["/T", "/F", "/PID", String(pid)], () => void 0);
|
|
57583
|
+
return;
|
|
57584
|
+
}
|
|
57585
|
+
try {
|
|
57586
|
+
process.kill(-pid, signal);
|
|
57587
|
+
} catch {
|
|
57588
|
+
}
|
|
57589
|
+
}
|
|
57590
|
+
async function runDelegatedWorker(options) {
|
|
57591
|
+
const prompt = await writeWorkerPrompt();
|
|
57592
|
+
const task = composeDelegatedTask(options.task, options.acceptanceCriteria, options.relevantPaths);
|
|
57593
|
+
const args = buildDelegatedWorkerArgs(task, prompt.filePath);
|
|
57594
|
+
let output = "";
|
|
57595
|
+
let turns = 0;
|
|
57596
|
+
let terminalStatus;
|
|
57597
|
+
let assistantFailed = false;
|
|
57598
|
+
let eventBytes = 0;
|
|
57599
|
+
try {
|
|
57600
|
+
const exitCode = await new Promise((resolve15) => {
|
|
57601
|
+
const invocation = getNexusInvocation(args);
|
|
57602
|
+
const child = spawn8(invocation.command, invocation.args, {
|
|
57603
|
+
cwd: options.cwd,
|
|
57604
|
+
detached: true,
|
|
57605
|
+
env: {
|
|
57606
|
+
...process.env,
|
|
57607
|
+
[INTERNAL_WORKER_MARKER_ENV]: "1",
|
|
57608
|
+
[INTERNAL_WORKER_SESSION_ENV]: options.workerContext.sessionId,
|
|
57609
|
+
[INTERNAL_WORKER_TASK_ENV]: options.workerContext.taskId,
|
|
57610
|
+
[INTERNAL_WORKER_RUN_ENV]: options.workerContext.runId,
|
|
57611
|
+
[INTERNAL_WORKER_ROOT_REQUEST_ENV]: options.workerContext.rootRequestId,
|
|
57612
|
+
[INTERNAL_WORKER_PARENT_REQUEST_ENV]: options.workerContext.parentRequestId
|
|
57613
|
+
},
|
|
57614
|
+
shell: false,
|
|
57615
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
57616
|
+
windowsHide: true
|
|
57617
|
+
});
|
|
57618
|
+
let buffer = "";
|
|
57619
|
+
let settled = false;
|
|
57620
|
+
let stopped = false;
|
|
57621
|
+
let forceKillTimer;
|
|
57622
|
+
const finish = (code) => {
|
|
57623
|
+
if (settled)
|
|
57624
|
+
return;
|
|
57625
|
+
settled = true;
|
|
57626
|
+
clearTimeout(timeoutTimer);
|
|
57627
|
+
clearTimeout(forceKillTimer);
|
|
57628
|
+
options.signal?.removeEventListener("abort", abortHandler);
|
|
57629
|
+
resolve15(code);
|
|
57630
|
+
};
|
|
57631
|
+
const stop = (status2) => {
|
|
57632
|
+
if (stopped)
|
|
57633
|
+
return;
|
|
57634
|
+
stopped = true;
|
|
57635
|
+
terminalStatus = status2;
|
|
57636
|
+
killProcessTree2(child.pid, "SIGTERM");
|
|
57637
|
+
forceKillTimer = setTimeout(() => {
|
|
57638
|
+
if (process.platform !== "win32")
|
|
57639
|
+
killProcessTree2(child.pid, "SIGKILL");
|
|
57640
|
+
finish(1);
|
|
57641
|
+
}, 5e3);
|
|
57642
|
+
};
|
|
57643
|
+
const emitProgress = () => {
|
|
57644
|
+
options.onUpdate?.({
|
|
57645
|
+
content: [{ type: "text", text: "Delegated work is in progress." }],
|
|
57646
|
+
details: { status: "running", turns }
|
|
57647
|
+
});
|
|
57648
|
+
};
|
|
57649
|
+
const processLine = (line) => {
|
|
57650
|
+
if (!line.trim())
|
|
57651
|
+
return;
|
|
57652
|
+
let parsed;
|
|
57653
|
+
try {
|
|
57654
|
+
parsed = JSON.parse(line);
|
|
57655
|
+
} catch {
|
|
57656
|
+
return;
|
|
57657
|
+
}
|
|
57658
|
+
if (!isRecord(parsed) || parsed.type !== "message_end")
|
|
57659
|
+
return;
|
|
57660
|
+
const snapshot = parseAssistantSnapshot(parsed.message);
|
|
57661
|
+
if (!snapshot)
|
|
57662
|
+
return;
|
|
57663
|
+
turns += 1;
|
|
57664
|
+
if (snapshot.text)
|
|
57665
|
+
output = snapshot.text;
|
|
57666
|
+
if (snapshot.stopReason === "error" || snapshot.stopReason === "aborted")
|
|
57667
|
+
assistantFailed = true;
|
|
57668
|
+
emitProgress();
|
|
57669
|
+
if (turns >= MAX_DELEGATED_TURNS)
|
|
57670
|
+
stop("turn_limit");
|
|
57671
|
+
};
|
|
57672
|
+
const abortHandler = () => stop("aborted");
|
|
57673
|
+
const timeoutTimer = setTimeout(() => stop("timeout"), Math.min(Math.max(1e3, options.timeoutMs ?? DELEGATED_WORKER_TIMEOUT_MS), DELEGATED_WORKER_TIMEOUT_MS));
|
|
57674
|
+
child.stdout.on("data", (chunk) => {
|
|
57675
|
+
eventBytes += Buffer.byteLength(chunk);
|
|
57676
|
+
if (eventBytes > DELEGATED_EVENT_CAP_BYTES) {
|
|
57677
|
+
assistantFailed = true;
|
|
57678
|
+
stop("event_limit");
|
|
57679
|
+
return;
|
|
57680
|
+
}
|
|
57681
|
+
buffer += chunk.toString();
|
|
57682
|
+
if (Buffer.byteLength(buffer, "utf8") > DELEGATED_EVENT_CAP_BYTES) {
|
|
57683
|
+
buffer = "";
|
|
57684
|
+
assistantFailed = true;
|
|
57685
|
+
return;
|
|
57686
|
+
}
|
|
57687
|
+
const lines = buffer.split("\n");
|
|
57688
|
+
buffer = lines.pop() ?? "";
|
|
57689
|
+
for (const line of lines)
|
|
57690
|
+
processLine(line);
|
|
57691
|
+
});
|
|
57692
|
+
child.stderr.on("data", () => void 0);
|
|
57693
|
+
child.on("close", (code) => {
|
|
57694
|
+
if (buffer.trim())
|
|
57695
|
+
processLine(buffer);
|
|
57696
|
+
finish(code ?? (terminalStatus ? 1 : 0));
|
|
57697
|
+
});
|
|
57698
|
+
child.on("error", () => finish(1));
|
|
57699
|
+
if (options.signal?.aborted)
|
|
57700
|
+
abortHandler();
|
|
57701
|
+
else
|
|
57702
|
+
options.signal?.addEventListener("abort", abortHandler, { once: true });
|
|
57703
|
+
});
|
|
57704
|
+
const limitedOutput = truncateUtf8(output, DELEGATED_OUTPUT_CAP_BYTES);
|
|
57705
|
+
const status = terminalStatus ?? (exitCode === 0 && !assistantFailed ? "completed" : "failed");
|
|
57706
|
+
return {
|
|
57707
|
+
status,
|
|
57708
|
+
turns,
|
|
57709
|
+
exitCode,
|
|
57710
|
+
output: limitedOutput.value,
|
|
57711
|
+
outputTruncated: limitedOutput.truncated
|
|
57712
|
+
};
|
|
57713
|
+
} finally {
|
|
57714
|
+
await fs6.promises.rm(prompt.dir, { recursive: true, force: true });
|
|
57715
|
+
}
|
|
57716
|
+
}
|
|
57717
|
+
var DelegateTaskParameters = Type17.Object({
|
|
57718
|
+
task: Type17.String({ description: "A narrow implementation task with explicit boundaries", maxLength: 32768 }),
|
|
57719
|
+
acceptanceCriteria: Type17.Optional(Type17.Array(Type17.String({ maxLength: 2e3 }), { maxItems: 10 })),
|
|
57720
|
+
relevantPaths: Type17.Optional(Type17.Array(Type17.String({ maxLength: 1e3 }), { maxItems: 20 }))
|
|
57721
|
+
});
|
|
57722
|
+
function resultContent(result) {
|
|
57723
|
+
const report = result.output.trim() || "No implementation report was returned.";
|
|
57724
|
+
if (result.status === "completed")
|
|
57725
|
+
return `Delegated implementation completed.
|
|
57726
|
+
|
|
57727
|
+
${report}`;
|
|
57728
|
+
return `Delegated implementation did not complete (${result.status}).
|
|
57729
|
+
|
|
57730
|
+
Partial report:
|
|
57731
|
+
${report}`;
|
|
57732
|
+
}
|
|
57733
|
+
function registerDelegateTaskTool(pi, capability) {
|
|
57734
|
+
const maxTaskBytes = Math.min(Math.max(1, Math.floor(capability.maxTaskBytes)), MAX_DELEGATED_TASK_BYTES);
|
|
57735
|
+
const workerTimeoutMs = Math.min(Math.max(1e3, Math.floor(capability.workerTimeoutMs)), DELEGATED_WORKER_TIMEOUT_MS);
|
|
57736
|
+
const runId = randomUUID3();
|
|
57737
|
+
let rootRequestId;
|
|
57738
|
+
let latestRootRequestId;
|
|
57739
|
+
let activeWorkers = 0;
|
|
57740
|
+
let invocationCount = 0;
|
|
57741
|
+
let rootReviewToolCalls = 0;
|
|
57742
|
+
pi.on("before_agent_start", (event) => {
|
|
57743
|
+
invocationCount = 0;
|
|
57744
|
+
rootReviewToolCalls = 0;
|
|
57745
|
+
return {
|
|
57746
|
+
systemPrompt: `${event.systemPrompt}
|
|
57747
|
+
|
|
57748
|
+
Implementation policy: perform implementation, mutation, shell, and repeated tool loops through delegate_task. Keep this parent conversation focused on planning and final review. Use only bounded read-only tools to inspect worker changes, verify graph impact, and reach the final answer.`
|
|
57749
|
+
};
|
|
57750
|
+
});
|
|
57751
|
+
pi.on("before_provider_headers", (event, ctx) => {
|
|
57752
|
+
if (!isAutoModel(ctx.model) || isDelegatedWorkerProcess())
|
|
57753
|
+
return;
|
|
57754
|
+
const requestId = randomUUID3();
|
|
57755
|
+
rootRequestId ??= requestId;
|
|
57756
|
+
latestRootRequestId = requestId;
|
|
57757
|
+
event.headers[RUN_ID_HEADER] = runId;
|
|
57758
|
+
event.headers[REQUEST_ID_HEADER] = requestId;
|
|
57759
|
+
event.headers[ROOT_REQUEST_ID_HEADER] = rootRequestId;
|
|
57760
|
+
event.headers[REQUEST_SCOPE_HEADER] = "root";
|
|
57761
|
+
});
|
|
57762
|
+
pi.on("tool_call", (event, ctx) => {
|
|
57763
|
+
if (!isAutoModel(ctx.model) || isDelegatedWorkerProcess() || event.toolName === DELEGATE_TASK_TOOL_NAME) {
|
|
57764
|
+
return;
|
|
57765
|
+
}
|
|
57766
|
+
if (!ROOT_REVIEW_TOOLS.has(event.toolName)) {
|
|
57767
|
+
return {
|
|
57768
|
+
block: true,
|
|
57769
|
+
reason: "This parent run is review-only. Use delegate_task for implementation, mutation, shell commands, tests, or other execution."
|
|
57770
|
+
};
|
|
57771
|
+
}
|
|
57772
|
+
if (rootReviewToolCalls >= MAX_ROOT_REVIEW_TOOL_CALLS) {
|
|
57773
|
+
return {
|
|
57774
|
+
block: true,
|
|
57775
|
+
reason: "The bounded parent review budget is exhausted. Delegate further investigation or finalize the review."
|
|
57776
|
+
};
|
|
57777
|
+
}
|
|
57778
|
+
rootReviewToolCalls += 1;
|
|
57779
|
+
});
|
|
57780
|
+
pi.registerTool({
|
|
57781
|
+
name: DELEGATE_TASK_TOOL_NAME,
|
|
57782
|
+
label: "Work",
|
|
57783
|
+
description: "Delegate one narrow implementation task to an isolated internal worker. Keep planning, user communication, and final verification in this conversation.",
|
|
57784
|
+
promptGuidelines: [
|
|
57785
|
+
"Use delegate_task for bounded implementation, mutation, command execution, tests, and repeated tool work after you have formed a plan.",
|
|
57786
|
+
"You remain responsible for reviewing the returned report, verifying the result, and communicating with the user."
|
|
57787
|
+
],
|
|
57788
|
+
parameters: DelegateTaskParameters,
|
|
57789
|
+
executionMode: "sequential",
|
|
57790
|
+
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
57791
|
+
if (!isAutoModel(ctx.model)) {
|
|
57792
|
+
return {
|
|
57793
|
+
content: [{ type: "text", text: "Delegated work is unavailable for the active mode." }],
|
|
57794
|
+
details: { status: "failed", turns: 0 }
|
|
57795
|
+
};
|
|
57796
|
+
}
|
|
57797
|
+
if (!ctx.isProjectTrusted()) {
|
|
57798
|
+
return {
|
|
57799
|
+
content: [{ type: "text", text: "Delegated work requires a trusted project." }],
|
|
57800
|
+
details: { status: "failed", turns: 0 }
|
|
57801
|
+
};
|
|
57802
|
+
}
|
|
57803
|
+
if (activeWorkers >= MAX_PARALLEL_MUTATING_WORKERS || invocationCount >= MAX_DELEGATIONS_PER_RUN) {
|
|
57804
|
+
return {
|
|
57805
|
+
content: [{ type: "text", text: "Delegated work is temporarily unavailable for this run." }],
|
|
57806
|
+
details: { status: "failed", turns: 0 }
|
|
57807
|
+
};
|
|
57808
|
+
}
|
|
57809
|
+
const request = {
|
|
57810
|
+
task: params.task,
|
|
57811
|
+
acceptanceCriteria: params.acceptanceCriteria ?? [],
|
|
57812
|
+
relevantPaths: params.relevantPaths ?? [],
|
|
57813
|
+
cwd: ctx.cwd,
|
|
57814
|
+
signal
|
|
57815
|
+
};
|
|
57816
|
+
if (Buffer.byteLength(composeDelegatedTask(request.task, request.acceptanceCriteria, request.relevantPaths), "utf8") > maxTaskBytes) {
|
|
57817
|
+
return {
|
|
57818
|
+
content: [{ type: "text", text: "Delegated work is too large for one bounded task." }],
|
|
57819
|
+
details: { status: "failed", turns: 0 }
|
|
57820
|
+
};
|
|
57821
|
+
}
|
|
57822
|
+
activeWorkers += 1;
|
|
57823
|
+
invocationCount += 1;
|
|
57824
|
+
try {
|
|
57825
|
+
const delegationId = randomUUID3();
|
|
57826
|
+
rootRequestId ??= randomUUID3();
|
|
57827
|
+
const result = await runDelegatedWorker({
|
|
57828
|
+
...request,
|
|
57829
|
+
workerContext: {
|
|
57830
|
+
sessionId: ctx.sessionManager.getSessionId(),
|
|
57831
|
+
taskId: delegationId,
|
|
57832
|
+
runId,
|
|
57833
|
+
rootRequestId,
|
|
57834
|
+
parentRequestId: latestRootRequestId ?? rootRequestId
|
|
57835
|
+
},
|
|
57836
|
+
timeoutMs: workerTimeoutMs,
|
|
57837
|
+
onUpdate
|
|
57838
|
+
});
|
|
57839
|
+
return {
|
|
57840
|
+
content: [{ type: "text", text: resultContent(result) }],
|
|
57841
|
+
details: {
|
|
57842
|
+
status: result.status,
|
|
57843
|
+
turns: result.turns,
|
|
57844
|
+
exitCode: result.exitCode,
|
|
57845
|
+
outputTruncated: result.outputTruncated
|
|
57846
|
+
}
|
|
57847
|
+
};
|
|
57848
|
+
} catch {
|
|
57849
|
+
return {
|
|
57850
|
+
content: [{ type: "text", text: "Delegated work could not be started." }],
|
|
57851
|
+
details: { status: "failed", turns: 0 }
|
|
57852
|
+
};
|
|
57853
|
+
} finally {
|
|
57854
|
+
activeWorkers -= 1;
|
|
57855
|
+
}
|
|
57856
|
+
},
|
|
57857
|
+
renderCall(_args, theme2) {
|
|
57858
|
+
return new Text(theme2.fg("toolTitle", theme2.bold("Working\u2026")), 0, 0);
|
|
57859
|
+
},
|
|
57860
|
+
renderResult(result, _options, theme2) {
|
|
57861
|
+
const details = result.details;
|
|
57862
|
+
if (details?.status === "running")
|
|
57863
|
+
return new Text(theme2.fg("muted", "Working\u2026"), 0, 0);
|
|
57864
|
+
if (details?.status === "completed")
|
|
57865
|
+
return new Text(theme2.fg("success", "Work completed"), 0, 0);
|
|
57866
|
+
return new Text(theme2.fg("error", "Work needs attention"), 0, 0);
|
|
57867
|
+
}
|
|
57868
|
+
});
|
|
57869
|
+
}
|
|
57870
|
+
function registerWorkerGrantHeaders(pi, workerContext, controller) {
|
|
57871
|
+
pi.on("before_provider_headers", async (event, ctx) => {
|
|
57872
|
+
if (!isAutoModel(ctx.model)) {
|
|
57873
|
+
ctx.abort();
|
|
57874
|
+
return;
|
|
57875
|
+
}
|
|
57876
|
+
const requestId = randomUUID3();
|
|
57877
|
+
event.headers[INTERNAL_WORKER_GRANT_HEADER] = INVALID_WORKER_GRANT;
|
|
57878
|
+
event.headers[INTERNAL_WORKER_TASK_HEADER] = workerContext.taskId;
|
|
57879
|
+
event.headers[SESSION_AFFINITY_HEADER] = workerContext.sessionId;
|
|
57880
|
+
event.headers[RUN_ID_HEADER] = workerContext.runId;
|
|
57881
|
+
event.headers[REQUEST_ID_HEADER] = requestId;
|
|
57882
|
+
event.headers[ROOT_REQUEST_ID_HEADER] = workerContext.rootRequestId;
|
|
57883
|
+
event.headers[PARENT_REQUEST_ID_HEADER] = workerContext.parentRequestId;
|
|
57884
|
+
event.headers[DELEGATION_ID_HEADER] = workerContext.taskId;
|
|
57885
|
+
event.headers[REQUEST_SCOPE_HEADER] = "worker";
|
|
57886
|
+
if (!controller)
|
|
57887
|
+
return;
|
|
57888
|
+
const grant = await controller.createWorkerGrant({
|
|
57889
|
+
...workerContext,
|
|
57890
|
+
requestId,
|
|
57891
|
+
signal: ctx.signal
|
|
57892
|
+
});
|
|
57893
|
+
event.headers[INTERNAL_WORKER_GRANT_HEADER] = grant.token;
|
|
57894
|
+
});
|
|
57895
|
+
}
|
|
57896
|
+
function delegatedWorkerRuntime(pi) {
|
|
57897
|
+
const isWorker = isDelegatedWorkerProcess();
|
|
57898
|
+
const workerContext = consumeWorkerContext();
|
|
57899
|
+
if (!isWorker)
|
|
57900
|
+
return;
|
|
57901
|
+
const config = resolveGitNexusConfig();
|
|
57902
|
+
const failClosedContext = {
|
|
57903
|
+
sessionId: "unavailable",
|
|
57904
|
+
taskId: "unavailable",
|
|
57905
|
+
runId: "unavailable",
|
|
57906
|
+
rootRequestId: "unavailable",
|
|
57907
|
+
parentRequestId: "unavailable"
|
|
57908
|
+
};
|
|
57909
|
+
registerWorkerGrantHeaders(pi, workerContext ?? failClosedContext, workerContext && config ? createHubDelegationController(config) : void 0);
|
|
57910
|
+
}
|
|
57911
|
+
|
|
57261
57912
|
// dist/extensions/gitnexus/augment.js
|
|
57262
57913
|
var AUGMENT_TIMEOUT_MS = 3e3;
|
|
57263
57914
|
var AUGMENT_MAX_CHARS = 1500;
|
|
@@ -57330,11 +57981,11 @@ function registerChangeTracking(pi, cwd) {
|
|
|
57330
57981
|
execute: async (id, params, signal, onUpdate, ctx) => {
|
|
57331
57982
|
const result = await edit.execute(id, params, signal, onUpdate, ctx);
|
|
57332
57983
|
try {
|
|
57333
|
-
const
|
|
57984
|
+
const path12 = String(params?.path ?? "");
|
|
57334
57985
|
const diff = result.details?.diff;
|
|
57335
57986
|
const { added, removed } = countDiff(diff);
|
|
57336
|
-
if (
|
|
57337
|
-
graphRailStore.recordChange(
|
|
57987
|
+
if (path12 && (added > 0 || removed > 0))
|
|
57988
|
+
graphRailStore.recordChange(path12, added, removed);
|
|
57338
57989
|
} catch {
|
|
57339
57990
|
}
|
|
57340
57991
|
return result;
|
|
@@ -57346,10 +57997,10 @@ function registerChangeTracking(pi, cwd) {
|
|
|
57346
57997
|
const result = await write.execute(id, params, signal, onUpdate, ctx);
|
|
57347
57998
|
try {
|
|
57348
57999
|
const p = params;
|
|
57349
|
-
const
|
|
58000
|
+
const path12 = String(p?.path ?? "");
|
|
57350
58001
|
const lineCount = String(p?.content ?? "").split("\n").length;
|
|
57351
|
-
if (
|
|
57352
|
-
graphRailStore.recordChange(
|
|
58002
|
+
if (path12)
|
|
58003
|
+
graphRailStore.recordChange(path12, lineCount, 0);
|
|
57353
58004
|
} catch {
|
|
57354
58005
|
}
|
|
57355
58006
|
return result;
|
|
@@ -57358,16 +58009,16 @@ function registerChangeTracking(pi, cwd) {
|
|
|
57358
58009
|
}
|
|
57359
58010
|
|
|
57360
58011
|
// dist/extensions/gitnexus/observatory.js
|
|
57361
|
-
import { spawn as
|
|
58012
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
57362
58013
|
import { appendFileSync as appendFileSync5 } from "node:fs";
|
|
57363
58014
|
|
|
57364
58015
|
// dist/core/observatory-cache.js
|
|
57365
58016
|
import { readFileSync as readFileSync17, statSync as statSync11 } from "node:fs";
|
|
57366
|
-
import { tmpdir as
|
|
57367
|
-
import { join as
|
|
58017
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
58018
|
+
import { join as join34 } from "node:path";
|
|
57368
58019
|
function observatoryCachePath(repo) {
|
|
57369
58020
|
const slug = repo.replace(/[^a-zA-Z0-9._-]+/g, "_");
|
|
57370
|
-
return
|
|
58021
|
+
return join34(tmpdir4(), `nexus-observatory-${slug}.json`);
|
|
57371
58022
|
}
|
|
57372
58023
|
var MAX_CACHE_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
57373
58024
|
var lastCheckAt = 0;
|
|
@@ -57378,14 +58029,14 @@ function tryLoadObservatoryCache(repo) {
|
|
|
57378
58029
|
if (now - lastCheckAt < CHECK_INTERVAL_MS)
|
|
57379
58030
|
return;
|
|
57380
58031
|
lastCheckAt = now;
|
|
57381
|
-
const
|
|
58032
|
+
const path12 = observatoryCachePath(repo);
|
|
57382
58033
|
try {
|
|
57383
|
-
const stat3 = statSync11(
|
|
58034
|
+
const stat3 = statSync11(path12);
|
|
57384
58035
|
if (now - stat3.mtimeMs > MAX_CACHE_AGE_MS)
|
|
57385
58036
|
return;
|
|
57386
58037
|
if (stat3.mtimeMs <= loadedMtimeMs)
|
|
57387
58038
|
return;
|
|
57388
|
-
const parsed = JSON.parse(readFileSync17(
|
|
58039
|
+
const parsed = JSON.parse(readFileSync17(path12, "utf8"));
|
|
57389
58040
|
if (!Array.isArray(parsed.communities) || parsed.communities.length === 0)
|
|
57390
58041
|
return;
|
|
57391
58042
|
loadedMtimeMs = stat3.mtimeMs;
|
|
@@ -57411,7 +58062,7 @@ function trace(message) {
|
|
|
57411
58062
|
function spawnObservatoryFetch(config, repo) {
|
|
57412
58063
|
try {
|
|
57413
58064
|
const script = buildFetchScript();
|
|
57414
|
-
const child =
|
|
58065
|
+
const child = spawn9(process.execPath, ["-e", script], {
|
|
57415
58066
|
detached: true,
|
|
57416
58067
|
stdio: "ignore",
|
|
57417
58068
|
env: {
|
|
@@ -57549,7 +58200,7 @@ function parseHubJson(text) {
|
|
|
57549
58200
|
return void 0;
|
|
57550
58201
|
}
|
|
57551
58202
|
}
|
|
57552
|
-
function
|
|
58203
|
+
function basename12(filePath) {
|
|
57553
58204
|
if (!filePath)
|
|
57554
58205
|
return "";
|
|
57555
58206
|
return filePath.split("/").pop() ?? filePath;
|
|
@@ -57779,7 +58430,7 @@ function formatQuery(text, theme2) {
|
|
|
57779
58430
|
if (shownSymbols.length > 0) {
|
|
57780
58431
|
lines.push(theme2.fg("muted", "symbols:"));
|
|
57781
58432
|
for (const sym of shownSymbols) {
|
|
57782
|
-
const loc = sym.filePath ? `${
|
|
58433
|
+
const loc = sym.filePath ? `${basename12(sym.filePath)}${sym.startLine ? `:${sym.startLine}` : ""}` : "";
|
|
57783
58434
|
lines.push(` ${theme2.fg("accent", "\u2022")} ${sym.name} ${theme2.fg("muted", loc)}`);
|
|
57784
58435
|
}
|
|
57785
58436
|
}
|
|
@@ -57910,7 +58561,7 @@ function matchCurrentRepo(inventory, slug) {
|
|
|
57910
58561
|
|
|
57911
58562
|
// dist/extensions/gitnexus/tools.js
|
|
57912
58563
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
57913
|
-
import { Type as
|
|
58564
|
+
import { Type as Type18 } from "typebox";
|
|
57914
58565
|
function aliasParam(args, canonical, aliases) {
|
|
57915
58566
|
if (args[canonical] !== void 0)
|
|
57916
58567
|
return args;
|
|
@@ -57989,7 +58640,7 @@ function makeHubTool(ctx, options) {
|
|
|
57989
58640
|
}
|
|
57990
58641
|
};
|
|
57991
58642
|
}
|
|
57992
|
-
var repoParam =
|
|
58643
|
+
var repoParam = Type18.Optional(Type18.String({
|
|
57993
58644
|
description: "Indexed repository name or @group. Omit for the current repository."
|
|
57994
58645
|
}));
|
|
57995
58646
|
function createGitNexusTools(ctx) {
|
|
@@ -57999,11 +58650,11 @@ function createGitNexusTools(ctx) {
|
|
|
57999
58650
|
label: "GitNexus query",
|
|
58000
58651
|
description: "Query the code knowledge graph for execution flows related to a concept. Returns processes (call chains) ranked by relevance, each with its symbols and file locations. WHEN TO USE: understanding how code works together \u2014 execution flows and relationships, not just file matches. Complements grep. AFTER THIS: use gitnexus_context on a specific symbol for its 360-degree view.",
|
|
58001
58652
|
promptSnippet: "gitnexus_query: find execution flows by concept in the knowledge graph",
|
|
58002
|
-
parameters:
|
|
58003
|
-
query:
|
|
58004
|
-
goal:
|
|
58005
|
-
task_context:
|
|
58006
|
-
limit:
|
|
58653
|
+
parameters: Type18.Object({
|
|
58654
|
+
query: Type18.String({ description: "Natural language or keyword search query" }),
|
|
58655
|
+
goal: Type18.Optional(Type18.String({ description: "What you want to find. Helps ranking." })),
|
|
58656
|
+
task_context: Type18.Optional(Type18.String({ description: "What you are working on. Helps ranking." })),
|
|
58657
|
+
limit: Type18.Optional(Type18.Number({ description: "Max processes to return (default 5)" })),
|
|
58007
58658
|
repo: repoParam
|
|
58008
58659
|
})
|
|
58009
58660
|
});
|
|
@@ -58013,10 +58664,10 @@ function createGitNexusTools(ctx) {
|
|
|
58013
58664
|
label: "GitNexus context",
|
|
58014
58665
|
description: "360-degree view of a single code symbol: categorized incoming/outgoing references (calls, imports, extends, implements, overrides, field reads/writes), process participation, and file location. WHEN TO USE: after gitnexus_query, or whenever you need all callers/callees of a symbol. AFTER THIS: use gitnexus_impact if you plan to change it.",
|
|
58015
58666
|
promptSnippet: "gitnexus_context: all callers/callees/flows of one symbol",
|
|
58016
|
-
parameters:
|
|
58017
|
-
name:
|
|
58018
|
-
file_path:
|
|
58019
|
-
kind:
|
|
58667
|
+
parameters: Type18.Object({
|
|
58668
|
+
name: Type18.String({ description: 'Symbol name (e.g. "validateUser", "AuthService")' }),
|
|
58669
|
+
file_path: Type18.Optional(Type18.String({ description: "File path to disambiguate common names" })),
|
|
58670
|
+
kind: Type18.Optional(Type18.String({ description: "Kind filter, e.g. 'Function' | 'Class' | 'Method'" })),
|
|
58020
58671
|
repo: repoParam
|
|
58021
58672
|
}),
|
|
58022
58673
|
prepareArguments: (args) => aliasParam(args ?? {}, "name", ["target", "symbol"])
|
|
@@ -58030,9 +58681,9 @@ function createGitNexusTools(ctx) {
|
|
|
58030
58681
|
promptGuidelines: [
|
|
58031
58682
|
"Before editing a function, class, or method that the graph knows, run gitnexus_impact on it first and surface HIGH/CRITICAL risk to the user."
|
|
58032
58683
|
],
|
|
58033
|
-
parameters:
|
|
58034
|
-
target:
|
|
58035
|
-
direction:
|
|
58684
|
+
parameters: Type18.Object({
|
|
58685
|
+
target: Type18.String({ description: "Symbol to analyze" }),
|
|
58686
|
+
direction: Type18.Optional(Type18.String({ description: '"upstream" (callers, default), "downstream" (callees), or "both"' })),
|
|
58036
58687
|
repo: repoParam
|
|
58037
58688
|
}),
|
|
58038
58689
|
prepareArguments: (args) => aliasParam(args ?? {}, "target", ["name", "symbol"]),
|
|
@@ -58044,7 +58695,7 @@ function createGitNexusTools(ctx) {
|
|
|
58044
58695
|
label: "GitNexus detect changes",
|
|
58045
58696
|
description: "Map the current git diff to indexed symbols and trace which execution flows are impacted. WHEN TO USE: before committing \u2014 to understand what your changes affect and what to test.",
|
|
58046
58697
|
promptSnippet: "gitnexus_detect_changes: map local diff to affected flows",
|
|
58047
|
-
parameters:
|
|
58698
|
+
parameters: Type18.Object({ repo: repoParam }),
|
|
58048
58699
|
mapArgs: (params) => {
|
|
58049
58700
|
const diff = spawnSync7("git", ["diff", "--name-only", "HEAD"], {
|
|
58050
58701
|
cwd: ctx.cwd,
|
|
@@ -58063,8 +58714,8 @@ function createGitNexusTools(ctx) {
|
|
|
58063
58714
|
promptGuidelines: [
|
|
58064
58715
|
"Prefer gitnexus_query/context/impact; reach for gitnexus_cypher only when they cannot express the question."
|
|
58065
58716
|
],
|
|
58066
|
-
parameters:
|
|
58067
|
-
query:
|
|
58717
|
+
parameters: Type18.Object({
|
|
58718
|
+
query: Type18.String({ description: "Cypher query to execute" }),
|
|
58068
58719
|
repo: repoParam
|
|
58069
58720
|
})
|
|
58070
58721
|
});
|
|
@@ -58073,14 +58724,14 @@ function createGitNexusTools(ctx) {
|
|
|
58073
58724
|
hubTool: "list_repos",
|
|
58074
58725
|
label: "GitNexus repos",
|
|
58075
58726
|
description: "List all repositories (and multi-repo @groups) indexed on GitNexus, with symbol/relationship counts and indexed dates. WHEN TO USE: to discover or refresh what you can query across repositories.",
|
|
58076
|
-
parameters:
|
|
58727
|
+
parameters: Type18.Object({}),
|
|
58077
58728
|
mapArgs: () => ({})
|
|
58078
58729
|
});
|
|
58079
58730
|
return [query, context, impact, detectChanges, cypher, listRepos];
|
|
58080
58731
|
}
|
|
58081
58732
|
|
|
58082
58733
|
// dist/extensions/gitnexus/index.js
|
|
58083
|
-
function resolveGitNexusSkillsDir(moduleUrl = import.meta.url, pathExists2 =
|
|
58734
|
+
function resolveGitNexusSkillsDir(moduleUrl = import.meta.url, pathExists2 = existsSync25) {
|
|
58084
58735
|
const candidates = [
|
|
58085
58736
|
fileURLToPath7(new URL("./skills/", moduleUrl)),
|
|
58086
58737
|
fileURLToPath7(new URL("./extensions/gitnexus/skills/", moduleUrl))
|
|
@@ -58092,11 +58743,21 @@ function gitnexusExtension(pi) {
|
|
|
58092
58743
|
let current;
|
|
58093
58744
|
let activeClient;
|
|
58094
58745
|
let toolsRegistered = false;
|
|
58746
|
+
let delegationRegistered = false;
|
|
58095
58747
|
let startupNotice;
|
|
58096
58748
|
let loginRequired = false;
|
|
58097
58749
|
const cwd = process.cwd();
|
|
58098
58750
|
let gatewayPolicy = readGatewayCache();
|
|
58099
|
-
|
|
58751
|
+
const initialConfig = resolveGitNexusConfig();
|
|
58752
|
+
registerAutoProvider(pi, initialConfig, gatewayPolicy);
|
|
58753
|
+
function registerDelegationIfAvailable() {
|
|
58754
|
+
if (delegationRegistered || isDelegatedWorkerProcess() || !resolveGitNexusConfig() || !gatewayPolicy?.delegation) {
|
|
58755
|
+
return;
|
|
58756
|
+
}
|
|
58757
|
+
registerDelegateTaskTool(pi, gatewayPolicy.delegation);
|
|
58758
|
+
delegationRegistered = true;
|
|
58759
|
+
}
|
|
58760
|
+
registerDelegationIfAvailable();
|
|
58100
58761
|
function updateCreditStatus(ctx) {
|
|
58101
58762
|
ctx.ui.setStatus("nexus-credits", formatCreditBalance(gatewayPolicy));
|
|
58102
58763
|
}
|
|
@@ -58162,10 +58823,11 @@ function gitnexusExtension(pi) {
|
|
|
58162
58823
|
const config = resolveGitNexusConfig();
|
|
58163
58824
|
if (config)
|
|
58164
58825
|
gatewayPolicy = await refreshGatewayPolicy(config);
|
|
58826
|
+
registerDelegationIfAvailable();
|
|
58165
58827
|
updateCreditStatus(ctx);
|
|
58166
58828
|
});
|
|
58167
58829
|
pi.on("resources_discover", (event) => {
|
|
58168
|
-
const hasOwnGitnexusSkills =
|
|
58830
|
+
const hasOwnGitnexusSkills = existsSync25(join35(event.cwd, ".agents", "skills", "gitnexus")) || existsSync25(join35(homedir11(), ".agents", "skills", "gitnexus-debugging"));
|
|
58169
58831
|
if (hasOwnGitnexusSkills)
|
|
58170
58832
|
return;
|
|
58171
58833
|
const skillsDir = resolveGitNexusSkillsDir();
|
|
@@ -58188,9 +58850,9 @@ ${buildGitNexusPrompt(inventory, current)}` };
|
|
|
58188
58850
|
if (pasted) {
|
|
58189
58851
|
try {
|
|
58190
58852
|
await new GitNexusClient({ hubUrl, token: pasted }).callTool("list_repos", {});
|
|
58191
|
-
const
|
|
58853
|
+
const path12 = saveGitNexusConfig({ hubUrl, token: pasted });
|
|
58192
58854
|
await connect2();
|
|
58193
|
-
ctx.ui.notify(`GitNexus token saved to ${
|
|
58855
|
+
ctx.ui.notify(`GitNexus token saved to ${path12}. ${startupNotice ?? ""}`, "info");
|
|
58194
58856
|
} catch (error) {
|
|
58195
58857
|
const message = error instanceof Error ? error.message : String(error);
|
|
58196
58858
|
ctx.ui.notify(`GitNexus login failed: ${message}`, "error");
|
|
@@ -58212,9 +58874,9 @@ ${buildGitNexusPrompt(inventory, current)}` };
|
|
|
58212
58874
|
deviceName
|
|
58213
58875
|
};
|
|
58214
58876
|
await new GitNexusClient(config).callTool("list_repos", {});
|
|
58215
|
-
const
|
|
58877
|
+
const path12 = saveGitNexusConfig(config);
|
|
58216
58878
|
await connect2();
|
|
58217
|
-
ctx.ui.notify(`Signed in. Token saved to ${
|
|
58879
|
+
ctx.ui.notify(`Signed in. Token saved to ${path12}. ${startupNotice ?? ""}`, "info");
|
|
58218
58880
|
} catch (error) {
|
|
58219
58881
|
const message = error instanceof Error ? error.message : String(error);
|
|
58220
58882
|
ctx.ui.notify(`GitNexus login failed: ${message}`, "error");
|
|
@@ -58241,10 +58903,10 @@ ${buildGitNexusPrompt(inventory, current)}` };
|
|
|
58241
58903
|
}
|
|
58242
58904
|
|
|
58243
58905
|
// dist/extensions/mcp/index.js
|
|
58244
|
-
import { Type as
|
|
58906
|
+
import { Type as Type19 } from "typebox";
|
|
58245
58907
|
|
|
58246
58908
|
// dist/extensions/mcp/client.js
|
|
58247
|
-
import { spawn as
|
|
58909
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
58248
58910
|
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
58249
58911
|
var REQUEST_TIMEOUT_MS4 = 6e4;
|
|
58250
58912
|
var McpClientError = class extends Error {
|
|
@@ -58350,7 +59012,7 @@ var StdioTransport = class {
|
|
|
58350
59012
|
return this.child;
|
|
58351
59013
|
let child;
|
|
58352
59014
|
try {
|
|
58353
|
-
child =
|
|
59015
|
+
child = spawn10(this.command, this.args, {
|
|
58354
59016
|
stdio: ["pipe", "pipe", "pipe"],
|
|
58355
59017
|
env: { ...process.env, ...this.env },
|
|
58356
59018
|
cwd: this.cwd
|
|
@@ -58488,7 +59150,7 @@ var McpClient = class {
|
|
|
58488
59150
|
// dist/extensions/mcp/config.js
|
|
58489
59151
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
58490
59152
|
import { homedir as homedir12 } from "node:os";
|
|
58491
|
-
import { join as
|
|
59153
|
+
import { join as join36 } from "node:path";
|
|
58492
59154
|
function stringRecord(value) {
|
|
58493
59155
|
if (!value || typeof value !== "object")
|
|
58494
59156
|
return {};
|
|
@@ -58543,19 +59205,19 @@ function parseMcpConfig(text, source) {
|
|
|
58543
59205
|
return { servers, diagnostics };
|
|
58544
59206
|
}
|
|
58545
59207
|
function mcpConfigPaths(cwd, home = homedir12()) {
|
|
58546
|
-
return [
|
|
59208
|
+
return [join36(home, ".config", "nexus", "mcp.json"), join36(cwd, CONFIG_DIR_NAME, "mcp.json")];
|
|
58547
59209
|
}
|
|
58548
|
-
function loadMcpConfig(cwd, readFile4 = (
|
|
59210
|
+
function loadMcpConfig(cwd, readFile4 = (path12) => readFileSync18(path12, "utf8"), home) {
|
|
58549
59211
|
const byName = /* @__PURE__ */ new Map();
|
|
58550
59212
|
const diagnostics = [];
|
|
58551
|
-
for (const
|
|
59213
|
+
for (const path12 of mcpConfigPaths(cwd, home)) {
|
|
58552
59214
|
let text;
|
|
58553
59215
|
try {
|
|
58554
|
-
text = readFile4(
|
|
59216
|
+
text = readFile4(path12);
|
|
58555
59217
|
} catch {
|
|
58556
59218
|
continue;
|
|
58557
59219
|
}
|
|
58558
|
-
const parsed = parseMcpConfig(text,
|
|
59220
|
+
const parsed = parseMcpConfig(text, path12);
|
|
58559
59221
|
diagnostics.push(...parsed.diagnostics);
|
|
58560
59222
|
for (const server of parsed.servers)
|
|
58561
59223
|
byName.set(server.name, server);
|
|
@@ -58587,7 +59249,7 @@ function defineProxyTool(client, serverName, schema) {
|
|
|
58587
59249
|
// Pass the server's own JSON Schema straight through. Type.Unsafe wraps it
|
|
58588
59250
|
// without reinterpreting it, so the model sees the parameters the server
|
|
58589
59251
|
// documented and we never reject a payload the server would have accepted.
|
|
58590
|
-
parameters:
|
|
59252
|
+
parameters: Type19.Unsafe(schema.inputSchema ?? { type: "object", properties: {} }),
|
|
58591
59253
|
execute: async (_id, params, signal) => {
|
|
58592
59254
|
const result = await client.callTool(schema.name, params ?? {}, signal);
|
|
58593
59255
|
return {
|
|
@@ -58633,23 +59295,23 @@ function mcpExtension(pi) {
|
|
|
58633
59295
|
}
|
|
58634
59296
|
|
|
58635
59297
|
// dist/extensions/web-access.js
|
|
58636
|
-
import { existsSync as
|
|
58637
|
-
import { join as
|
|
59298
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync11 } from "node:fs";
|
|
59299
|
+
import { join as join37 } from "node:path";
|
|
58638
59300
|
var WEB_ACCESS_NPM_FALLBACK_SOURCE = "npm:pi-web-access@0.22.0";
|
|
58639
59301
|
function resolveWebAccessExtensionSource() {
|
|
58640
59302
|
const packageDir = getPackageDir();
|
|
58641
59303
|
const sourceCandidates = [
|
|
58642
|
-
|
|
58643
|
-
|
|
59304
|
+
join37(packageDir, "node_modules", "pi-web-access", "index.ts"),
|
|
59305
|
+
join37(packageDir, "..", "..", "node_modules", "pi-web-access", "index.ts")
|
|
58644
59306
|
];
|
|
58645
59307
|
const bundledCandidates = [
|
|
58646
|
-
|
|
58647
|
-
|
|
59308
|
+
join37(packageDir, "dist", "vendor", "web-access.js"),
|
|
59309
|
+
join37(packageDir, "vendor", "web-access.js")
|
|
58648
59310
|
];
|
|
58649
59311
|
const isTypeScriptSourceRuntime2 = import.meta.url.endsWith(".ts");
|
|
58650
59312
|
const candidates = isTypeScriptSourceRuntime2 ? [...sourceCandidates, ...bundledCandidates] : [...bundledCandidates, ...sourceCandidates];
|
|
58651
59313
|
for (const candidate of candidates) {
|
|
58652
|
-
if (
|
|
59314
|
+
if (existsSync26(candidate))
|
|
58653
59315
|
return candidate;
|
|
58654
59316
|
}
|
|
58655
59317
|
return WEB_ACCESS_NPM_FALLBACK_SOURCE;
|
|
@@ -58681,17 +59343,17 @@ var DEFAULT_SEARCH_ROUTING = {
|
|
|
58681
59343
|
],
|
|
58682
59344
|
fallbackOn: ["quota", "transient", "network", "invalid-response"]
|
|
58683
59345
|
};
|
|
58684
|
-
function
|
|
59346
|
+
function isRecord2(value) {
|
|
58685
59347
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
58686
59348
|
}
|
|
58687
59349
|
function prepareWebAccessConfig(agentDir) {
|
|
58688
59350
|
setAppEnv("CODING_AGENT_DIR", agentDir);
|
|
58689
|
-
const configPath2 =
|
|
59351
|
+
const configPath2 = join37(agentDir, WEB_ACCESS_CONFIG_FILENAME);
|
|
58690
59352
|
let config = {};
|
|
58691
|
-
if (
|
|
59353
|
+
if (existsSync26(configPath2)) {
|
|
58692
59354
|
try {
|
|
58693
59355
|
const parsed = JSON.parse(readFileSync19(configPath2, "utf-8"));
|
|
58694
|
-
if (!
|
|
59356
|
+
if (!isRecord2(parsed)) {
|
|
58695
59357
|
return { changed: false };
|
|
58696
59358
|
}
|
|
58697
59359
|
config = parsed;
|
|
@@ -58707,7 +59369,7 @@ function prepareWebAccessConfig(agentDir) {
|
|
|
58707
59369
|
if (config.toolNames === void 0) {
|
|
58708
59370
|
config.toolNames = { webSearch: DEFAULT_WEB_SEARCH_TOOL_NAME };
|
|
58709
59371
|
changed = true;
|
|
58710
|
-
} else if (
|
|
59372
|
+
} else if (isRecord2(config.toolNames) && config.toolNames.webSearch === void 0) {
|
|
58711
59373
|
config.toolNames.webSearch = DEFAULT_WEB_SEARCH_TOOL_NAME;
|
|
58712
59374
|
changed = true;
|
|
58713
59375
|
}
|
|
@@ -58743,8 +59405,8 @@ function prepareWebAccessConfig(agentDir) {
|
|
|
58743
59405
|
}
|
|
58744
59406
|
function readConfiguredWebSearchToolName(agentDir) {
|
|
58745
59407
|
try {
|
|
58746
|
-
const parsed = JSON.parse(readFileSync19(
|
|
58747
|
-
if (!
|
|
59408
|
+
const parsed = JSON.parse(readFileSync19(join37(agentDir, WEB_ACCESS_CONFIG_FILENAME), "utf-8"));
|
|
59409
|
+
if (!isRecord2(parsed) || !isRecord2(parsed.toolNames))
|
|
58748
59410
|
return void 0;
|
|
58749
59411
|
return typeof parsed.toolNames.webSearch === "string" ? parsed.toolNames.webSearch : void 0;
|
|
58750
59412
|
} catch {
|
|
@@ -58855,6 +59517,7 @@ function webSearchConcurrencyExtension(pi) {
|
|
|
58855
59517
|
// dist/extensions/index.js
|
|
58856
59518
|
var builtInExtensions = [
|
|
58857
59519
|
{ name: "gitnexus", factory: gitnexusExtension },
|
|
59520
|
+
{ name: "delegated-worker-runtime", factory: delegatedWorkerRuntime, hidden: true },
|
|
58858
59521
|
// No-op until the user writes an mcp.json; connecting nothing costs nothing.
|
|
58859
59522
|
{ name: "mcp", factory: mcpExtension },
|
|
58860
59523
|
{ name: "web-search-concurrency", factory: webSearchConcurrencyExtension }
|
|
@@ -58862,20 +59525,20 @@ var builtInExtensions = [
|
|
|
58862
59525
|
|
|
58863
59526
|
// dist/migrations.js
|
|
58864
59527
|
import chalk9 from "chalk";
|
|
58865
|
-
import { existsSync as
|
|
58866
|
-
import { dirname as dirname21, join as
|
|
59528
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync10, readFileSync as readFileSync20, renameSync as renameSync2, rmSync as rmSync4, writeFileSync as writeFileSync12 } from "fs";
|
|
59529
|
+
import { dirname as dirname21, join as join38 } from "path";
|
|
58867
59530
|
var MIGRATION_GUIDE_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
|
|
58868
59531
|
var EXTENSIONS_DOC_URL = "https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md";
|
|
58869
59532
|
function migrateAuthToAuthJson() {
|
|
58870
59533
|
const agentDir = getAgentDir();
|
|
58871
|
-
const authPath =
|
|
58872
|
-
const oauthPath =
|
|
58873
|
-
const settingsPath =
|
|
58874
|
-
if (
|
|
59534
|
+
const authPath = join38(agentDir, "auth.json");
|
|
59535
|
+
const oauthPath = join38(agentDir, "oauth.json");
|
|
59536
|
+
const settingsPath = join38(agentDir, "settings.json");
|
|
59537
|
+
if (existsSync27(authPath))
|
|
58875
59538
|
return [];
|
|
58876
59539
|
const migrated = {};
|
|
58877
59540
|
const providers = [];
|
|
58878
|
-
if (
|
|
59541
|
+
if (existsSync27(oauthPath)) {
|
|
58879
59542
|
try {
|
|
58880
59543
|
const oauth = JSON.parse(readFileSync20(oauthPath, "utf-8"));
|
|
58881
59544
|
for (const [provider, cred] of Object.entries(oauth)) {
|
|
@@ -58886,7 +59549,7 @@ function migrateAuthToAuthJson() {
|
|
|
58886
59549
|
} catch {
|
|
58887
59550
|
}
|
|
58888
59551
|
}
|
|
58889
|
-
if (
|
|
59552
|
+
if (existsSync27(settingsPath)) {
|
|
58890
59553
|
try {
|
|
58891
59554
|
const content = readFileSync20(settingsPath, "utf-8");
|
|
58892
59555
|
const settings = JSON.parse(content);
|
|
@@ -58913,7 +59576,7 @@ function migrateSessionsFromAgentRoot() {
|
|
|
58913
59576
|
const agentDir = getAgentDir();
|
|
58914
59577
|
let files;
|
|
58915
59578
|
try {
|
|
58916
|
-
files = readdirSync10(agentDir).filter((f) => f.endsWith(".jsonl")).map((f) =>
|
|
59579
|
+
files = readdirSync10(agentDir).filter((f) => f.endsWith(".jsonl")).map((f) => join38(agentDir, f));
|
|
58917
59580
|
} catch {
|
|
58918
59581
|
return;
|
|
58919
59582
|
}
|
|
@@ -58930,13 +59593,13 @@ function migrateSessionsFromAgentRoot() {
|
|
|
58930
59593
|
continue;
|
|
58931
59594
|
const cwd = header.cwd;
|
|
58932
59595
|
const safePath = `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
58933
|
-
const correctDir =
|
|
58934
|
-
if (!
|
|
59596
|
+
const correctDir = join38(agentDir, "sessions", safePath);
|
|
59597
|
+
if (!existsSync27(correctDir)) {
|
|
58935
59598
|
mkdirSync13(correctDir, { recursive: true });
|
|
58936
59599
|
}
|
|
58937
59600
|
const fileName = file.split("/").pop() || file.split("\\").pop();
|
|
58938
|
-
const newPath =
|
|
58939
|
-
if (
|
|
59601
|
+
const newPath = join38(correctDir, fileName);
|
|
59602
|
+
if (existsSync27(newPath))
|
|
58940
59603
|
continue;
|
|
58941
59604
|
renameSync2(file, newPath);
|
|
58942
59605
|
} catch {
|
|
@@ -58944,9 +59607,9 @@ function migrateSessionsFromAgentRoot() {
|
|
|
58944
59607
|
}
|
|
58945
59608
|
}
|
|
58946
59609
|
function migrateCommandsToPrompts(baseDir, label) {
|
|
58947
|
-
const commandsDir =
|
|
58948
|
-
const promptsDir =
|
|
58949
|
-
if (
|
|
59610
|
+
const commandsDir = join38(baseDir, "commands");
|
|
59611
|
+
const promptsDir = join38(baseDir, "prompts");
|
|
59612
|
+
if (existsSync27(commandsDir) && !existsSync27(promptsDir)) {
|
|
58950
59613
|
try {
|
|
58951
59614
|
renameSync2(commandsDir, promptsDir);
|
|
58952
59615
|
console.log(chalk9.green(`Migrated ${label} commands/ \u2192 prompts/`));
|
|
@@ -58958,8 +59621,8 @@ function migrateCommandsToPrompts(baseDir, label) {
|
|
|
58958
59621
|
return false;
|
|
58959
59622
|
}
|
|
58960
59623
|
function migrateKeybindingsConfigFile() {
|
|
58961
|
-
const configPath2 =
|
|
58962
|
-
if (!
|
|
59624
|
+
const configPath2 = join38(getAgentDir(), "keybindings.json");
|
|
59625
|
+
if (!existsSync27(configPath2))
|
|
58963
59626
|
return;
|
|
58964
59627
|
try {
|
|
58965
59628
|
const parsed = JSON.parse(readFileSync20(configPath2, "utf-8"));
|
|
@@ -58976,20 +59639,20 @@ function migrateKeybindingsConfigFile() {
|
|
|
58976
59639
|
}
|
|
58977
59640
|
function migrateToolsToBin() {
|
|
58978
59641
|
const agentDir = getAgentDir();
|
|
58979
|
-
const toolsDir =
|
|
59642
|
+
const toolsDir = join38(agentDir, "tools");
|
|
58980
59643
|
const binDir = getBinDir();
|
|
58981
|
-
if (!
|
|
59644
|
+
if (!existsSync27(toolsDir))
|
|
58982
59645
|
return;
|
|
58983
59646
|
const binaries = ["fd", "rg", "fd.exe", "rg.exe"];
|
|
58984
59647
|
let movedAny = false;
|
|
58985
59648
|
for (const bin of binaries) {
|
|
58986
|
-
const oldPath =
|
|
58987
|
-
const newPath =
|
|
58988
|
-
if (
|
|
58989
|
-
if (!
|
|
59649
|
+
const oldPath = join38(toolsDir, bin);
|
|
59650
|
+
const newPath = join38(binDir, bin);
|
|
59651
|
+
if (existsSync27(oldPath)) {
|
|
59652
|
+
if (!existsSync27(binDir)) {
|
|
58990
59653
|
mkdirSync13(binDir, { recursive: true });
|
|
58991
59654
|
}
|
|
58992
|
-
if (!
|
|
59655
|
+
if (!existsSync27(newPath)) {
|
|
58993
59656
|
try {
|
|
58994
59657
|
renameSync2(oldPath, newPath);
|
|
58995
59658
|
movedAny = true;
|
|
@@ -59008,13 +59671,13 @@ function migrateToolsToBin() {
|
|
|
59008
59671
|
}
|
|
59009
59672
|
}
|
|
59010
59673
|
function checkDeprecatedExtensionDirs(baseDir, label) {
|
|
59011
|
-
const hooksDir =
|
|
59012
|
-
const toolsDir =
|
|
59674
|
+
const hooksDir = join38(baseDir, "hooks");
|
|
59675
|
+
const toolsDir = join38(baseDir, "tools");
|
|
59013
59676
|
const warnings = [];
|
|
59014
|
-
if (
|
|
59677
|
+
if (existsSync27(hooksDir)) {
|
|
59015
59678
|
warnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);
|
|
59016
59679
|
}
|
|
59017
|
-
if (
|
|
59680
|
+
if (existsSync27(toolsDir)) {
|
|
59018
59681
|
try {
|
|
59019
59682
|
const entries = readdirSync10(toolsDir);
|
|
59020
59683
|
const customTools = entries.filter((e) => {
|
|
@@ -59031,7 +59694,7 @@ function checkDeprecatedExtensionDirs(baseDir, label) {
|
|
|
59031
59694
|
}
|
|
59032
59695
|
function migrateExtensionSystem(cwd) {
|
|
59033
59696
|
const agentDir = getAgentDir();
|
|
59034
|
-
const projectDir =
|
|
59697
|
+
const projectDir = join38(cwd, CONFIG_DIR_NAME);
|
|
59035
59698
|
migrateCommandsToPrompts(agentDir, "Global");
|
|
59036
59699
|
migrateCommandsToPrompts(projectDir, "Project");
|
|
59037
59700
|
const warnings = [
|
|
@@ -59074,11 +59737,11 @@ function runMigrations(cwd) {
|
|
|
59074
59737
|
|
|
59075
59738
|
// dist/modes/interactive/interactive-mode.js
|
|
59076
59739
|
import * as crypto2 from "node:crypto";
|
|
59077
|
-
import * as
|
|
59078
|
-
import * as
|
|
59079
|
-
import * as
|
|
59740
|
+
import * as fs7 from "node:fs";
|
|
59741
|
+
import * as os5 from "node:os";
|
|
59742
|
+
import * as path11 from "node:path";
|
|
59080
59743
|
import chalk10 from "chalk";
|
|
59081
|
-
import { spawn as
|
|
59744
|
+
import { spawn as spawn13, spawnSync as spawnSync9 } from "child_process";
|
|
59082
59745
|
|
|
59083
59746
|
// dist/core/cache-stats.js
|
|
59084
59747
|
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
@@ -59186,22 +59849,22 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
59186
59849
|
];
|
|
59187
59850
|
|
|
59188
59851
|
// dist/utils/clipboard.js
|
|
59189
|
-
import { execFileSync, execSync as execSync3, spawn as
|
|
59852
|
+
import { execFileSync, execSync as execSync3, spawn as spawn11 } from "child_process";
|
|
59190
59853
|
import { platform as platform3 } from "os";
|
|
59191
59854
|
|
|
59192
59855
|
// dist/utils/clipboard-image.js
|
|
59193
59856
|
import { spawnSync as spawnSync8 } from "child_process";
|
|
59194
|
-
import { randomUUID as
|
|
59857
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
59195
59858
|
import { readFileSync as readFileSync21, unlinkSync } from "fs";
|
|
59196
|
-
import { tmpdir as
|
|
59197
|
-
import { join as
|
|
59859
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
59860
|
+
import { join as join40 } from "path";
|
|
59198
59861
|
|
|
59199
59862
|
// dist/utils/clipboard-native.js
|
|
59200
59863
|
import { createRequire as createRequire4 } from "module";
|
|
59201
|
-
import { dirname as dirname22, join as
|
|
59864
|
+
import { dirname as dirname22, join as join39 } from "path";
|
|
59202
59865
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
59203
59866
|
var moduleRequire = createRequire4(import.meta.url);
|
|
59204
|
-
var executableDirRequire = createRequire4(pathToFileURL3(
|
|
59867
|
+
var executableDirRequire = createRequire4(pathToFileURL3(join39(dirname22(process.execPath), "package.json")).href);
|
|
59205
59868
|
var hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
59206
59869
|
function loadClipboardNative(requires = [moduleRequire, executableDirRequire]) {
|
|
59207
59870
|
for (const requireClipboard of requires) {
|
|
@@ -59316,7 +59979,7 @@ function isWSL(env = process.env) {
|
|
|
59316
59979
|
}
|
|
59317
59980
|
}
|
|
59318
59981
|
function readClipboardImageViaPowerShell() {
|
|
59319
|
-
const tmpFile =
|
|
59982
|
+
const tmpFile = join40(tmpdir5(), `pi-wsl-clip-${randomUUID4()}.png`);
|
|
59320
59983
|
try {
|
|
59321
59984
|
const winPathResult = runCommand("wslpath", ["-w", tmpFile], { timeoutMs: DEFAULT_LIST_TIMEOUT_MS });
|
|
59322
59985
|
if (!winPathResult.ok) {
|
|
@@ -59511,7 +60174,7 @@ async function copyToClipboard(text) {
|
|
|
59511
60174
|
try {
|
|
59512
60175
|
execSync3("which wl-copy", { stdio: "ignore" });
|
|
59513
60176
|
const wlCopyExit = await new Promise((resolve15) => {
|
|
59514
|
-
const proc =
|
|
60177
|
+
const proc = spawn11("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
59515
60178
|
proc.on("error", () => resolve15(1));
|
|
59516
60179
|
proc.on("close", (code) => resolve15(code ?? 1));
|
|
59517
60180
|
proc.stdin.on("error", () => {
|
|
@@ -60262,13 +60925,13 @@ var DialogFrame = class {
|
|
|
60262
60925
|
};
|
|
60263
60926
|
|
|
60264
60927
|
// dist/modes/interactive/external-editor.js
|
|
60265
|
-
import { spawn as
|
|
60928
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
60266
60929
|
import { mkdtempSync, readFileSync as readFileSync22, rmSync as rmSync5, writeFileSync as writeFileSync13 } from "node:fs";
|
|
60267
|
-
import { tmpdir as
|
|
60268
|
-
import { join as
|
|
60930
|
+
import { tmpdir as tmpdir6 } from "node:os";
|
|
60931
|
+
import { join as join41 } from "node:path";
|
|
60269
60932
|
async function editInExternalEditor(options) {
|
|
60270
|
-
const directory = mkdtempSync(
|
|
60271
|
-
const filePath =
|
|
60933
|
+
const directory = mkdtempSync(join41(tmpdir6(), "pi-editor-"));
|
|
60934
|
+
const filePath = join41(directory, "prompt.md");
|
|
60272
60935
|
try {
|
|
60273
60936
|
writeFileSync13(filePath, options.content, "utf-8");
|
|
60274
60937
|
const [editor, ...editorArgs] = options.command.split(" ");
|
|
@@ -60276,7 +60939,7 @@ async function editInExternalEditor(options) {
|
|
|
60276
60939
|
Pi will resume when the editor exits.
|
|
60277
60940
|
`);
|
|
60278
60941
|
const exitCode = await new Promise((resolve15) => {
|
|
60279
|
-
const child =
|
|
60942
|
+
const child = spawn12(editor, [...editorArgs, filePath], {
|
|
60280
60943
|
stdio: "inherit",
|
|
60281
60944
|
shell: process.platform === "win32"
|
|
60282
60945
|
});
|
|
@@ -60471,7 +61134,7 @@ function clipVisible(line, width) {
|
|
|
60471
61134
|
}
|
|
60472
61135
|
return `${out}\x1B[0m`;
|
|
60473
61136
|
}
|
|
60474
|
-
function
|
|
61137
|
+
function basename13(filePath) {
|
|
60475
61138
|
if (!filePath)
|
|
60476
61139
|
return "";
|
|
60477
61140
|
return filePath.split("/").pop() ?? filePath;
|
|
@@ -60679,7 +61342,7 @@ var GraphRailComponent = class {
|
|
|
60679
61342
|
return;
|
|
60680
61343
|
}
|
|
60681
61344
|
for (const change of s.changes.slice(-5)) {
|
|
60682
|
-
row(`${
|
|
61345
|
+
row(`${basename13(change.path)} ${theme.fg("success", `+${change.added}`)} ${theme.fg("error", `-${change.removed}`)}`);
|
|
60683
61346
|
}
|
|
60684
61347
|
end();
|
|
60685
61348
|
}
|
|
@@ -63646,10 +64309,10 @@ var TreeList = class {
|
|
|
63646
64309
|
};
|
|
63647
64310
|
switch (name) {
|
|
63648
64311
|
case "read": {
|
|
63649
|
-
const
|
|
64312
|
+
const path12 = shortenPath3(String(args.path || args.file_path || ""));
|
|
63650
64313
|
const offset = args.offset;
|
|
63651
64314
|
const limit = args.limit;
|
|
63652
|
-
let display =
|
|
64315
|
+
let display = path12;
|
|
63653
64316
|
if (offset !== void 0 || limit !== void 0) {
|
|
63654
64317
|
const start = offset ?? 1;
|
|
63655
64318
|
const end = limit !== void 0 ? start + limit - 1 : "";
|
|
@@ -63658,12 +64321,12 @@ var TreeList = class {
|
|
|
63658
64321
|
return `[read: ${display}]`;
|
|
63659
64322
|
}
|
|
63660
64323
|
case "write": {
|
|
63661
|
-
const
|
|
63662
|
-
return `[write: ${
|
|
64324
|
+
const path12 = shortenPath3(String(args.path || args.file_path || ""));
|
|
64325
|
+
return `[write: ${path12}]`;
|
|
63663
64326
|
}
|
|
63664
64327
|
case "edit": {
|
|
63665
|
-
const
|
|
63666
|
-
return `[edit: ${
|
|
64328
|
+
const path12 = shortenPath3(String(args.path || args.file_path || ""));
|
|
64329
|
+
return `[edit: ${path12}]`;
|
|
63667
64330
|
}
|
|
63668
64331
|
case "bash": {
|
|
63669
64332
|
const rawCmd = String(args.command || "");
|
|
@@ -63672,17 +64335,17 @@ var TreeList = class {
|
|
|
63672
64335
|
}
|
|
63673
64336
|
case "grep": {
|
|
63674
64337
|
const pattern = String(args.pattern || "");
|
|
63675
|
-
const
|
|
63676
|
-
return `[grep: /${pattern}/ in ${
|
|
64338
|
+
const path12 = shortenPath3(String(args.path || "."));
|
|
64339
|
+
return `[grep: /${pattern}/ in ${path12}]`;
|
|
63677
64340
|
}
|
|
63678
64341
|
case "find": {
|
|
63679
64342
|
const pattern = String(args.pattern || "");
|
|
63680
|
-
const
|
|
63681
|
-
return `[find: ${pattern} in ${
|
|
64343
|
+
const path12 = shortenPath3(String(args.path || "."));
|
|
64344
|
+
return `[find: ${pattern} in ${path12}]`;
|
|
63682
64345
|
}
|
|
63683
64346
|
case "ls": {
|
|
63684
|
-
const
|
|
63685
|
-
return `[ls: ${
|
|
64347
|
+
const path12 = shortenPath3(String(args.path || "."));
|
|
64348
|
+
return `[ls: ${path12}]`;
|
|
63686
64349
|
}
|
|
63687
64350
|
default: {
|
|
63688
64351
|
const argsStr = JSON.stringify(args).slice(0, 40);
|
|
@@ -64416,7 +65079,7 @@ function formatResumeCommand(sessionManager) {
|
|
|
64416
65079
|
if (!sessionManager.isPersisted())
|
|
64417
65080
|
return void 0;
|
|
64418
65081
|
const sessionFile = sessionManager.getSessionFile();
|
|
64419
|
-
if (!sessionFile || !
|
|
65082
|
+
if (!sessionFile || !fs7.existsSync(sessionFile))
|
|
64420
65083
|
return void 0;
|
|
64421
65084
|
const args = [APP_NAME];
|
|
64422
65085
|
if (!sessionManager.usesDefaultSessionDir()) {
|
|
@@ -65015,7 +65678,7 @@ var InteractiveMode = class _InteractiveMode {
|
|
|
65015
65678
|
* Update terminal title with session name and cwd.
|
|
65016
65679
|
*/
|
|
65017
65680
|
updateTerminalTitle() {
|
|
65018
|
-
const cwdBasename =
|
|
65681
|
+
const cwdBasename = path11.basename(this.sessionManager.getCwd());
|
|
65019
65682
|
const sessionName = this.sessionManager.getSessionName();
|
|
65020
65683
|
if (sessionName) {
|
|
65021
65684
|
this.ui.terminal.setTitle(`${APP_TITLE} - ${sessionName} - ${cwdBasename}`);
|
|
@@ -65112,7 +65775,7 @@ var InteractiveMode = class _InteractiveMode {
|
|
|
65112
65775
|
return void 0;
|
|
65113
65776
|
const runTmuxShow = (option) => {
|
|
65114
65777
|
return new Promise((resolve15) => {
|
|
65115
|
-
const proc =
|
|
65778
|
+
const proc = spawn13("tmux", ["show", "-gv", option], {
|
|
65116
65779
|
stdio: ["ignore", "pipe", "ignore"]
|
|
65117
65780
|
});
|
|
65118
65781
|
let stdout = "";
|
|
@@ -65157,21 +65820,21 @@ var InteractiveMode = class _InteractiveMode {
|
|
|
65157
65820
|
// Extension System
|
|
65158
65821
|
// =========================================================================
|
|
65159
65822
|
formatDisplayPath(p) {
|
|
65160
|
-
const home =
|
|
65823
|
+
const home = os5.homedir();
|
|
65161
65824
|
let result = p;
|
|
65162
65825
|
if (result.startsWith(home)) {
|
|
65163
65826
|
result = `~${result.slice(home.length)}`;
|
|
65164
65827
|
}
|
|
65165
65828
|
return result;
|
|
65166
65829
|
}
|
|
65167
|
-
formatExtensionDisplayPath(
|
|
65168
|
-
let result = this.formatDisplayPath(
|
|
65830
|
+
formatExtensionDisplayPath(path12) {
|
|
65831
|
+
let result = this.formatDisplayPath(path12);
|
|
65169
65832
|
result = result.replace(/\/index\.ts$/, "").replace(/\/index\.js$/, "");
|
|
65170
65833
|
return result;
|
|
65171
65834
|
}
|
|
65172
65835
|
formatContextPath(p) {
|
|
65173
|
-
const cwd =
|
|
65174
|
-
const absolutePath =
|
|
65836
|
+
const cwd = path11.resolve(this.sessionManager.getCwd());
|
|
65837
|
+
const absolutePath = path11.isAbsolute(p) ? path11.resolve(p) : path11.resolve(cwd, p);
|
|
65175
65838
|
const relativePath = getCwdRelativePath(absolutePath, cwd);
|
|
65176
65839
|
if (relativePath !== void 0) {
|
|
65177
65840
|
return relativePath;
|
|
@@ -65191,10 +65854,10 @@ var InteractiveMode = class _InteractiveMode {
|
|
|
65191
65854
|
const normalizedBaseDir = baseDir.replace(/\\/g, "/");
|
|
65192
65855
|
const npmRootMatch = normalizedBaseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
|
|
65193
65856
|
if (npmRootMatch?.[1] && normalizedFullPath.startsWith(`${npmRootMatch[1]}/`)) {
|
|
65194
|
-
return
|
|
65857
|
+
return path11.posix.relative(normalizedBaseDir, normalizedFullPath);
|
|
65195
65858
|
}
|
|
65196
|
-
const relativePath =
|
|
65197
|
-
if (relativePath && relativePath !== "." && !relativePath.startsWith("..") && !relativePath.startsWith(`..${
|
|
65859
|
+
const relativePath = path11.relative(path11.resolve(baseDir), path11.resolve(fullPath));
|
|
65860
|
+
if (relativePath && relativePath !== "." && !relativePath.startsWith("..") && !relativePath.startsWith(`..${path11.sep}`) && !path11.isAbsolute(relativePath)) {
|
|
65198
65861
|
return relativePath.replace(/\\/g, "/");
|
|
65199
65862
|
}
|
|
65200
65863
|
}
|
|
@@ -65239,7 +65902,7 @@ var InteractiveMode = class _InteractiveMode {
|
|
|
65239
65902
|
}
|
|
65240
65903
|
const shortPath = this.getShortPath(resourcePath, sourceInfo).replace(/\\/g, "/");
|
|
65241
65904
|
const packagePath = shortPath.startsWith("extensions/") ? shortPath.slice("extensions/".length) : shortPath;
|
|
65242
|
-
const parsedPath =
|
|
65905
|
+
const parsedPath = path11.posix.parse(packagePath);
|
|
65243
65906
|
if (parsedPath.name === "index") {
|
|
65244
65907
|
return !parsedPath.dir || parsedPath.dir === "." ? sourceLabel : `${sourceLabel}:${parsedPath.dir}`;
|
|
65245
65908
|
}
|
|
@@ -66436,11 +67099,11 @@ ${message}`, ["Yes", "No"], opts);
|
|
|
66436
67099
|
try {
|
|
66437
67100
|
const image = await readClipboardImage();
|
|
66438
67101
|
if (image) {
|
|
66439
|
-
const tmpDir =
|
|
67102
|
+
const tmpDir = os5.tmpdir();
|
|
66440
67103
|
const ext = extensionForImageMimeType(image.mimeType) ?? "png";
|
|
66441
67104
|
const fileName = `pi-clipboard-${crypto2.randomUUID()}.${ext}`;
|
|
66442
|
-
const filePath =
|
|
66443
|
-
|
|
67105
|
+
const filePath = path11.join(tmpDir, fileName);
|
|
67106
|
+
fs7.writeFileSync(filePath, Buffer.from(image.bytes));
|
|
66444
67107
|
this.editor.insertTextAtCursor?.(filePath);
|
|
66445
67108
|
this.ui.requestRender();
|
|
66446
67109
|
return;
|
|
@@ -68646,7 +69309,7 @@ ${packageLines}`, 1, 0));
|
|
|
68646
69309
|
dialog.showDetails([
|
|
68647
69310
|
theme.fg("text", "You can also use an AWS profile, IAM keys, or role-based credentials."),
|
|
68648
69311
|
theme.fg("muted", "See:"),
|
|
68649
|
-
theme.fg("accent", ` ${
|
|
69312
|
+
theme.fg("accent", ` ${path11.join(getDocsPath(), "providers.md")}`)
|
|
68650
69313
|
]);
|
|
68651
69314
|
}
|
|
68652
69315
|
this.editorContainer.clear();
|
|
@@ -68939,7 +69602,7 @@ ${packageLines}`, 1, 0));
|
|
|
68939
69602
|
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
|
68940
69603
|
return;
|
|
68941
69604
|
}
|
|
68942
|
-
const tmpFile =
|
|
69605
|
+
const tmpFile = path11.join(os5.tmpdir(), "session.html");
|
|
68943
69606
|
try {
|
|
68944
69607
|
await this.session.exportToHtml(tmpFile);
|
|
68945
69608
|
} catch (error) {
|
|
@@ -68957,7 +69620,7 @@ ${packageLines}`, 1, 0));
|
|
|
68957
69620
|
this.editorContainer.addChild(this.editor);
|
|
68958
69621
|
this.ui.setFocus(this.editor);
|
|
68959
69622
|
try {
|
|
68960
|
-
|
|
69623
|
+
fs7.unlinkSync(tmpFile);
|
|
68961
69624
|
} catch {
|
|
68962
69625
|
}
|
|
68963
69626
|
};
|
|
@@ -68969,7 +69632,7 @@ ${packageLines}`, 1, 0));
|
|
|
68969
69632
|
};
|
|
68970
69633
|
try {
|
|
68971
69634
|
const result = await new Promise((resolve15) => {
|
|
68972
|
-
proc =
|
|
69635
|
+
proc = spawn13("gh", ["gist", "create", "--public=false", tmpFile]);
|
|
68973
69636
|
let stdout = "";
|
|
68974
69637
|
let stderr = "";
|
|
68975
69638
|
proc.stdout?.on("data", (data) => {
|
|
@@ -69154,8 +69817,8 @@ ${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
|
|
|
69154
69817
|
...this.session.messages.map((msg) => JSON.stringify(msg)),
|
|
69155
69818
|
""
|
|
69156
69819
|
].join("\n");
|
|
69157
|
-
|
|
69158
|
-
|
|
69820
|
+
fs7.mkdirSync(path11.dirname(debugLogPath), { recursive: true });
|
|
69821
|
+
fs7.writeFileSync(debugLogPath, debugData);
|
|
69159
69822
|
this.chatContainer.addChild(new Spacer(1));
|
|
69160
69823
|
this.chatContainer.addChild(new Text(`${theme.fg("accent", "\u2713 Debug log written")}
|
|
69161
69824
|
${theme.fg("muted", debugLogPath)}`, 1, 1));
|
|
@@ -69390,7 +70053,7 @@ async function runPrintMode(runtimeHost, options) {
|
|
|
69390
70053
|
}
|
|
69391
70054
|
|
|
69392
70055
|
// dist/modes/rpc/rpc-client.js
|
|
69393
|
-
import { spawn as
|
|
70056
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
69394
70057
|
|
|
69395
70058
|
// dist/modes/rpc/jsonl.js
|
|
69396
70059
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
@@ -69462,7 +70125,7 @@ var RpcClient = class {
|
|
|
69462
70125
|
if (this.options.args) {
|
|
69463
70126
|
args.push(...this.options.args);
|
|
69464
70127
|
}
|
|
69465
|
-
const childProcess =
|
|
70128
|
+
const childProcess = spawn14("node", [cliPath, ...args], {
|
|
69466
70129
|
cwd: this.options.cwd,
|
|
69467
70130
|
env: { ...process.env, ...this.options.env },
|
|
69468
70131
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -70312,8 +70975,8 @@ async function runRpcMode(runtimeHost) {
|
|
|
70312
70975
|
return success(id, "get_session_stats", stats);
|
|
70313
70976
|
}
|
|
70314
70977
|
case "export_html": {
|
|
70315
|
-
const
|
|
70316
|
-
return success(id, "export_html", { path:
|
|
70978
|
+
const path12 = await session.exportToHtml(command.outputPath);
|
|
70979
|
+
return success(id, "export_html", { path: path12 });
|
|
70317
70980
|
}
|
|
70318
70981
|
case "switch_session": {
|
|
70319
70982
|
const result = await runtimeHost.switchSession(command.sessionPath);
|
|
@@ -70489,12 +71152,12 @@ async function runRpcMode(runtimeHost) {
|
|
|
70489
71152
|
}
|
|
70490
71153
|
|
|
70491
71154
|
// dist/package-manager-cli.js
|
|
70492
|
-
import { join as
|
|
71155
|
+
import { join as join45 } from "node:path";
|
|
70493
71156
|
import chalk11 from "chalk";
|
|
70494
71157
|
|
|
70495
71158
|
// dist/modes/interactive/components/config-selector.js
|
|
70496
71159
|
import { homedir as homedir14 } from "node:os";
|
|
70497
|
-
import { basename as
|
|
71160
|
+
import { basename as basename15, dirname as dirname24, join as join43, relative as relative7 } from "node:path";
|
|
70498
71161
|
var RESOURCE_TYPES2 = ["extensions", "skills", "prompts", "themes"];
|
|
70499
71162
|
var RESOURCE_TYPE_LABELS = {
|
|
70500
71163
|
extensions: "Extensions",
|
|
@@ -70531,7 +71194,7 @@ function buildGroups(resolved, agentDir) {
|
|
|
70531
71194
|
const groupMap = /* @__PURE__ */ new Map();
|
|
70532
71195
|
const addToGroup = (resources, resourceType) => {
|
|
70533
71196
|
for (const res of resources) {
|
|
70534
|
-
const { path:
|
|
71197
|
+
const { path: path12, enabled, metadata } = res;
|
|
70535
71198
|
const groupKey = `${metadata.origin}:${metadata.scope}:${metadata.source}:${metadata.baseDir ?? ""}`;
|
|
70536
71199
|
if (!groupMap.has(groupKey)) {
|
|
70537
71200
|
groupMap.set(groupKey, {
|
|
@@ -70554,8 +71217,8 @@ function buildGroups(resolved, agentDir) {
|
|
|
70554
71217
|
};
|
|
70555
71218
|
group.subgroups.push(subgroup);
|
|
70556
71219
|
}
|
|
70557
|
-
const fileName =
|
|
70558
|
-
const parentFolder =
|
|
71220
|
+
const fileName = basename15(path12);
|
|
71221
|
+
const parentFolder = basename15(dirname24(path12));
|
|
70559
71222
|
let displayName;
|
|
70560
71223
|
if (resourceType === "extensions" && parentFolder !== "extensions") {
|
|
70561
71224
|
displayName = `${parentFolder}/${fileName}`;
|
|
@@ -70565,7 +71228,7 @@ function buildGroups(resolved, agentDir) {
|
|
|
70565
71228
|
displayName = fileName;
|
|
70566
71229
|
}
|
|
70567
71230
|
subgroup.items.push({
|
|
70568
|
-
path:
|
|
71231
|
+
path: path12,
|
|
70569
71232
|
enabled,
|
|
70570
71233
|
metadata,
|
|
70571
71234
|
resourceType,
|
|
@@ -71127,7 +71790,7 @@ var ResourceList = class {
|
|
|
71127
71790
|
return item.metadata.scope === "project" ? "project" : "user";
|
|
71128
71791
|
}
|
|
71129
71792
|
getTopLevelBaseDir(scope) {
|
|
71130
|
-
return scope === "project" ?
|
|
71793
|
+
return scope === "project" ? join43(this.cwd, CONFIG_DIR_NAME) : this.agentDir;
|
|
71131
71794
|
}
|
|
71132
71795
|
getResourcePattern(item) {
|
|
71133
71796
|
const scope = item.metadata.scope;
|
|
@@ -71282,18 +71945,18 @@ async function getLatestPiRelease(currentVersion, options = {}) {
|
|
|
71282
71945
|
}
|
|
71283
71946
|
|
|
71284
71947
|
// dist/utils/windows-self-update.js
|
|
71285
|
-
import { randomUUID as
|
|
71286
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
71287
|
-
import { basename as
|
|
71948
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
71949
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync15, renameSync as renameSync3, rmSync as rmSync6 } from "node:fs";
|
|
71950
|
+
import { basename as basename16, dirname as dirname25, join as join44, relative as relative8, resolve as resolve14, toNamespacedPath } from "node:path";
|
|
71288
71951
|
var QUARANTINE_DIR_NAME = ".pi-native-quarantine";
|
|
71289
|
-
function normalizePath2(
|
|
71290
|
-
return toNamespacedPath(resolve14(
|
|
71952
|
+
function normalizePath2(path12) {
|
|
71953
|
+
return toNamespacedPath(resolve14(path12));
|
|
71291
71954
|
}
|
|
71292
71955
|
function getQuarantineRoot(packageDir) {
|
|
71293
71956
|
let current = resolve14(packageDir);
|
|
71294
71957
|
while (true) {
|
|
71295
|
-
if (
|
|
71296
|
-
return
|
|
71958
|
+
if (basename16(current).toLowerCase() === "node_modules") {
|
|
71959
|
+
return join44(current, QUARANTINE_DIR_NAME);
|
|
71297
71960
|
}
|
|
71298
71961
|
const parent = dirname25(current);
|
|
71299
71962
|
if (parent === current) {
|
|
@@ -71344,12 +72007,12 @@ function quarantineWindowsNativeDependencies(packageDir) {
|
|
|
71344
72007
|
if (loadedFiles.length === 0) {
|
|
71345
72008
|
return;
|
|
71346
72009
|
}
|
|
71347
|
-
const quarantineRunDir =
|
|
72010
|
+
const quarantineRunDir = join44(quarantineRoot, `${Date.now()}-${process.pid}-${randomUUID7()}`);
|
|
71348
72011
|
for (const loadedFile of loadedFiles) {
|
|
71349
|
-
if (!
|
|
72012
|
+
if (!existsSync29(loadedFile)) {
|
|
71350
72013
|
continue;
|
|
71351
72014
|
}
|
|
71352
|
-
const quarantinePath =
|
|
72015
|
+
const quarantinePath = join44(quarantineRunDir, relative8(resolvedPackageDir, loadedFile));
|
|
71353
72016
|
mkdirSync15(dirname25(quarantinePath), { recursive: true });
|
|
71354
72017
|
renameSync3(loadedFile, quarantinePath);
|
|
71355
72018
|
copyFileSync2(quarantinePath, loadedFile);
|
|
@@ -71673,8 +72336,8 @@ async function refreshModelCatalogs(agentDir) {
|
|
|
71673
72336
|
const timeout = setTimeout(() => controller.abort(), 15e3);
|
|
71674
72337
|
try {
|
|
71675
72338
|
const modelRuntime = await ModelRuntime.create({
|
|
71676
|
-
authPath:
|
|
71677
|
-
modelsPath:
|
|
72339
|
+
authPath: join45(agentDir, "auth.json"),
|
|
72340
|
+
modelsPath: join45(agentDir, "models.json"),
|
|
71678
72341
|
allowModelNetwork: false,
|
|
71679
72342
|
signal: controller.signal
|
|
71680
72343
|
});
|
|
@@ -72249,9 +72912,9 @@ function validateSessionIdFlags(parsed) {
|
|
|
72249
72912
|
process.exit(1);
|
|
72250
72913
|
}
|
|
72251
72914
|
}
|
|
72252
|
-
function openSessionOrExit(
|
|
72915
|
+
function openSessionOrExit(path12, sessionDir) {
|
|
72253
72916
|
try {
|
|
72254
|
-
return SessionManager.open(
|
|
72917
|
+
return SessionManager.open(path12, sessionDir);
|
|
72255
72918
|
} catch (error) {
|
|
72256
72919
|
const message = error instanceof Error ? error.message : String(error);
|
|
72257
72920
|
console.error(chalk12.red(`Error: ${message}`));
|
|
@@ -72608,9 +73271,9 @@ async function main(args, options) {
|
|
|
72608
73271
|
...projectTrustDiagnostics,
|
|
72609
73272
|
...services2.diagnostics,
|
|
72610
73273
|
...collectSettingsDiagnostics(settingsManager2, "runtime creation"),
|
|
72611
|
-
...resourceLoader2.getExtensions().errors.map(({ path:
|
|
73274
|
+
...resourceLoader2.getExtensions().errors.map(({ path: path12, error }) => ({
|
|
72612
73275
|
type: "error",
|
|
72613
|
-
message: `Failed to load extension "${
|
|
73276
|
+
message: `Failed to load extension "${path12}": ${error}`
|
|
72614
73277
|
}))
|
|
72615
73278
|
];
|
|
72616
73279
|
const modelPatterns = parsed.models ?? settingsManager2.getEnabledModels();
|