Skip to content

Commit b044e19

Browse files
committed
feat(openrouter): add improvements to openrouter provider
1 parent 0fbbe66 commit b044e19

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

src/api/providers/__tests__/openrouter.spec.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,28 @@ vitest.mock("../fetchers/modelCache", () => ({
6161
cacheReadsPrice: 0.3,
6262
description: "Claude 3.7 Sonnet with thinking",
6363
},
64+
"openai/gpt-4o": {
65+
maxTokens: 16384,
66+
contextWindow: 128000,
67+
supportsImages: true,
68+
supportsPromptCache: false,
69+
supportsNativeTools: true,
70+
inputPrice: 2.5,
71+
outputPrice: 10,
72+
description: "GPT-4o",
73+
},
74+
"openai/o1": {
75+
maxTokens: 100000,
76+
contextWindow: 200000,
77+
supportsImages: true,
78+
supportsPromptCache: false,
79+
supportsNativeTools: true,
80+
inputPrice: 15,
81+
outputPrice: 60,
82+
description: "OpenAI o1",
83+
excludedTools: ["existing_excluded"],
84+
includedTools: ["existing_included"],
85+
},
6486
})
6587
}),
6688
}))
@@ -138,6 +160,51 @@ describe("OpenRouterHandler", () => {
138160
expect(result.reasoningBudget).toBeUndefined()
139161
expect(result.temperature).toBe(0)
140162
})
163+
164+
it("adds excludedTools and includedTools for OpenAI models", async () => {
165+
const handler = new OpenRouterHandler({
166+
openRouterApiKey: "test-key",
167+
openRouterModelId: "openai/gpt-4o",
168+
})
169+
170+
const result = await handler.fetchModel()
171+
expect(result.id).toBe("openai/gpt-4o")
172+
expect(result.info.excludedTools).toContain("apply_diff")
173+
expect(result.info.excludedTools).toContain("write_to_file")
174+
expect(result.info.includedTools).toContain("apply_patch")
175+
})
176+
177+
it("merges excludedTools and includedTools with existing values for OpenAI models", async () => {
178+
const handler = new OpenRouterHandler({
179+
openRouterApiKey: "test-key",
180+
openRouterModelId: "openai/o1",
181+
})
182+
183+
const result = await handler.fetchModel()
184+
expect(result.id).toBe("openai/o1")
185+
// Should have the new exclusions
186+
expect(result.info.excludedTools).toContain("apply_diff")
187+
expect(result.info.excludedTools).toContain("write_to_file")
188+
// Should preserve existing exclusions
189+
expect(result.info.excludedTools).toContain("existing_excluded")
190+
// Should have the new inclusions
191+
expect(result.info.includedTools).toContain("apply_patch")
192+
// Should preserve existing inclusions
193+
expect(result.info.includedTools).toContain("existing_included")
194+
})
195+
196+
it("does not add excludedTools or includedTools for non-OpenAI models", async () => {
197+
const handler = new OpenRouterHandler({
198+
openRouterApiKey: "test-key",
199+
openRouterModelId: "anthropic/claude-sonnet-4",
200+
})
201+
202+
const result = await handler.fetchModel()
203+
expect(result.id).toBe("anthropic/claude-sonnet-4")
204+
// Should NOT have the tool exclusions/inclusions
205+
expect(result.info.excludedTools).toBeUndefined()
206+
expect(result.info.includedTools).toBeUndefined()
207+
})
141208
})
142209

143210
describe("createMessage", () => {

src/api/providers/openrouter.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,16 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
432432
info = this.endpoints[this.options.openRouterSpecificProvider]
433433
}
434434

435+
// For OpenAI models via OpenRouter, exclude write_to_file and apply_diff, and include apply_patch
436+
// This matches the behavior of the native OpenAI provider
437+
if (id.startsWith("openai/")) {
438+
info = {
439+
...info,
440+
excludedTools: [...new Set([...(info.excludedTools || []), "apply_diff", "write_to_file"])],
441+
includedTools: [...new Set([...(info.includedTools || []), "apply_patch"])],
442+
}
443+
}
444+
435445
const isDeepSeekR1 = id.startsWith("deepseek/deepseek-r1") || id === "perplexity/sonar-reasoning"
436446

437447
const params = getModelParams({

0 commit comments

Comments
 (0)