mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Focus the extension when receiving bridge commands (#7633)
This commit is contained in:
parent
d7896924a9
commit
280b75d2eb
14 changed files with 206 additions and 114 deletions
|
|
@ -13,6 +13,10 @@ export const Uri = {
|
|||
parse: vi.fn((uri: string) => ({ toString: () => uri })),
|
||||
}
|
||||
|
||||
export const commands = {
|
||||
executeCommand: vi.fn().mockResolvedValue(undefined),
|
||||
}
|
||||
|
||||
export interface ExtensionContext {
|
||||
secrets: {
|
||||
get: (key: string) => Promise<string | undefined>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
import type { Socket } from "socket.io-client"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
import type { StaticAppProperties, GitProperties } from "@roo-code/types"
|
||||
|
||||
export interface BaseChannelOptions {
|
||||
instanceId: string
|
||||
appProperties: StaticAppProperties
|
||||
gitProperties?: GitProperties
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract base class for communication channels in the bridge system.
|
||||
|
|
@ -11,9 +20,13 @@ import type { Socket } from "socket.io-client"
|
|||
export abstract class BaseChannel<TCommand = unknown, TEventName extends string = string, TEventData = unknown> {
|
||||
protected socket: Socket | null = null
|
||||
protected readonly instanceId: string
|
||||
protected readonly appProperties: StaticAppProperties
|
||||
protected readonly gitProperties?: GitProperties
|
||||
|
||||
constructor(instanceId: string) {
|
||||
this.instanceId = instanceId
|
||||
constructor(options: BaseChannelOptions) {
|
||||
this.instanceId = options.instanceId
|
||||
this.appProperties = options.appProperties
|
||||
this.gitProperties = options.gitProperties
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,9 +94,26 @@ export abstract class BaseChannel<TCommand = unknown, TEventName extends string
|
|||
}
|
||||
|
||||
/**
|
||||
* Handle incoming commands - must be implemented by subclasses.
|
||||
* Handle incoming commands - template method that ensures common functionality
|
||||
* is executed before subclass-specific logic.
|
||||
*
|
||||
* This method should be called by subclasses to handle commands.
|
||||
* It will execute common functionality and then delegate to the abstract
|
||||
* handleCommandImplementation method.
|
||||
*/
|
||||
public abstract handleCommand(command: TCommand): Promise<void>
|
||||
public async handleCommand(command: TCommand): Promise<void> {
|
||||
// Common functionality: focus the sidebar.
|
||||
await vscode.commands.executeCommand(`${this.appProperties.appName}.SidebarProvider.focus`)
|
||||
|
||||
// Delegate to subclass-specific implementation.
|
||||
await this.handleCommandImplementation(command)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle command-specific logic - must be implemented by subclasses.
|
||||
* This method is called after common functionality has been executed.
|
||||
*/
|
||||
protected abstract handleCommandImplementation(command: TCommand): Promise<void>
|
||||
|
||||
/**
|
||||
* Handle connection-specific logic.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import crypto from "crypto"
|
||||
import os from "os"
|
||||
|
||||
import {
|
||||
type TaskProviderLike,
|
||||
|
|
@ -6,6 +7,8 @@ import {
|
|||
type CloudUserInfo,
|
||||
type ExtensionBridgeCommand,
|
||||
type TaskBridgeCommand,
|
||||
type StaticAppProperties,
|
||||
type GitProperties,
|
||||
ConnectionState,
|
||||
ExtensionSocketEvents,
|
||||
TaskSocketEvents,
|
||||
|
|
@ -39,6 +42,8 @@ export class BridgeOrchestrator {
|
|||
private readonly token: string
|
||||
private readonly provider: TaskProviderLike
|
||||
private readonly instanceId: string
|
||||
private readonly appProperties: StaticAppProperties
|
||||
private readonly gitProperties?: GitProperties
|
||||
|
||||
// Components
|
||||
private socketTransport: SocketTransport
|
||||
|
|
@ -61,69 +66,75 @@ export class BridgeOrchestrator {
|
|||
public static async connectOrDisconnect(
|
||||
userInfo: CloudUserInfo | null,
|
||||
remoteControlEnabled: boolean | undefined,
|
||||
options?: BridgeOrchestratorOptions,
|
||||
options: BridgeOrchestratorOptions,
|
||||
): Promise<void> {
|
||||
const isEnabled = BridgeOrchestrator.isEnabled(userInfo, remoteControlEnabled)
|
||||
if (BridgeOrchestrator.isEnabled(userInfo, remoteControlEnabled)) {
|
||||
await BridgeOrchestrator.connect(options)
|
||||
} else {
|
||||
await BridgeOrchestrator.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
public static async connect(options: BridgeOrchestratorOptions) {
|
||||
const instance = BridgeOrchestrator.instance
|
||||
|
||||
if (isEnabled) {
|
||||
if (!instance) {
|
||||
if (!options) {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Cannot connect: options are required for connection`,
|
||||
)
|
||||
return
|
||||
}
|
||||
try {
|
||||
console.log(`[BridgeOrchestrator#connectOrDisconnect] Connecting...`)
|
||||
BridgeOrchestrator.instance = new BridgeOrchestrator(options)
|
||||
await BridgeOrchestrator.instance.connect()
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] connect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
instance.connectionState === ConnectionState.FAILED ||
|
||||
instance.connectionState === ConnectionState.DISCONNECTED
|
||||
) {
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Re-connecting... (state: ${instance.connectionState})`,
|
||||
)
|
||||
if (!instance) {
|
||||
try {
|
||||
console.log(`[BridgeOrchestrator#connectOrDisconnect] Connecting...`)
|
||||
// Populate telemetry properties before registering the instance.
|
||||
await options.provider.getTelemetryProperties()
|
||||
|
||||
instance.reconnect().catch((error) => {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] reconnect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Already connected or connecting (state: ${instance.connectionState})`,
|
||||
)
|
||||
}
|
||||
BridgeOrchestrator.instance = new BridgeOrchestrator(options)
|
||||
await BridgeOrchestrator.instance.connect()
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] connect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (instance) {
|
||||
try {
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Disconnecting... (state: ${instance.connectionState})`,
|
||||
)
|
||||
if (
|
||||
instance.connectionState === ConnectionState.FAILED ||
|
||||
instance.connectionState === ConnectionState.DISCONNECTED
|
||||
) {
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Re-connecting... (state: ${instance.connectionState})`,
|
||||
)
|
||||
|
||||
await instance.disconnect()
|
||||
} catch (error) {
|
||||
instance.reconnect().catch((error) => {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] disconnect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
`[BridgeOrchestrator#connectOrDisconnect] reconnect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
} finally {
|
||||
BridgeOrchestrator.instance = null
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log(`[BridgeOrchestrator#connectOrDisconnect] Already disconnected`)
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Already connected or connecting (state: ${instance.connectionState})`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async disconnect() {
|
||||
const instance = BridgeOrchestrator.instance
|
||||
|
||||
if (instance) {
|
||||
try {
|
||||
console.log(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] Disconnecting... (state: ${instance.connectionState})`,
|
||||
)
|
||||
|
||||
await instance.disconnect()
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[BridgeOrchestrator#connectOrDisconnect] disconnect() failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
} finally {
|
||||
BridgeOrchestrator.instance = null
|
||||
}
|
||||
} else {
|
||||
console.log(`[BridgeOrchestrator#connectOrDisconnect] Already disconnected`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @TODO: What if subtasks also get spawned? We'd probably want deferred
|
||||
* subscriptions for those too.
|
||||
|
|
@ -146,6 +157,8 @@ export class BridgeOrchestrator {
|
|||
this.token = options.token
|
||||
this.provider = options.provider
|
||||
this.instanceId = options.sessionId || crypto.randomUUID()
|
||||
this.appProperties = { ...options.provider.appProperties, hostname: os.hostname() }
|
||||
this.gitProperties = options.provider.gitProperties
|
||||
|
||||
this.socketTransport = new SocketTransport({
|
||||
url: this.socketBridgeUrl,
|
||||
|
|
@ -166,8 +179,19 @@ export class BridgeOrchestrator {
|
|||
onReconnect: () => this.handleReconnect(),
|
||||
})
|
||||
|
||||
this.extensionChannel = new ExtensionChannel(this.instanceId, this.userId, this.provider)
|
||||
this.taskChannel = new TaskChannel(this.instanceId)
|
||||
this.extensionChannel = new ExtensionChannel({
|
||||
instanceId: this.instanceId,
|
||||
appProperties: this.appProperties,
|
||||
gitProperties: this.gitProperties,
|
||||
userId: this.userId,
|
||||
provider: this.provider,
|
||||
})
|
||||
|
||||
this.taskChannel = new TaskChannel({
|
||||
instanceId: this.instanceId,
|
||||
appProperties: this.appProperties,
|
||||
gitProperties: this.gitProperties,
|
||||
})
|
||||
}
|
||||
|
||||
private setupSocketListeners() {
|
||||
|
|
@ -288,9 +312,6 @@ export class BridgeOrchestrator {
|
|||
}
|
||||
|
||||
private async connect(): Promise<void> {
|
||||
// Populate the app and git properties before registering the instance.
|
||||
await this.provider.getTelemetryProperties()
|
||||
|
||||
await this.socketTransport.connect()
|
||||
this.setupSocketListeners()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@ import {
|
|||
HEARTBEAT_INTERVAL_MS,
|
||||
} from "@roo-code/types"
|
||||
|
||||
import { BaseChannel } from "./BaseChannel.js"
|
||||
import { type BaseChannelOptions, BaseChannel } from "./BaseChannel.js"
|
||||
|
||||
interface ExtensionChannelOptions extends BaseChannelOptions {
|
||||
userId: string
|
||||
provider: TaskProviderLike
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the extension-level communication channel.
|
||||
|
|
@ -31,33 +36,36 @@ export class ExtensionChannel extends BaseChannel<
|
|||
private heartbeatInterval: NodeJS.Timeout | null = null
|
||||
private eventListeners: Map<RooCodeEventName, (...args: unknown[]) => void> = new Map()
|
||||
|
||||
constructor(instanceId: string, userId: string, provider: TaskProviderLike) {
|
||||
super(instanceId)
|
||||
this.userId = userId
|
||||
this.provider = provider
|
||||
constructor(options: ExtensionChannelOptions) {
|
||||
super({
|
||||
instanceId: options.instanceId,
|
||||
appProperties: options.appProperties,
|
||||
gitProperties: options.gitProperties,
|
||||
})
|
||||
|
||||
this.userId = options.userId
|
||||
this.provider = options.provider
|
||||
|
||||
this.extensionInstance = {
|
||||
instanceId: this.instanceId,
|
||||
userId: this.userId,
|
||||
workspacePath: this.provider.cwd,
|
||||
appProperties: this.provider.appProperties,
|
||||
gitProperties: this.provider.gitProperties,
|
||||
appProperties: this.appProperties,
|
||||
gitProperties: this.gitProperties,
|
||||
lastHeartbeat: Date.now(),
|
||||
task: {
|
||||
taskId: "",
|
||||
taskStatus: TaskStatus.None,
|
||||
},
|
||||
task: { taskId: "", taskStatus: TaskStatus.None },
|
||||
taskHistory: [],
|
||||
}
|
||||
|
||||
this.setupListeners()
|
||||
}
|
||||
|
||||
public async handleCommand(command: ExtensionBridgeCommand): Promise<void> {
|
||||
protected async handleCommandImplementation(command: ExtensionBridgeCommand): Promise<void> {
|
||||
if (command.instanceId !== this.instanceId) {
|
||||
console.log(`[ExtensionChannel] command -> instance id mismatch | ${this.instanceId}`, {
|
||||
messageInstanceId: command.instanceId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -217,8 +225,6 @@ export class ExtensionChannel extends BaseChannel<
|
|||
|
||||
this.extensionInstance = {
|
||||
...this.extensionInstance,
|
||||
appProperties: this.extensionInstance.appProperties ?? this.provider.appProperties,
|
||||
gitProperties: this.extensionInstance.gitProperties ?? this.provider.gitProperties,
|
||||
lastHeartbeat: Date.now(),
|
||||
task: task
|
||||
? {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
TaskSocketEvents,
|
||||
} from "@roo-code/types"
|
||||
|
||||
import { BaseChannel } from "./BaseChannel.js"
|
||||
import { type BaseChannelOptions, BaseChannel } from "./BaseChannel.js"
|
||||
|
||||
type TaskEventListener = {
|
||||
[K in keyof TaskEvents]: (...args: TaskEvents[K]) => void | Promise<void>
|
||||
|
|
@ -26,6 +26,9 @@ type TaskEventMapping = {
|
|||
createPayload: (task: TaskLike, ...args: any[]) => any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
interface TaskChannelOptions extends BaseChannelOptions {}
|
||||
|
||||
/**
|
||||
* Manages task-level communication channels.
|
||||
* Handles task subscriptions, messaging, and task-specific commands.
|
||||
|
|
@ -69,11 +72,11 @@ export class TaskChannel extends BaseChannel<
|
|||
},
|
||||
] as const
|
||||
|
||||
constructor(instanceId: string) {
|
||||
super(instanceId)
|
||||
constructor(options: TaskChannelOptions) {
|
||||
super(options)
|
||||
}
|
||||
|
||||
public async handleCommand(command: TaskBridgeCommand): Promise<void> {
|
||||
protected async handleCommandImplementation(command: TaskBridgeCommand): Promise<void> {
|
||||
const task = this.subscribedTasks.get(command.taskId)
|
||||
|
||||
if (!task) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import type { Socket } from "socket.io-client"
|
|||
import {
|
||||
type TaskProviderLike,
|
||||
type TaskProviderEvents,
|
||||
type StaticAppProperties,
|
||||
RooCodeEventName,
|
||||
ExtensionBridgeEventName,
|
||||
ExtensionSocketEvents,
|
||||
|
|
@ -19,6 +20,15 @@ describe("ExtensionChannel", () => {
|
|||
const instanceId = "test-instance-123"
|
||||
const userId = "test-user-456"
|
||||
|
||||
const appProperties: StaticAppProperties = {
|
||||
appName: "roo-code",
|
||||
appVersion: "1.0.0",
|
||||
vscodeVersion: "1.0.0",
|
||||
platform: "darwin",
|
||||
editorName: "Roo Code",
|
||||
hostname: "test-host",
|
||||
}
|
||||
|
||||
// Track registered event listeners
|
||||
const eventListeners = new Map<keyof TaskProviderEvents, Set<(...args: unknown[]) => unknown>>()
|
||||
|
||||
|
|
@ -80,7 +90,12 @@ describe("ExtensionChannel", () => {
|
|||
} as unknown as TaskProviderLike
|
||||
|
||||
// Create extension channel instance
|
||||
extensionChannel = new ExtensionChannel(instanceId, userId, mockProvider)
|
||||
extensionChannel = new ExtensionChannel({
|
||||
instanceId,
|
||||
appProperties,
|
||||
userId,
|
||||
provider: mockProvider,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -155,7 +170,12 @@ describe("ExtensionChannel", () => {
|
|||
|
||||
it("should not have duplicate listeners after multiple channel creations", () => {
|
||||
// Create a second channel with the same provider
|
||||
const secondChannel = new ExtensionChannel("instance-2", userId, mockProvider)
|
||||
const secondChannel = new ExtensionChannel({
|
||||
instanceId: "instance-2",
|
||||
appProperties,
|
||||
userId,
|
||||
provider: mockProvider,
|
||||
})
|
||||
|
||||
// Each event should have exactly 2 listeners (one from each channel)
|
||||
eventListeners.forEach((listeners) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import type { Socket } from "socket.io-client"
|
|||
import {
|
||||
type TaskLike,
|
||||
type ClineMessage,
|
||||
type StaticAppProperties,
|
||||
RooCodeEventName,
|
||||
TaskBridgeEventName,
|
||||
TaskBridgeCommandName,
|
||||
|
|
@ -22,6 +23,15 @@ describe("TaskChannel", () => {
|
|||
const instanceId = "test-instance-123"
|
||||
const taskId = "test-task-456"
|
||||
|
||||
const appProperties: StaticAppProperties = {
|
||||
appName: "roo-code",
|
||||
appVersion: "1.0.0",
|
||||
vscodeVersion: "1.0.0",
|
||||
platform: "darwin",
|
||||
editorName: "Roo Code",
|
||||
hostname: "test-host",
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
// Create mock socket
|
||||
mockSocket = {
|
||||
|
|
@ -75,7 +85,10 @@ describe("TaskChannel", () => {
|
|||
}
|
||||
|
||||
// Create task channel instance
|
||||
taskChannel = new TaskChannel(instanceId)
|
||||
taskChannel = new TaskChannel({
|
||||
instanceId,
|
||||
appProperties,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -320,7 +333,7 @@ describe("TaskChannel", () => {
|
|||
channel.subscribedTasks.set(taskId, mockTask)
|
||||
})
|
||||
|
||||
it("should handle Message command", () => {
|
||||
it("should handle Message command", async () => {
|
||||
const command = {
|
||||
type: TaskBridgeCommandName.Message,
|
||||
taskId,
|
||||
|
|
@ -331,7 +344,7 @@ describe("TaskChannel", () => {
|
|||
},
|
||||
}
|
||||
|
||||
taskChannel.handleCommand(command)
|
||||
await taskChannel.handleCommand(command)
|
||||
|
||||
expect(mockTask.submitUserMessage).toHaveBeenCalledWith(
|
||||
command.payload.text,
|
||||
|
|
@ -341,7 +354,7 @@ describe("TaskChannel", () => {
|
|||
)
|
||||
})
|
||||
|
||||
it("should handle ApproveAsk command", () => {
|
||||
it("should handle ApproveAsk command", async () => {
|
||||
const command = {
|
||||
type: TaskBridgeCommandName.ApproveAsk,
|
||||
taskId,
|
||||
|
|
@ -351,12 +364,12 @@ describe("TaskChannel", () => {
|
|||
},
|
||||
}
|
||||
|
||||
taskChannel.handleCommand(command)
|
||||
await taskChannel.handleCommand(command)
|
||||
|
||||
expect(mockTask.approveAsk).toHaveBeenCalledWith(command.payload)
|
||||
})
|
||||
|
||||
it("should handle DenyAsk command", () => {
|
||||
it("should handle DenyAsk command", async () => {
|
||||
const command = {
|
||||
type: TaskBridgeCommandName.DenyAsk,
|
||||
taskId,
|
||||
|
|
@ -366,12 +379,12 @@ describe("TaskChannel", () => {
|
|||
},
|
||||
}
|
||||
|
||||
taskChannel.handleCommand(command)
|
||||
await taskChannel.handleCommand(command)
|
||||
|
||||
expect(mockTask.denyAsk).toHaveBeenCalledWith(command.payload)
|
||||
})
|
||||
|
||||
it("should log error for unknown task", () => {
|
||||
it("should log error for unknown task", async () => {
|
||||
const errorSpy = vi.spyOn(console, "error")
|
||||
|
||||
const command = {
|
||||
|
|
@ -383,7 +396,7 @@ describe("TaskChannel", () => {
|
|||
},
|
||||
}
|
||||
|
||||
taskChannel.handleCommand(command)
|
||||
await taskChannel.handleCommand(command)
|
||||
|
||||
expect(errorSpy).toHaveBeenCalledWith(`[TaskChannel] Unable to find task unknown-task`)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@roo-code/types",
|
||||
"version": "1.69.0",
|
||||
"version": "1.71.0",
|
||||
"description": "TypeScript type definitions for Roo Code.",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ export const staticAppPropertiesSchema = z.object({
|
|||
vscodeVersion: z.string(),
|
||||
platform: z.string(),
|
||||
editorName: z.string(),
|
||||
hostname: z.string().optional(),
|
||||
})
|
||||
|
||||
export type StaticAppProperties = z.infer<typeof staticAppPropertiesSchema>
|
||||
|
|
|
|||
|
|
@ -2095,7 +2095,6 @@ export class ClineProvider
|
|||
|
||||
public async remoteControlEnabled(enabled: boolean) {
|
||||
const userInfo = CloudService.instance.getUserInfo()
|
||||
|
||||
const config = await CloudService.instance.cloudAPI?.bridgeConfig().catch(() => undefined)
|
||||
|
||||
if (!config) {
|
||||
|
|
|
|||
|
|
@ -956,13 +956,21 @@ export const webviewMessageHandler = async (
|
|||
break
|
||||
case "remoteControlEnabled":
|
||||
try {
|
||||
await CloudService.instance.updateUserSettings({
|
||||
extensionBridgeEnabled: message.bool ?? false,
|
||||
})
|
||||
await CloudService.instance.updateUserSettings({ extensionBridgeEnabled: message.bool ?? false })
|
||||
} catch (error) {
|
||||
provider.log(`Failed to update cloud settings for remote control: ${error}`)
|
||||
provider.log(
|
||||
`CloudService#updateUserSettings failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
await provider.remoteControlEnabled(message.bool ?? false)
|
||||
|
||||
try {
|
||||
await provider.remoteControlEnabled(message.bool ?? false)
|
||||
} catch (error) {
|
||||
provider.log(
|
||||
`ClineProvider#remoteControlEnabled failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
|
||||
await provider.postStateToWebview()
|
||||
break
|
||||
case "refreshAllMcpServers": {
|
||||
|
|
|
|||
|
|
@ -131,20 +131,13 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
authStateChangedHandler = async (data: { state: AuthState; previousState: AuthState }) => {
|
||||
postStateListener()
|
||||
|
||||
// Check if user has logged out
|
||||
if (data.state === "logged-out") {
|
||||
try {
|
||||
// Disconnect the bridge when user logs out
|
||||
// When userInfo is null and remoteControlEnabled is false, BridgeOrchestrator
|
||||
// will disconnect. The options parameter is not needed for disconnection.
|
||||
await BridgeOrchestrator.connectOrDisconnect(null, false)
|
||||
|
||||
await BridgeOrchestrator.disconnect()
|
||||
cloudLogger("[CloudService] BridgeOrchestrator disconnected on logout")
|
||||
} catch (error) {
|
||||
cloudLogger(
|
||||
`[CloudService] Failed to disconnect BridgeOrchestrator on logout: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
`[CloudService] Failed to disconnect BridgeOrchestrator on logout: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -152,6 +145,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
settingsUpdatedHandler = async () => {
|
||||
const userInfo = CloudService.instance.getUserInfo()
|
||||
|
||||
if (userInfo && CloudService.instance.cloudAPI) {
|
||||
try {
|
||||
const config = await CloudService.instance.cloudAPI.bridgeConfig()
|
||||
|
|
@ -163,8 +157,6 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
? true
|
||||
: (CloudService.instance.getUserSettings()?.settings?.extensionBridgeEnabled ?? false)
|
||||
|
||||
cloudLogger(`[CloudService] Settings updated - remoteControlEnabled = ${remoteControlEnabled}`)
|
||||
|
||||
await BridgeOrchestrator.connectOrDisconnect(userInfo, remoteControlEnabled, {
|
||||
...config,
|
||||
provider,
|
||||
|
|
@ -172,7 +164,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
})
|
||||
} catch (error) {
|
||||
cloudLogger(
|
||||
`[CloudService] Failed to update BridgeOrchestrator on settings change: ${error instanceof Error ? error.message : String(error)}`,
|
||||
`[CloudService] BridgeOrchestrator#connectOrDisconnect failed on settings change: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -194,8 +186,6 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
const isCloudAgent =
|
||||
typeof process.env.ROO_CODE_CLOUD_TOKEN === "string" && process.env.ROO_CODE_CLOUD_TOKEN.length > 0
|
||||
|
||||
cloudLogger(`[CloudService] isCloudAgent = ${isCloudAgent}, socketBridgeUrl = ${config.socketBridgeUrl}`)
|
||||
|
||||
const remoteControlEnabled = isCloudAgent
|
||||
? true
|
||||
: (CloudService.instance.getUserSettings()?.settings?.extensionBridgeEnabled ?? false)
|
||||
|
|
@ -207,7 +197,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
})
|
||||
} catch (error) {
|
||||
cloudLogger(
|
||||
`[CloudService] Failed to fetch bridgeConfig: ${error instanceof Error ? error.message : String(error)}`,
|
||||
`[CloudService] BridgeOrchestrator#connectOrDisconnect failed on user change: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { EventEmitter } from "events"
|
||||
import * as vscode from "vscode"
|
||||
import fs from "fs/promises"
|
||||
import * as path from "path"
|
||||
import * as os from "os"
|
||||
|
||||
import * as vscode from "vscode"
|
||||
|
||||
import {
|
||||
type RooCodeAPI,
|
||||
type RooCodeSettings,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
/**
|
||||
* Package
|
||||
*/
|
||||
|
||||
import { publisher, name, version } from "../package.json"
|
||||
|
||||
// These ENV variables can be defined by ESBuild when building the extension
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue