Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions scripts/link-packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 })
Expand Down
50 changes: 23 additions & 27 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)}`,
)
}
}

Expand Down Expand Up @@ -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)}`,
)
}
}

Expand Down Expand Up @@ -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.
Expand Down
45 changes: 14 additions & 31 deletions src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2134,75 +2134,58 @@ 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 },
(message: string) => this.log(message),
)

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)

if (bridgeConfig) {
currentTask.taskBridgeService = await TaskBridgeService.createInstance({
...bridgeConfig,
})
}
}
currentTask.bridgeService = UnifiedBridgeService.getInstance()

if (currentTask.taskBridgeService) {
await currentTask.taskBridgeService.subscribeToTask(currentTask)
if (currentTask.bridgeService) {
await currentTask.bridgeService.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()
}
}

Expand Down
11 changes: 5 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -141,7 +141,7 @@ export async function activate(context: vscode.ExtensionContext) {
return
}

ExtensionBridgeService.handleRemoteControlState(
UnifiedBridgeService.handleRemoteControlState(
userInfo,
contextProxy.getValue("remoteControlEnabled"),
{ ...bridgeConfig, provider },
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:^",
Expand Down
Loading