From 503b68e4a541500c94104b40e115d46ff52973d6 Mon Sep 17 00:00:00 2001 From: cte Date: Wed, 27 Aug 2025 00:16:47 -0700 Subject: [PATCH 1/4] Update @roo-code/cloud to enable roomote control for cloud agents --- .gitignore | 3 ++ pnpm-lock.yaml | 20 +++++-- src/extension.ts | 60 ++++++++++++--------- src/package.json | 3 +- webview-ui/src/components/chat/ChatView.tsx | 2 - 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 65c201c3c25..e044fc32a7b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ logs .qodo/ .vercel .roo/mcp.json + +# Qdrant +qdrant_storage/ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 905845e552e..191d8100443 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -584,8 +584,8 @@ importers: specifier: ^1.14.0 version: 1.14.0(typescript@5.8.3) '@roo-code/cloud': - specifier: ^0.22.0 - version: 0.22.0 + specifier: ^0.24.0 + version: 0.24.0 '@roo-code/ipc': specifier: workspace:^ version: link:../packages/ipc @@ -661,6 +661,9 @@ importers: isbinaryfile: specifier: ^5.0.2 version: 5.0.4 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 lodash.debounce: specifier: ^4.0.8 version: 4.0.8 @@ -3343,8 +3346,8 @@ packages: cpu: [x64] os: [win32] - '@roo-code/cloud@0.22.0': - resolution: {integrity: sha512-s1d4wcDYeDzcwr+YypMWDlNKL4f2osOZ3NoIlD36LCfFeMs+hnluZPS1oXX3WHtmPDC76vSzPMfwW2Ef41hEoA==} + '@roo-code/cloud@0.24.0': + resolution: {integrity: sha512-0aG1rWFQ18jCC1ZuDlBYoB+di640p7uK1pv2zNRwOJIClWRtkP84GARYPotRgtCGfiyuI4sQ0jQRdi8Hh1ClRQ==} '@roo-code/types@1.61.0': resolution: {integrity: sha512-YJdFc6aYfaZ8EN08KbWaKLehRr1dcN3G3CzDjpppb08iehSEUZMycax/ryP5/G4vl34HTdtzyHNMboDen5ElUg==} @@ -7001,6 +7004,10 @@ packages: jws@4.0.0: resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + katex@0.16.22: resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} hasBin: true @@ -12725,10 +12732,11 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.40.2': optional: true - '@roo-code/cloud@0.22.0': + '@roo-code/cloud@0.24.0': dependencies: '@roo-code/types': 1.61.0 ioredis: 5.6.1 + jwt-decode: 4.0.0 p-wait-for: 5.0.2 socket.io-client: 4.8.1 zod: 3.25.76 @@ -17002,6 +17010,8 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 + jwt-decode@4.0.0: {} + katex@0.16.22: dependencies: commander: 8.3.0 diff --git a/src/extension.ts b/src/extension.ts index 6cb6ea4b073..63f2ecb147a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -94,13 +94,16 @@ export async function activate(context: vscode.ExtensionContext) { const contextProxy = await ContextProxy.getInstance(context) - // Initialize code index managers for all workspace folders + // Initialize code index managers for all workspace folders. const codeIndexManagers: CodeIndexManager[] = [] + if (vscode.workspace.workspaceFolders) { for (const folder of vscode.workspace.workspaceFolders) { const manager = CodeIndexManager.getInstance(context, folder.uri.fsPath) + if (manager) { codeIndexManagers.push(manager) + try { await manager.initialize(contextProxy) } catch (error) { @@ -108,13 +111,43 @@ export async function activate(context: vscode.ExtensionContext) { `[CodeIndexManager] Error during background CodeIndexManager configuration/indexing for ${folder.uri.fsPath}: ${error.message || error}`, ) } + context.subscriptions.push(manager) } } } + const postStateListener = () => ClineProvider.getVisibleInstance()?.postStateToWebview() + // Initialize Roo Code Cloud service. - const cloudService = await CloudService.createInstance(context, cloudLogger) + const cloudService = await CloudService.createInstance(context, cloudLogger, { + "auth-state-changed": postStateListener, + "settings-updated": postStateListener, + "user-info": async ({ userInfo }) => { + postStateListener() + + if (!CloudService.instance.cloudAPI) { + cloudLogger("[CloudService] CloudAPI is not initialized") + return + } + + try { + const config = await CloudService.instance.cloudAPI.bridgeConfig() + cloudLogger(`[CloudService] bridgeConfig -> ${JSON.stringify(config)}`) + + ExtensionBridgeService.handleRemoteControlState( + userInfo, + contextProxy.getValue("remoteControlEnabled"), + { ...config, provider, sessionId: vscode.env.sessionId }, + (message: string) => outputChannel.appendLine(message), + ) + } catch (error) { + cloudLogger( + `[CloudService] Failed to fetch bridgeConfig: ${error instanceof Error ? error.message : String(error)}`, + ) + } + }, + }) try { if (cloudService.telemetryClient) { @@ -126,29 +159,6 @@ export async function activate(context: vscode.ExtensionContext) { ) } - const postStateListener = () => ClineProvider.getVisibleInstance()?.postStateToWebview() - - cloudService.on("auth-state-changed", postStateListener) - cloudService.on("settings-updated", postStateListener) - - cloudService.on("user-info", async ({ userInfo }) => { - postStateListener() - - const bridgeConfig = await cloudService.cloudAPI?.bridgeConfig().catch(() => undefined) - - if (!bridgeConfig) { - outputChannel.appendLine("[CloudService] Failed to get bridge config") - return - } - - ExtensionBridgeService.handleRemoteControlState( - userInfo, - contextProxy.getValue("remoteControlEnabled"), - { ...bridgeConfig, provider, sessionId: vscode.env.sessionId }, - (message: string) => outputChannel.appendLine(message), - ) - }) - // Add to subscriptions for proper cleanup on deactivate. context.subscriptions.push(cloudService) diff --git a/src/package.json b/src/package.json index 1f515496845..64e097aed0e 100644 --- a/src/package.json +++ b/src/package.json @@ -429,7 +429,7 @@ "@mistralai/mistralai": "^1.9.18", "@modelcontextprotocol/sdk": "^1.9.0", "@qdrant/js-client-rest": "^1.14.0", - "@roo-code/cloud": "^0.22.0", + "@roo-code/cloud": "^0.24.0", "@roo-code/ipc": "workspace:^", "@roo-code/telemetry": "workspace:^", "@roo-code/types": "workspace:^", @@ -455,6 +455,7 @@ "i18next": "^25.0.0", "ignore": "^7.0.3", "isbinaryfile": "^5.0.2", + "jwt-decode": "^4.0.0", "lodash.debounce": "^4.0.8", "mammoth": "^1.9.1", "monaco-vscode-textmate-theme-converter": "^0.1.7", diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 8a93b8becc7..7cca453580b 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1787,8 +1787,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction Date: Wed, 27 Aug 2025 00:29:13 -0700 Subject: [PATCH 2/4] PR feedback --- src/extension.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index 63f2ecb147a..c6e41783102 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -117,6 +117,9 @@ export async function activate(context: vscode.ExtensionContext) { } } + // Initialize the provider *before* the Roo Code Cloud service. + const provider = new ClineProvider(context, outputChannel, "sidebar", contextProxy, mdmService) + const postStateListener = () => ClineProvider.getVisibleInstance()?.postStateToWebview() // Initialize Roo Code Cloud service. @@ -162,7 +165,7 @@ export async function activate(context: vscode.ExtensionContext) { // Add to subscriptions for proper cleanup on deactivate. context.subscriptions.push(cloudService) - const provider = new ClineProvider(context, outputChannel, "sidebar", contextProxy, mdmService) + // Finish initializing the provider. TelemetryService.instance.setProvider(provider) context.subscriptions.push( From 30500cb107026faf626b5a720ac14f6b2cecf928 Mon Sep 17 00:00:00 2001 From: cte Date: Wed, 27 Aug 2025 00:39:13 -0700 Subject: [PATCH 3/4] PR feedback --- src/extension.ts | 86 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index c6e41783102..ff7779959f8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -12,7 +12,7 @@ try { console.warn("Failed to load environment variables:", e) } -import { CloudService, ExtensionBridgeService } from "@roo-code/cloud" +import { CloudService, ExtensionBridgeService, type CloudUserInfo } from "@roo-code/cloud" import { TelemetryService, PostHogTelemetryClient } from "@roo-code/telemetry" import "./utils/path" // Necessary to have access to String.prototype.toPosix. @@ -51,6 +51,11 @@ import { initializeI18n } from "./i18n" let outputChannel: vscode.OutputChannel let extensionContext: vscode.ExtensionContext +let cloudService: CloudService | undefined + +let authStateChangedHandler: (() => void) | undefined +let settingsUpdatedHandler: (() => void) | undefined +let userInfoHandler: ((data: { userInfo: CloudUserInfo }) => Promise) | undefined // This method is called when your extension is activated. // Your extension is activated the very first time the command is executed. @@ -120,36 +125,39 @@ export async function activate(context: vscode.ExtensionContext) { // Initialize the provider *before* the Roo Code Cloud service. const provider = new ClineProvider(context, outputChannel, "sidebar", contextProxy, mdmService) + // Initialize Roo Code Cloud service. const postStateListener = () => ClineProvider.getVisibleInstance()?.postStateToWebview() + authStateChangedHandler = postStateListener + settingsUpdatedHandler = postStateListener - // Initialize Roo Code Cloud service. - const cloudService = await CloudService.createInstance(context, cloudLogger, { - "auth-state-changed": postStateListener, - "settings-updated": postStateListener, - "user-info": async ({ userInfo }) => { - postStateListener() - - if (!CloudService.instance.cloudAPI) { - cloudLogger("[CloudService] CloudAPI is not initialized") - return - } + userInfoHandler = async ({ userInfo }: { userInfo: any }) => { + postStateListener() - try { - const config = await CloudService.instance.cloudAPI.bridgeConfig() - cloudLogger(`[CloudService] bridgeConfig -> ${JSON.stringify(config)}`) - - ExtensionBridgeService.handleRemoteControlState( - userInfo, - contextProxy.getValue("remoteControlEnabled"), - { ...config, provider, sessionId: vscode.env.sessionId }, - (message: string) => outputChannel.appendLine(message), - ) - } catch (error) { - cloudLogger( - `[CloudService] Failed to fetch bridgeConfig: ${error instanceof Error ? error.message : String(error)}`, - ) - } - }, + if (!CloudService.instance.cloudAPI) { + cloudLogger("[CloudService] CloudAPI is not initialized") + return + } + + try { + const config = await CloudService.instance.cloudAPI.bridgeConfig() + + ExtensionBridgeService.handleRemoteControlState( + userInfo, + contextProxy.getValue("remoteControlEnabled"), + { ...config, provider, sessionId: vscode.env.sessionId }, + (message: string) => outputChannel.appendLine(message), + ) + } catch (error) { + cloudLogger( + `[CloudService] Failed to fetch bridgeConfig: ${error instanceof Error ? error.message : String(error)}`, + ) + } + } + + cloudService = await CloudService.createInstance(context, cloudLogger, { + "auth-state-changed": authStateChangedHandler, + "settings-updated": settingsUpdatedHandler, + "user-info": userInfoHandler, }) try { @@ -293,6 +301,28 @@ export async function activate(context: vscode.ExtensionContext) { export async function deactivate() { outputChannel.appendLine(`${Package.name} extension deactivated`) + if (cloudService && CloudService.hasInstance()) { + try { + if (authStateChangedHandler) { + CloudService.instance.off("auth-state-changed", authStateChangedHandler) + } + + if (settingsUpdatedHandler) { + CloudService.instance.off("settings-updated", settingsUpdatedHandler) + } + + if (userInfoHandler) { + CloudService.instance.off("user-info", userInfoHandler as any) + } + + outputChannel.appendLine("CloudService event handlers cleaned up") + } catch (error) { + outputChannel.appendLine( + `Failed to clean up CloudService event handlers: ${error instanceof Error ? error.message : String(error)}`, + ) + } + } + const bridgeService = ExtensionBridgeService.getInstance() if (bridgeService) { From 5ebd7a6ebeaef2874892bf0779d338ea89e21e51 Mon Sep 17 00:00:00 2001 From: Chris Estreich Date: Wed, 27 Aug 2025 00:43:39 -0700 Subject: [PATCH 4/4] Update src/extension.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --- src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index ff7779959f8..bd0863bd35f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -130,7 +130,7 @@ export async function activate(context: vscode.ExtensionContext) { authStateChangedHandler = postStateListener settingsUpdatedHandler = postStateListener - userInfoHandler = async ({ userInfo }: { userInfo: any }) => { + userInfoHandler = async ({ userInfo }: { userInfo: CloudUserInfo }) => { postStateListener() if (!CloudService.instance.cloudAPI) {