Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/api/providers/__tests__/groq.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/groq.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import OpenAI from "openai"
import { Anthropic } from "@anthropic-ai/sdk"

Expand Down
3 changes: 0 additions & 3 deletions src/api/providers/__tests__/lite-llm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { LiteLLMHandler } from "../lite-llm"
import { ApiHandlerOptions } from "../../../shared/api"
import { litellmDefaultModelId, litellmDefaultModelInfo } from "@roo-code/types"

// Mock vscode first to avoid import errors
vi.mock("vscode", () => ({}))

// Mock OpenAI
vi.mock("openai", () => {
const mockStream = {
Expand Down
4 changes: 2 additions & 2 deletions src/api/providers/__tests__/lm-studio-timeout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("LmStudioHandler timeout configuration", () => {
)
})

it("should handle zero timeout (no timeout)", () => {
it("should handle zero timeout", () => {
;(getApiRequestTimeout as any).mockReturnValue(0)

const options: ApiHandlerOptions = {
Expand All @@ -84,7 +84,7 @@ describe("LmStudioHandler timeout configuration", () => {

expect(mockOpenAIConstructor).toHaveBeenCalledWith(
expect.objectContaining({
timeout: 0, // No timeout
timeout: 0,
}),
)
})
Expand Down
2 changes: 1 addition & 1 deletion src/api/providers/__tests__/ollama-timeout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe("OllamaHandler timeout configuration", () => {

expect(mockOpenAIConstructor).toHaveBeenCalledWith(
expect.objectContaining({
timeout: 0, // No timeout
timeout: 0,
}),
)
})
Expand Down
2 changes: 1 addition & 1 deletion src/api/providers/__tests__/openai-timeout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ describe("OpenAiHandler timeout configuration", () => {

expect(mockOpenAIConstructor).toHaveBeenCalledWith(
expect.objectContaining({
timeout: 0, // No timeout
timeout: 0,
}),
)
})
Expand Down
4 changes: 1 addition & 3 deletions src/api/providers/__tests__/openrouter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/openrouter.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"

Expand Down Expand Up @@ -65,6 +62,7 @@ describe("OpenRouterHandler", () => {
"X-Title": "Roo Code",
"User-Agent": `RooCode/${Package.version}`,
},
timeout: 600000,
})
})

Expand Down
2 changes: 2 additions & 0 deletions src/api/providers/__tests__/requesty.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe("RequestyHandler", () => {
"X-Title": "Roo Code",
"User-Agent": `RooCode/${Package.version}`,
},
timeout: 600000,
})
})

Expand All @@ -77,6 +78,7 @@ describe("RequestyHandler", () => {
"X-Title": "Roo Code",
"User-Agent": `RooCode/${Package.version}`,
},
timeout: 600000,
})
})

Expand Down
3 changes: 0 additions & 3 deletions src/api/providers/__tests__/sambanova.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/sambanova.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import OpenAI from "openai"
import { Anthropic } from "@anthropic-ai/sdk"

Expand Down
4 changes: 1 addition & 3 deletions src/api/providers/__tests__/vercel-ai-gateway.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/vercel-ai-gateway.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import { Anthropic } from "@anthropic-ai/sdk"
import OpenAI from "openai"

Expand Down Expand Up @@ -102,6 +99,7 @@ describe("VercelAiGatewayHandler", () => {
"X-Title": "Roo Code",
"User-Agent": expect.stringContaining("RooCode/"),
}),
timeout: 600000,
})
})

Expand Down
3 changes: 0 additions & 3 deletions src/api/providers/__tests__/vertex.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/vertex.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import { Anthropic } from "@anthropic-ai/sdk"

import { ApiStreamChunk } from "../../transform/stream"
Expand Down
3 changes: 0 additions & 3 deletions src/api/providers/__tests__/zai.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// npx vitest run src/api/providers/__tests__/zai.spec.ts

// Mock vscode first to avoid import errors
vitest.mock("vscode", () => ({}))

import OpenAI from "openai"
import { Anthropic } from "@anthropic-ai/sdk"

Expand Down
4 changes: 4 additions & 0 deletions src/api/providers/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getModelParams } from "../transform/model-params"
import { BaseProvider } from "./base-provider"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { calculateApiCostAnthropic } from "../../shared/cost"
import { getApiRequestTimeout } from "./utils/timeout-config"

export class AnthropicHandler extends BaseProvider implements SingleCompletionHandler {
private options: ApiHandlerOptions
Expand All @@ -30,9 +31,12 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
const apiKeyFieldName =
this.options.anthropicBaseUrl && this.options.anthropicUseAuthToken ? "authToken" : "apiKey"

const timeout = getApiRequestTimeout()

this.client = new Anthropic({
baseURL: this.options.anthropicBaseUrl || undefined,
[apiKeyFieldName]: this.options.apiKey,
timeout,
})
}

Expand Down
4 changes: 4 additions & 0 deletions src/api/providers/base-openai-compatible-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { convertToOpenAiMessages } from "../transform/openai-format"

import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { DEFAULT_HEADERS } from "./constants"
import { getApiRequestTimeout } from "./utils/timeout-config"
import { BaseProvider } from "./base-provider"
import { handleOpenAIError } from "./utils/openai-error-handler"

Expand Down Expand Up @@ -56,10 +57,13 @@ export abstract class BaseOpenAiCompatibleProvider<ModelName extends string>
throw new Error("API key is required")
}

const timeout = getApiRequestTimeout()

this.client = new OpenAI({
baseURL,
apiKey: this.options.apiKey,
defaultHeaders: DEFAULT_HEADERS,
timeout,
})
}

Expand Down
27 changes: 20 additions & 7 deletions src/api/providers/bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { convertToBedrockConverseMessages as sharedConverter } from "../transfor
import { getModelParams } from "../transform/model-params"
import { shouldUseReasoningBudget } from "../../shared/api"
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
import { getApiRequestTimeout } from "./utils/timeout-config"

/************************************************************************************
*
Expand Down Expand Up @@ -401,17 +402,17 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
...(thinkingEnabled && { anthropic_version: "bedrock-2023-05-31" }),
}

// Create AbortController with 10 minute timeout
// Create AbortController with configured timeout
const controller = new AbortController()
let timeoutId: NodeJS.Timeout | undefined
const timeoutMs = getApiRequestTimeout()

try {
timeoutId = setTimeout(
() => {
if (timeoutMs !== 0) {
timeoutId = setTimeout(() => {
controller.abort()
},
10 * 60 * 1000,
)
}, timeoutMs)
}

const command = new ConverseStreamCommand(payload)
const response = await this.client.send(command, {
Expand Down Expand Up @@ -670,8 +671,18 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
inferenceConfig,
}

const controller = new AbortController()
let timeoutId: NodeJS.Timeout | undefined
const timeoutMs = getApiRequestTimeout()

if (timeoutMs !== 0) {
timeoutId = setTimeout(() => {
controller.abort()
}, timeoutMs)
}

const command = new ConverseCommand(payload)
const response = await this.client.send(command)
const response = await this.client.send(command, { abortSignal: controller.signal })

if (
response?.output?.message?.content &&
Expand All @@ -680,6 +691,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
response.output.message.content[0].text.trim().length > 0
) {
try {
if (timeoutId) clearTimeout(timeoutId)
return response.output.message.content[0].text
} catch (parseError) {
logger.error("Failed to parse Bedrock response", {
Expand All @@ -688,6 +700,7 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
})
}
}
if (timeoutId) clearTimeout(timeoutId)
return ""
} catch (error) {
// Use the extracted error handling method for all errors
Expand Down
Loading
Loading