Skip to content

Commit 4dbfb96

Browse files
cteroomote
authored andcommitted
Bare metal evals fixes (RooCodeInc#8224)
Co-authored-by: Roo Code <[email protected]>
1 parent e70a4fa commit 4dbfb96

File tree

7 files changed

+62
-38
lines changed

7 files changed

+62
-38
lines changed

apps/web-evals/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"scripts": {
66
"lint": "next lint --max-warnings 0",
77
"check-types": "tsc -b",
8-
"dev": "scripts/check-services.sh && next dev",
8+
"dev": "scripts/check-services.sh && next dev -p 3446",
99
"format": "prettier --write src",
1010
"build": "next build",
1111
"start": "next start",

packages/evals/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ By default, the evals system uses the following ports:
9595

9696
- **PostgreSQL**: 5433 (external) → 5432 (internal)
9797
- **Redis**: 6380 (external) → 6379 (internal)
98-
- **Web Service**: 3446 (external) → 3000 (internal)
98+
- **Web Service**: 3446 (external) → 3446 (internal)
9999

100100
These ports are configured to avoid conflicts with other services that might be running on the standard PostgreSQL (5432) and Redis (6379) ports.
101101

packages/evals/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ services:
5252
context: ../../
5353
dockerfile: packages/evals/Dockerfile.web
5454
ports:
55-
- "${EVALS_WEB_PORT:-3446}:3000"
55+
- "${EVALS_WEB_PORT:-3446}:3446"
5656
environment:
5757
- HOST_EXECUTION_METHOD=docker
5858
volumes:

packages/evals/scripts/setup.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ build_extension() {
1212
echo "🔨 Building the Roo Code extension..."
1313
pnpm -w vsix -- --out ../bin/roo-code-$(git rev-parse --short HEAD).vsix || exit 1
1414
code --install-extension ../../bin/roo-code-$(git rev-parse --short HEAD).vsix || exit 1
15-
cd evals
1615
}
1716

1817
check_docker_services() {
@@ -377,7 +376,7 @@ fi
377376

378377
echo -e "\n🚀 You're ready to rock and roll! \n"
379378

380-
if ! nc -z localhost 3000; then
379+
if ! nc -z localhost 3446; then
381380
read -p "🌐 Would you like to start the evals web app? (Y/n): " start_evals
382381

383382
if [[ "$start_evals" =~ ^[Yy]|^$ ]]; then
@@ -386,5 +385,5 @@ if ! nc -z localhost 3000; then
386385
echo "💡 You can start it anytime with 'pnpm --filter @roo-code/web-evals dev'."
387386
fi
388387
else
389-
echo "👟 The evals web app is running at http://localhost:3000 (or http://localhost:3446 if using Docker)"
388+
echo "👟 The evals web app is running at http://localhost:3446"
390389
fi

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

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,12 @@ vitest.mock("openai", () => {
3636
return {
3737
[Symbol.asyncIterator]: async function* () {
3838
yield {
39-
choices: [
40-
{
41-
delta: { content: "Test response" },
42-
index: 0,
43-
},
44-
],
39+
choices: [{ delta: { content: "Test response" }, index: 0 }],
4540
usage: null,
4641
}
4742
yield {
48-
choices: [
49-
{
50-
delta: {},
51-
index: 0,
52-
},
53-
],
54-
usage: {
55-
prompt_tokens: 10,
56-
completion_tokens: 5,
57-
total_tokens: 15,
58-
},
43+
choices: [{ delta: {}, index: 0 }],
44+
usage: { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 },
5945
}
6046
},
6147
}
@@ -73,6 +59,7 @@ const mockHasInstance = vitest.fn()
7359
// Create mock functions that we can control
7460
const mockGetSessionTokenFn = vitest.fn()
7561
const mockHasInstanceFn = vitest.fn()
62+
const mockOnFn = vitest.fn()
7663

7764
vitest.mock("@roo-code/cloud", () => ({
7865
CloudService: {
@@ -82,6 +69,8 @@ vitest.mock("@roo-code/cloud", () => ({
8269
authService: {
8370
getSessionToken: () => mockGetSessionTokenFn(),
8471
},
72+
on: vitest.fn(),
73+
off: vitest.fn(),
8574
}
8675
},
8776
},
@@ -409,11 +398,18 @@ describe("RooHandler", () => {
409398
it("should handle undefined auth service gracefully", () => {
410399
mockHasInstanceFn.mockReturnValue(true)
411400
// Mock CloudService with undefined authService
412-
const originalGetter = Object.getOwnPropertyDescriptor(CloudService, "instance")?.get
401+
const originalGetSessionToken = mockGetSessionTokenFn.getMockImplementation()
402+
403+
// Temporarily make authService return undefined
404+
mockGetSessionTokenFn.mockImplementation(() => undefined)
413405

414406
try {
415407
Object.defineProperty(CloudService, "instance", {
416-
get: () => ({ authService: undefined }),
408+
get: () => ({
409+
authService: undefined,
410+
on: vitest.fn(),
411+
off: vitest.fn(),
412+
}),
417413
configurable: true,
418414
})
419415

@@ -424,12 +420,11 @@ describe("RooHandler", () => {
424420
const handler = new RooHandler(mockOptions)
425421
expect(handler).toBeInstanceOf(RooHandler)
426422
} finally {
427-
// Always restore original getter, even if test fails
428-
if (originalGetter) {
429-
Object.defineProperty(CloudService, "instance", {
430-
get: originalGetter,
431-
configurable: true,
432-
})
423+
// Restore original mock implementation
424+
if (originalGetSessionToken) {
425+
mockGetSessionTokenFn.mockImplementation(originalGetSessionToken)
426+
} else {
427+
mockGetSessionTokenFn.mockReturnValue("test-session-token")
433428
}
434429
}
435430
})

src/api/providers/roo.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import { Anthropic } from "@anthropic-ai/sdk"
2+
import OpenAI from "openai"
23

3-
import { rooDefaultModelId, rooModels, type RooModelId } from "@roo-code/types"
4+
import { AuthState, rooDefaultModelId, rooModels, type RooModelId } from "@roo-code/types"
45
import { CloudService } from "@roo-code/cloud"
56

67
import type { ApiHandlerOptions } from "../../shared/api"
78
import { ApiStream } from "../transform/stream"
89

910
import type { ApiHandlerCreateMessageMetadata } from "../index"
11+
import { DEFAULT_HEADERS } from "./constants"
1012
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
1113

1214
export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
15+
private authStateListener?: (state: { state: AuthState }) => void
16+
1317
constructor(options: ApiHandlerOptions) {
14-
// Get the session token if available, but don't throw if not.
15-
// The server will handle authentication errors and return appropriate status codes.
16-
let sessionToken = ""
18+
let sessionToken: string | undefined = undefined
1719

1820
if (CloudService.hasInstance()) {
19-
sessionToken = CloudService.instance.authService?.getSessionToken() || ""
21+
sessionToken = CloudService.instance.authService?.getSessionToken()
2022
}
2123

2224
// Always construct the handler, even without a valid token.
@@ -25,11 +27,39 @@ export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
2527
...options,
2628
providerName: "Roo Code Cloud",
2729
baseURL: process.env.ROO_CODE_PROVIDER_URL ?? "https://api.roocode.com/proxy/v1",
28-
apiKey: sessionToken || "unauthenticated", // Use a placeholder if no token
30+
apiKey: sessionToken || "unauthenticated", // Use a placeholder if no token.
2931
defaultProviderModelId: rooDefaultModelId,
3032
providerModels: rooModels,
3133
defaultTemperature: 0.7,
3234
})
35+
36+
if (CloudService.hasInstance()) {
37+
const cloudService = CloudService.instance
38+
39+
this.authStateListener = (state: { state: AuthState }) => {
40+
if (state.state === "active-session") {
41+
this.client = new OpenAI({
42+
baseURL: this.baseURL,
43+
apiKey: cloudService.authService?.getSessionToken() ?? "unauthenticated",
44+
defaultHeaders: DEFAULT_HEADERS,
45+
})
46+
} else if (state.state === "logged-out") {
47+
this.client = new OpenAI({
48+
baseURL: this.baseURL,
49+
apiKey: "unauthenticated",
50+
defaultHeaders: DEFAULT_HEADERS,
51+
})
52+
}
53+
}
54+
55+
cloudService.on("auth-state-changed", this.authStateListener)
56+
}
57+
}
58+
59+
dispose() {
60+
if (this.authStateListener && CloudService.hasInstance()) {
61+
CloudService.instance.off("auth-state-changed", this.authStateListener)
62+
}
3363
}
3464

3565
override async *createMessage(

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export async function activate(context: vscode.ExtensionContext) {
194194
// Add to subscriptions for proper cleanup on deactivate.
195195
context.subscriptions.push(cloudService)
196196

197-
// Trigger initial cloud profile sync now that CloudService is ready
197+
// Trigger initial cloud profile sync now that CloudService is ready.
198198
try {
199199
await provider.initializeCloudProfileSyncWhenReady()
200200
} catch (error) {

0 commit comments

Comments
 (0)