Switch to the UnifiedBridgeService (#6976)

This commit is contained in:
Chris Estreich 2025-08-12 00:39:11 -10:00 committed by GitHub
parent 5f3c67fa91
commit 12d1959bbd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 101 additions and 70 deletions

10
pnpm-lock.yaml generated
View file

@ -563,8 +563,8 @@ importers:
specifier: ^1.14.0
version: 1.14.0(typescript@5.8.3)
'@roo-code/cloud':
specifier: ^0.10.0
version: 0.10.0
specifier: ^0.11.0
version: 0.11.0
'@roo-code/ipc':
specifier: workspace:^
version: link:../packages/ipc
@ -3065,8 +3065,8 @@ packages:
cpu: [x64]
os: [win32]
'@roo-code/cloud@0.10.0':
resolution: {integrity: sha512-nP5XD9JVaFFmz+XN9za9XMombCjw7LrS4pFEbBU52raZbobvUAExKuMJw8U+vyXFW+mcVAexM0i39XB6SJvhWA==}
'@roo-code/cloud@0.11.0':
resolution: {integrity: sha512-ZT3gBRNHI0HGmn5bMxdyhMxJVrp/7l7jcx/lDRl+xjeCP3KmJshzFKlfjdSGDtOoztnNj65hSbs/WiTS2wUodQ==}
'@roo-code/types@1.45.0':
resolution: {integrity: sha512-+rFJ9HcukDl59X9pI6lgZDtJHtKqHg6BIdS4LG759X+5MV7wvlNb4S+bQ3qKqIlBsQhH17bzIJCfsWZwjwxecw==}
@ -12234,7 +12234,7 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.40.2':
optional: true
'@roo-code/cloud@0.10.0':
'@roo-code/cloud@0.11.0':
dependencies:
'@roo-code/types': 1.45.0
ioredis: 5.6.1

View file

@ -58,6 +58,54 @@ if (!unlink && watch) {
}
}
function generateNpmPackageJson(sourcePath, npmPath) {
const npmDir = path.join(sourcePath, npmPath)
const npmPackagePath = path.join(npmDir, "package.json")
const npmMetadataPath = path.join(npmDir, "package.metadata.json")
const monorepoPackagePath = path.join(sourcePath, "package.json")
if (fs.existsSync(npmPackagePath)) {
console.log(` ✓ npm/package.json already exists`)
return
}
if (!fs.existsSync(npmMetadataPath)) {
console.log(` ⚠ No package.metadata.json found, skipping npm package.json generation`)
return
}
try {
console.log(` 📦 Generating npm/package.json...`)
const monorepoPackage = JSON.parse(fs.readFileSync(monorepoPackagePath, "utf8"))
const npmMetadata = JSON.parse(fs.readFileSync(npmMetadataPath, "utf8"))
const npmPackage = {
...npmMetadata,
type: "module",
dependencies: monorepoPackage.dependencies || {},
main: "./dist/index.cjs",
module: "./dist/index.js",
types: "./dist/index.d.ts",
exports: {
".": {
types: "./dist/index.d.ts",
import: "./dist/index.js",
require: {
types: "./dist/index.d.cts",
default: "./dist/index.cjs",
},
},
},
files: ["dist"],
}
fs.writeFileSync(npmPackagePath, JSON.stringify(npmPackage, null, 2) + "\n")
console.log(` ✓ Generated npm/package.json for ${npmPackage.name}`)
} catch (error) {
console.error(` ✗ Failed to generate npm/package.json: ${error.message}`)
}
}
function linkPackage(pkg) {
const sourcePath = path.resolve(__dirname, "..", pkg.sourcePath)
const targetPath = path.resolve(__dirname, "..", pkg.targetPath)
@ -78,6 +126,11 @@ function linkPackage(pkg) {
}
}
// If npmPath is specified, check if we need to generate package.json.
if (pkg.npmPath) {
generateNpmPackageJson(sourcePath, pkg.npmPath)
}
// Create symlink.
fs.rmSync(targetPath, { recursive: true, force: true })
fs.mkdirSync(path.dirname(targetPath), { recursive: true })

