Skip to content

Commit c641c59

Browse files
authored
Merge pull request #846 from RooVetGit/cte/catch-openai-provider-error
Prevent *all* provider clients from throwing
2 parents c14de4f + 4b3ea07 commit c641c59

File tree

10 files changed

+37
-49
lines changed

10 files changed

+37
-49
lines changed

src/api/providers/__tests__/deepseek.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe("DeepSeekHandler", () => {
8484
expect(handler.getModel().id).toBe(mockOptions.apiModelId)
8585
})
8686

87-
it("should throw error if API key is missing", () => {
87+
it.skip("should throw error if API key is missing", () => {
8888
expect(() => {
8989
new DeepSeekHandler({
9090
...mockOptions,

src/api/providers/__tests__/gemini.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe("GeminiHandler", () => {
3333
expect(handler["options"].apiModelId).toBe("gemini-2.0-flash-thinking-exp-1219")
3434
})
3535

36-
it("should throw if API key is missing", () => {
36+
it.skip("should throw if API key is missing", () => {
3737
expect(() => {
3838
new GeminiHandler({
3939
apiModelId: "gemini-2.0-flash-thinking-exp-1219",

src/api/providers/deepseek.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@ import { deepSeekModels, deepSeekDefaultModelId } from "../../shared/api"
44

55
export class DeepSeekHandler extends OpenAiHandler {
66
constructor(options: ApiHandlerOptions) {
7-
if (!options.deepSeekApiKey) {
8-
throw new Error("DeepSeek API key is required. Please provide it in the settings.")
9-
}
107
super({
118
...options,
12-
openAiApiKey: options.deepSeekApiKey,
9+
openAiApiKey: options.deepSeekApiKey ?? "not-provided",
1310
openAiModelId: options.apiModelId ?? deepSeekDefaultModelId,
1411
openAiBaseUrl: options.deepSeekBaseUrl ?? "https://api.deepseek.com/v1",
1512
openAiStreamingEnabled: true,

src/api/providers/gemini.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ export class GeminiHandler implements ApiHandler, SingleCompletionHandler {
1010
private client: GoogleGenerativeAI
1111

1212
constructor(options: ApiHandlerOptions) {
13-
if (!options.geminiApiKey) {
14-
throw new Error("API key is required for Google Gemini")
15-
}
1613
this.options = options
17-
this.client = new GoogleGenerativeAI(options.geminiApiKey)
14+
this.client = new GoogleGenerativeAI(options.geminiApiKey ?? "not-provided")
1815
}
1916

2017
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {

src/api/providers/glama.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ export class GlamaHandler implements ApiHandler, SingleCompletionHandler {
1313

1414
constructor(options: ApiHandlerOptions) {
1515
this.options = options
16-
this.client = new OpenAI({
17-
baseURL: "https://glama.ai/api/gateway/openai/v1",
18-
apiKey: this.options.glamaApiKey,
19-
})
16+
const baseURL = "https://glama.ai/api/gateway/openai/v1"
17+
const apiKey = this.options.glamaApiKey ?? "not-provided"
18+
this.client = new OpenAI({ baseURL, apiKey })
2019
}
2120

2221
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {

src/api/providers/openai-native.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
1717

1818
constructor(options: ApiHandlerOptions) {
1919
this.options = options
20-
this.client = new OpenAI({
21-
apiKey: this.options.openAiNativeApiKey,
22-
})
20+
const apiKey = this.options.openAiNativeApiKey ?? "not-provided"
21+
this.client = new OpenAI({ apiKey })
2322
}
2423

2524
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
@@ -41,7 +40,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
4140
private async *handleO1FamilyMessage(
4241
modelId: string,
4342
systemPrompt: string,
44-
messages: Anthropic.Messages.MessageParam[]
43+
messages: Anthropic.Messages.MessageParam[],
4544
): ApiStream {
4645
// o1 supports developer prompt with formatting
4746
// o1-preview and o1-mini only support user messages
@@ -63,7 +62,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
6362
private async *handleO3FamilyMessage(
6463
modelId: string,
6564
systemPrompt: string,
66-
messages: Anthropic.Messages.MessageParam[]
65+
messages: Anthropic.Messages.MessageParam[],
6766
): ApiStream {
6867
const stream = await this.client.chat.completions.create({
6968
model: "o3-mini",
@@ -85,7 +84,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
8584
private async *handleDefaultModelMessage(
8685
modelId: string,
8786
systemPrompt: string,
88-
messages: Anthropic.Messages.MessageParam[]
87+
messages: Anthropic.Messages.MessageParam[],
8988
): ApiStream {
9089
const stream = await this.client.chat.completions.create({
9190
model: modelId,
@@ -98,9 +97,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
9897
yield* this.handleStreamResponse(stream)
9998
}
10099

101-
private async *yieldResponseData(
102-
response: OpenAI.Chat.Completions.ChatCompletion
103-
): ApiStream {
100+
private async *yieldResponseData(response: OpenAI.Chat.Completions.ChatCompletion): ApiStream {
104101
yield {
105102
type: "text",
106103
text: response.choices[0]?.message.content || "",
@@ -112,9 +109,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
112109
}
113110
}
114111

115-
private async *handleStreamResponse(
116-
stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>
117-
): ApiStream {
112+
private async *handleStreamResponse(stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>): ApiStream {
118113
for await (const chunk of stream) {
119114
const delta = chunk.choices[0]?.delta
120115
if (delta?.content) {
@@ -168,7 +163,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
168163

169164
private getO1CompletionOptions(
170165
modelId: string,
171-
prompt: string
166+
prompt: string,
172167
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
173168
return {
174169
model: modelId,
@@ -178,7 +173,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
178173

179174
private getO3CompletionOptions(
180175
modelId: string,
181-
prompt: string
176+
prompt: string,
182177
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
183178
return {
184179
model: "o3-mini",
@@ -189,7 +184,7 @@ export class OpenAiNativeHandler implements ApiHandler, SingleCompletionHandler
189184

190185
private getDefaultCompletionOptions(
191186
modelId: string,
192-
prompt: string
187+
prompt: string,
193188
): OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming {
194189
return {
195190
model: modelId,

src/api/providers/openai.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export class OpenAiHandler implements ApiHandler, SingleCompletionHandler {
1919
constructor(options: ApiHandlerOptions) {
2020
this.options = options
2121

22+
const baseURL = this.options.openAiBaseUrl ?? "https://api.openai.com/v1"
23+
const apiKey = this.options.openAiApiKey ?? "not-provided"
2224
let urlHost: string
2325

2426
try {
@@ -33,15 +35,12 @@ export class OpenAiHandler implements ApiHandler, SingleCompletionHandler {
3335
// Azure API shape slightly differs from the core API shape:
3436
// https://github.com/openai/openai-node?tab=readme-ov-file#microsoft-azure-openai
3537
this.client = new AzureOpenAI({
36-
baseURL: this.options.openAiBaseUrl,
37-
apiKey: this.options.openAiApiKey,
38+
baseURL,
39+
apiKey,
3840
apiVersion: this.options.azureApiVersion || azureOpenAiDefaultApiVersion,
3941
})
4042
} else {
41-
this.client = new OpenAI({
42-
baseURL: this.options.openAiBaseUrl,
43-
apiKey: this.options.openAiApiKey,
44-
})
43+
this.client = new OpenAI({ baseURL, apiKey })
4544
}
4645
}
4746

src/api/providers/openrouter.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ export class OpenRouterHandler implements ApiHandler, SingleCompletionHandler {
2727

2828
constructor(options: ApiHandlerOptions) {
2929
this.options = options
30-
this.client = new OpenAI({
31-
baseURL: this.options.openRouterBaseUrl || "https://openrouter.ai/api/v1",
32-
apiKey: this.options.openRouterApiKey,
33-
defaultHeaders: {
34-
"HTTP-Referer": "https://github.com/RooVetGit/Roo-Cline",
35-
"X-Title": "Roo Code",
36-
},
37-
})
30+
31+
const baseURL = this.options.openRouterBaseUrl || "https://openrouter.ai/api/v1"
32+
const apiKey = this.options.openRouterApiKey ?? "not-provided"
33+
34+
const defaultHeaders = {
35+
"HTTP-Referer": "https://github.com/RooVetGit/Roo-Cline",
36+
"X-Title": "Roo Code",
37+
}
38+
39+
this.client = new OpenAI({ baseURL, apiKey, defaultHeaders })
3840
}
3941

4042
async *createMessage(

src/api/providers/unbound.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ export class UnboundHandler implements ApiHandler, SingleCompletionHandler {
1616

1717
constructor(options: ApiHandlerOptions) {
1818
this.options = options
19-
this.client = new OpenAI({
20-
baseURL: "https://api.getunbound.ai/v1",
21-
apiKey: this.options.unboundApiKey,
22-
})
19+
const baseURL = "https://api.getunbound.ai/v1"
20+
const apiKey = this.options.unboundApiKey ?? "not-provided"
21+
this.client = new OpenAI({ baseURL, apiKey })
2322
}
2423

2524
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {

src/api/providers/vertex.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export class VertexHandler implements ApiHandler, SingleCompletionHandler {
1212
constructor(options: ApiHandlerOptions) {
1313
this.options = options
1414
this.client = new AnthropicVertex({
15-
projectId: this.options.vertexProjectId,
15+
projectId: this.options.vertexProjectId ?? "not-provided",
1616
// https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude#regions
17-
region: this.options.vertexRegion,
17+
region: this.options.vertexRegion ?? "us-east5",
1818
})
1919
}
2020

0 commit comments

Comments
 (0)