mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
refactor: Remove exceptions from RooHandler constructor (#7302)
This commit is contained in:
parent
0bc1183c71
commit
44fd6432dc
4 changed files with 49 additions and 22 deletions
|
|
@ -143,6 +143,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
|
|||
case "io-intelligence":
|
||||
return new IOIntelligenceHandler(options)
|
||||
case "roo":
|
||||
// Never throw exceptions from provider constructors
|
||||
// The provider-proxy server will handle authentication and return appropriate error codes
|
||||
return new RooHandler(options)
|
||||
case "featherless":
|
||||
return new FeatherlessHandler(options)
|
||||
|
|
|
|||
|
|
@ -131,21 +131,25 @@ describe("RooHandler", () => {
|
|||
expect(handler.getModel().id).toBe(mockOptions.apiModelId)
|
||||
})
|
||||
|
||||
it("should throw error if CloudService is not available", () => {
|
||||
it("should not throw error if CloudService is not available", () => {
|
||||
mockHasInstanceFn.mockReturnValue(false)
|
||||
expect(() => {
|
||||
new RooHandler(mockOptions)
|
||||
}).toThrow("Authentication required for Roo Code Cloud")
|
||||
expect(t).toHaveBeenCalledWith("common:errors.roo.authenticationRequired")
|
||||
}).not.toThrow()
|
||||
// Constructor should succeed even without CloudService
|
||||
const handler = new RooHandler(mockOptions)
|
||||
expect(handler).toBeInstanceOf(RooHandler)
|
||||
})
|
||||
|
||||
it("should throw error if session token is not available", () => {
|
||||
it("should not throw error if session token is not available", () => {
|
||||
mockHasInstanceFn.mockReturnValue(true)
|
||||
mockGetSessionTokenFn.mockReturnValue(null)
|
||||
expect(() => {
|
||||
new RooHandler(mockOptions)
|
||||
}).toThrow("Authentication required for Roo Code Cloud")
|
||||
expect(t).toHaveBeenCalledWith("common:errors.roo.authenticationRequired")
|
||||
}).not.toThrow()
|
||||
// Constructor should succeed even without session token
|
||||
const handler = new RooHandler(mockOptions)
|
||||
expect(handler).toBeInstanceOf(RooHandler)
|
||||
})
|
||||
|
||||
it("should initialize with default model if no model specified", () => {
|
||||
|
|
@ -400,7 +404,7 @@ describe("RooHandler", () => {
|
|||
expect(mockGetSessionTokenFn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should handle undefined auth service", () => {
|
||||
it("should handle undefined auth service gracefully", () => {
|
||||
mockHasInstanceFn.mockReturnValue(true)
|
||||
// Mock CloudService with undefined authService
|
||||
const originalGetter = Object.getOwnPropertyDescriptor(CloudService, "instance")?.get
|
||||
|
|
@ -413,7 +417,10 @@ describe("RooHandler", () => {
|
|||
|
||||
expect(() => {
|
||||
new RooHandler(mockOptions)
|
||||
}).toThrow("Authentication required for Roo Code Cloud")
|
||||
}).not.toThrow()
|
||||
// Constructor should succeed even with undefined auth service
|
||||
const handler = new RooHandler(mockOptions)
|
||||
expect(handler).toBeInstanceOf(RooHandler)
|
||||
} finally {
|
||||
// Always restore original getter, even if test fails
|
||||
if (originalGetter) {
|
||||
|
|
@ -425,12 +432,15 @@ describe("RooHandler", () => {
|
|||
}
|
||||
})
|
||||
|
||||
it("should handle empty session token", () => {
|
||||
it("should handle empty session token gracefully", () => {
|
||||
mockGetSessionTokenFn.mockReturnValue("")
|
||||
|
||||
expect(() => {
|
||||
new RooHandler(mockOptions)
|
||||
}).toThrow("Authentication required for Roo Code Cloud")
|
||||
}).not.toThrow()
|
||||
// Constructor should succeed even with empty session token
|
||||
const handler = new RooHandler(mockOptions)
|
||||
expect(handler).toBeInstanceOf(RooHandler)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,29 +4,27 @@ import { CloudService } from "@roo-code/cloud"
|
|||
|
||||
import type { ApiHandlerOptions } from "../../shared/api"
|
||||
import { ApiStream } from "../transform/stream"
|
||||
import { t } from "../../i18n"
|
||||
|
||||
import type { ApiHandlerCreateMessageMetadata } from "../index"
|
||||
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
|
||||
|
||||
export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
|
||||
constructor(options: ApiHandlerOptions) {
|
||||
// Check if CloudService is available and get the session token.
|
||||
if (!CloudService.hasInstance()) {
|
||||
throw new Error(t("common:errors.roo.authenticationRequired"))
|
||||
}
|
||||
|
||||
const sessionToken = CloudService.instance.authService?.getSessionToken()
|
||||
|
||||
if (!sessionToken) {
|
||||
throw new Error(t("common:errors.roo.authenticationRequired"))
|
||||
// Get the session token if available, but don't throw if not.
|
||||
// The server will handle authentication errors and return appropriate status codes.
|
||||
let sessionToken = ""
|
||||
|
||||
if (CloudService.hasInstance()) {
|
||||
sessionToken = CloudService.instance.authService?.getSessionToken() || ""
|
||||
}
|
||||
|
||||
// Always construct the handler, even without a valid token.
|
||||
// The provider-proxy server will return 401 if authentication fails.
|
||||
super({
|
||||
...options,
|
||||
providerName: "Roo Code Cloud",
|
||||
baseURL: process.env.ROO_CODE_PROVIDER_URL ?? "https://api.roocode.com/proxy/v1",
|
||||
apiKey: sessionToken,
|
||||
apiKey: sessionToken || "unauthenticated", // Use a placeholder if no token
|
||||
defaultProviderModelId: rooDefaultModelId,
|
||||
providerModels: rooModels,
|
||||
defaultTemperature: 0.7,
|
||||
|
|
|
|||
|
|
@ -288,7 +288,24 @@ export const webviewMessageHandler = async (
|
|||
// Initializing new instance of Cline will make sure that any
|
||||
// agentically running promises in old instance don't affect our new
|
||||
// task. This essentially creates a fresh slate for the new task.
|
||||
await provider.createTask(message.text, message.images)
|
||||
try {
|
||||
await provider.createTask(message.text, message.images)
|
||||
// Task created successfully - notify the UI to reset
|
||||
await provider.postMessageToWebview({
|
||||
type: "invoke",
|
||||
invoke: "newChat",
|
||||
})
|
||||
} catch (error) {
|
||||
// For all errors, reset the UI and show error
|
||||
await provider.postMessageToWebview({
|
||||
type: "invoke",
|
||||
invoke: "newChat",
|
||||
})
|
||||
// Show error to user
|
||||
vscode.window.showErrorMessage(
|
||||
`Failed to create task: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
break
|
||||
case "customInstructions":
|
||||
await provider.updateCustomInstructions(message.text)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue