Skip to content

Commit 6f30283

Browse files
committed
fix: resolve memory leak in RooHandler event listener
- Add private authStateListener property to store listener reference - Store listener function reference for proper cleanup - Implement dispose() method to remove event listener - Fix API key issue by using cloudService reference instead of CloudService.instance - Update tests to include on/off methods in CloudService mock This prevents memory leaks when multiple RooHandler instances are created and ensures proper cleanup of event listeners.
1 parent f4fb8ee commit 6f30283

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ vitest.mock("@roo-code/cloud", () => ({
8282
authService: {
8383
getSessionToken: () => mockGetSessionTokenFn(),
8484
},
85+
on: vitest.fn(),
86+
off: vitest.fn(),
8587
}
8688
},
8789
},
@@ -413,7 +415,11 @@ describe("RooHandler", () => {
413415

414416
try {
415417
Object.defineProperty(CloudService, "instance", {
416-
get: () => ({ authService: undefined }),
418+
get: () => ({
419+
authService: undefined,
420+
on: vitest.fn(),
421+
off: vitest.fn(),
422+
}),
417423
configurable: true,
418424
})
419425

src/api/providers/roo.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { DEFAULT_HEADERS } from "./constants"
1212
import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider"
1313

1414
export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
15+
private authStateListener?: (state: { state: AuthState }) => void
16+
1517
constructor(options: ApiHandlerOptions) {
1618
let sessionToken: string | undefined = undefined
1719

@@ -34,11 +36,11 @@ export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
3436
if (CloudService.hasInstance()) {
3537
const cloudService = CloudService.instance
3638

37-
cloudService.on("auth-state-changed", (state: { state: AuthState }) => {
39+
this.authStateListener = (state: { state: AuthState }) => {
3840
if (state.state === "active-session") {
3941
this.client = new OpenAI({
4042
baseURL: this.baseURL,
41-
apiKey: CloudService.instance.authService?.getSessionToken() ?? "unauthenticated",
43+
apiKey: cloudService.authService?.getSessionToken() ?? "unauthenticated",
4244
defaultHeaders: DEFAULT_HEADERS,
4345
})
4446
} else if (state.state === "logged-out") {
@@ -48,7 +50,15 @@ export class RooHandler extends BaseOpenAiCompatibleProvider<RooModelId> {
4850
defaultHeaders: DEFAULT_HEADERS,
4951
})
5052
}
51-
})
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)
5262
}
5363
}
5464

0 commit comments

Comments
 (0)