View file

@ -33,7 +33,7 @@ import {
isBlockingAsk,
} from "@roo-code/types"
import { TelemetryService } from "@roo-code/telemetry"
import { CloudService, TaskBridgeService } from "@roo-code/cloud"
import { CloudService, UnifiedBridgeService } from "@roo-code/cloud"
// api
import { ApiHandler, ApiHandlerCreateMessageMetadata, buildApiHandler } from "../../api"
@ -241,7 +241,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Task Bridge
enableTaskBridge: boolean
taskBridgeService: TaskBridgeService | null = null
bridgeService: UnifiedBridgeService | null = null
// Streaming
isWaitingForFirstChunk = false
@ -980,19 +980,17 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
// Start / Abort / Resume
private async startTask(task?: string, images?: string[]): Promise<void> {
if (this.enableTaskBridge && CloudService.hasInstance()) {
if (!this.taskBridgeService) {
const bridgeConfig = await CloudService.instance.cloudAPI?.bridgeConfig().catch(() => undefined)
if (this.enableTaskBridge) {
try {
this.bridgeService = this.bridgeService || UnifiedBridgeService.getInstance()
if (bridgeConfig) {
this.taskBridgeService = await TaskBridgeService.createInstance({
...bridgeConfig,
})
if (this.bridgeService) {
await this.bridgeService.subscribeToTask(this)
}
}
if (this.taskBridgeService) {
await this.taskBridgeService.subscribeToTask(this)
} catch (error) {
console.error(
`[Task#startTask] subscribeToTask failed - ${error instanceof Error ? error.message : String(error)}`,
)
}
}
@ -1047,19 +1045,17 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
private async resumeTaskFromHistory() {
if (this.enableTaskBridge && CloudService.hasInstance()) {
if (!this.taskBridgeService) {
const bridgeConfig = await CloudService.instance.cloudAPI?.bridgeConfig().catch(() => undefined)
if (this.enableTaskBridge) {
try {
this.bridgeService = this.bridgeService || UnifiedBridgeService.getInstance()
if (bridgeConfig) {
this.taskBridgeService = await TaskBridgeService.createInstance({
...bridgeConfig,
})
if (this.bridgeService) {
await this.bridgeService.subscribeToTask(this)
}
}
if (this.taskBridgeService) {
await this.taskBridgeService.subscribeToTask(this)
} catch (error) {
console.error(
`[Task#resumeTaskFromHistory] subscribeToTask failed - ${error instanceof Error ? error.message : String(error)}`,
)
}
}
@ -1309,11 +1305,11 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
}
// Unsubscribe from TaskBridge service.
if (this.taskBridgeService) {
this.taskBridgeService
if (this.bridgeService) {
this.bridgeService
.unsubscribeFromTask(this.taskId)
.catch((error) => console.error("Error unsubscribing from task bridge:", error))
this.taskBridgeService = null
this.bridgeService = null
}
// Release any terminals associated with this task.

View file

@ -2134,25 +2134,21 @@ export class ClineProvider
/**
* Handle remote control enabled/disabled state changes
* Manages ExtensionBridgeService and TaskBridgeService lifecycle
* Manages UnifiedBridgeService lifecycle
*/
public async handleRemoteControlToggle(enabled: boolean) {
const {
CloudService: CloudServiceImport,
ExtensionBridgeService,
TaskBridgeService,
} = await import("@roo-code/cloud")
const { CloudService: CloudServiceImport, UnifiedBridgeService } = await import("@roo-code/cloud")
const userInfo = CloudServiceImport.instance.getUserInfo()
const bridgeConfig = await CloudServiceImport.instance.cloudAPI?.bridgeConfig().catch(() => undefined)
if (!bridgeConfig) {
this.log("[CloudService] Failed to get bridge config")
this.log("[ClineProvider#handleRemoteControlToggle] Failed to get bridge config")
return
}
ExtensionBridgeService.handleRemoteControlState(
await UnifiedBridgeService.handleRemoteControlState(
userInfo,
enabled,
{ ...bridgeConfig, provider: this },
@ -2160,49 +2156,36 @@ export class ClineProvider
)
if (isRemoteControlEnabled(userInfo, enabled)) {
// Set up TaskBridgeService for the currently active task if one exists.
const currentTask = this.getCurrentCline()
if (currentTask && !currentTask.taskBridgeService && CloudService.hasInstance()) {
if (currentTask && !currentTask.bridgeService) {
try {
if (!currentTask.taskBridgeService) {
const bridgeConfig = await CloudService.instance.cloudAPI?.bridgeConfig().catch(() => undefined)
currentTask.bridgeService = UnifiedBridgeService.getInstance()
if (bridgeConfig) {
currentTask.taskBridgeService = await TaskBridgeService.createInstance({
...bridgeConfig,
})
}
if (currentTask.bridgeService) {
await currentTask.bridgeService.subscribeToTask(currentTask)
}
if (currentTask.taskBridgeService) {
await currentTask.taskBridgeService.subscribeToTask(currentTask)
}
this.log(`[TaskBridgeService] Subscribed current task ${currentTask.taskId} to TaskBridge`)
} catch (error) {
const message = `[TaskBridgeService#subscribeToTask] ${error instanceof Error ? error.message : String(error)}`
const message = `[ClineProvider#handleRemoteControlToggle] subscribeToTask failed - ${error instanceof Error ? error.message : String(error)}`
this.log(message)
console.error(message)
}
}
} else {
// Disconnect TaskBridgeService for all tasks in the stack.
for (const task of this.clineStack) {
if (task.taskBridgeService) {
if (task.bridgeService) {
try {
await task.taskBridgeService.unsubscribeFromTask(task.taskId)
task.taskBridgeService = null
this.log(`[TaskBridgeService] Unsubscribed task ${task.taskId} from TaskBridge`)
await task.bridgeService.unsubscribeFromTask(task.taskId)
task.bridgeService = null
} catch (error) {
const message = `[TaskBridgeService#unsubscribeFromTask] for task ${task.taskId}: ${error instanceof Error ? error.message : String(error)}`
const message = `[ClineProvider#handleRemoteControlToggle] unsubscribeFromTask failed - ${error instanceof Error ? error.message : String(error)}`
this.log(message)
console.error(message)
}
}
}
TaskBridgeService.resetInstance()
UnifiedBridgeService.resetInstance()
}
}

View file

@ -12,7 +12,7 @@ try {
console.warn("Failed to load environment variables:", e)
}
import { CloudService, ExtensionBridgeService } from "@roo-code/cloud"
import { CloudService, UnifiedBridgeService } from "@roo-code/cloud"
import { TelemetryService, PostHogTelemetryClient } from "@roo-code/telemetry"
import "./utils/path" // Necessary to have access to String.prototype.toPosix.
@ -141,7 +141,7 @@ export async function activate(context: vscode.ExtensionContext) {
return
}
ExtensionBridgeService.handleRemoteControlState(
UnifiedBridgeService.handleRemoteControlState(
userInfo,
contextProxy.getValue("remoteControlEnabled"),
{ ...bridgeConfig, provider },
@ -280,11 +280,10 @@ export async function activate(context: vscode.ExtensionContext) {
export async function deactivate() {
outputChannel.appendLine(`${Package.name} extension deactivated`)
// Cleanup Extension Bridge service.
const extensionBridgeService = ExtensionBridgeService.getInstance()
const bridgeService = UnifiedBridgeService.getInstance()
if (extensionBridgeService) {
await extensionBridgeService.disconnect()
if (bridgeService) {
await bridgeService.disconnect()
}
await McpServerManager.cleanup(extensionContext)

View file

@ -420,7 +420,7 @@
"@mistralai/mistralai": "^1.3.6",
"@modelcontextprotocol/sdk": "^1.9.0",
"@qdrant/js-client-rest": "^1.14.0",
"@roo-code/cloud": "^0.10.0",
"@roo-code/cloud": "^0.11.0",
"@roo-code/ipc": "workspace:^",
"@roo-code/telemetry": "workspace:^",
"@roo-code/types": "workspace:^",