mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
New Cursor instance opens correctly, TODO: get acces to the Roo code extension in the cursor instance and send the prompt
This commit is contained in:
parent
efd86a22cf
commit
ce64c7f33e
5 changed files with 192 additions and 23 deletions
|
|
@ -2481,12 +2481,14 @@ export class Cline {
|
|||
case "open_cursor": {
|
||||
const mode: string | undefined = block.params.mode
|
||||
const prompt: string | undefined = block.params.prompt
|
||||
const projectDir: string | undefined = block.params.projectDir
|
||||
try {
|
||||
if (block.partial) {
|
||||
const partialMessage = JSON.stringify({
|
||||
tool: "openCursor",
|
||||
mode: removeClosingTag("mode", mode),
|
||||
prompt: removeClosingTag("prompt", prompt),
|
||||
projectDir: removeClosingTag("projectDir", projectDir),
|
||||
})
|
||||
await this.ask("tool", partialMessage, block.partial).catch(() => {})
|
||||
break
|
||||
|
|
@ -2501,11 +2503,18 @@ export class Cline {
|
|||
pushToolResult(await this.sayAndCreateMissingParamError("open_cursor", "prompt"))
|
||||
break
|
||||
}
|
||||
if (!projectDir) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(
|
||||
await this.sayAndCreateMissingParamError("open_cursor", "projectDir"),
|
||||
)
|
||||
break
|
||||
}
|
||||
this.consecutiveMistakeCount = 0
|
||||
|
||||
const provider = this.providerRef.deref()
|
||||
if (provider) {
|
||||
await provider.openCursorInstance(prompt, mode)
|
||||
await provider.openCursorInstance(prompt, mode, projectDir)
|
||||
pushToolResult(
|
||||
`Successfully opened new Cursor instance in ${mode} mode with prompt: ${prompt}`,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export const toolParamNames = [
|
|||
"message",
|
||||
"prompt",
|
||||
"monitor",
|
||||
"projectDir",
|
||||
] as const
|
||||
|
||||
export type ToolParamName = (typeof toolParamNames)[number]
|
||||
|
|
|
|||
|
|
@ -9,17 +9,20 @@ Parameters:
|
|||
- prompt: (required) The initial prompt or instructions to send to the new Cursor instance.
|
||||
- mode: (optional) The mode to start the new instance in (e.g., "code", "ask", "architect"). If not provided, will use the current mode.
|
||||
- monitor: (optional) Whether to monitor the task's progress. Defaults to true.
|
||||
- projectDir: (optional) The directory to open Cursor in. If not provided, will use the current project directory.
|
||||
|
||||
Usage:
|
||||
<open_cursor>
|
||||
<prompt>Your initial prompt here</prompt>
|
||||
<mode>Mode to start in (optional)</mode>
|
||||
<projectDir>Project directory to open Cursor in (optional)</projectDir>
|
||||
</open_cursor>
|
||||
|
||||
Example:
|
||||
<open_cursor>
|
||||
<prompt>Create a new React component</prompt>
|
||||
<mode>code</mode>
|
||||
<projectDir>/Users/rooCode/Projects/Roo-Code</projectDir>
|
||||
</open_cursor>
|
||||
`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Anthropic } from "@anthropic-ai/sdk"
|
||||
import delay from "delay"
|
||||
import axios from "axios"
|
||||
import fs from "fs/promises"
|
||||
import fs, { cp } from "fs/promises"
|
||||
import os from "os"
|
||||
import pWaitFor from "p-wait-for"
|
||||
import * as path from "path"
|
||||
|
|
@ -44,7 +44,8 @@ import { EXPERIMENT_IDS, experiments as Experiments, experimentDefault, Experime
|
|||
import { CustomSupportPrompts, supportPrompt } from "../../shared/support-prompt"
|
||||
|
||||
import { ACTION_NAMES } from "../CodeActionProvider"
|
||||
|
||||
import { spawn } from "child_process"
|
||||
import { openCursorInstance, startRooCodeTask } from "./openCursorInstance"
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
|
||||
|
|
@ -1413,26 +1414,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
await this.postStateToWebview()
|
||||
}
|
||||
|
||||
public async openCursorInstance(prompt: string, mode: string) {
|
||||
// Construct command to open new Cursor instance
|
||||
const cursorCommand = {
|
||||
command: "workbench.action.newWindow",
|
||||
args: [
|
||||
{
|
||||
mode,
|
||||
prompt,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// Execute command to open new window
|
||||
const result = await vscode.commands.executeCommand(cursorCommand.command, ...cursorCommand.args)
|
||||
console.log("result", result)
|
||||
const windows = vscode.window.state.active
|
||||
console.log("windows", windows)
|
||||
await vscode.commands.executeCommand("workbench.view.extension.roo-cline-ActivityBar")
|
||||
await this.postMessageToWebview({ type: "action", action: "openCursorInstance" })
|
||||
await this.postStateToWebview()
|
||||
public async openCursorInstance(prompt: string, mode: string, projectDir: string) {
|
||||
const workingDir =
|
||||
projectDir || vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0) || ""
|
||||
const instanceId = await openCursorInstance(prompt, mode, workingDir)
|
||||
await startRooCodeTask(instanceId, prompt, mode)
|
||||
this.outputChannel.appendLine(`Cursor instance opened in ${workingDir}`)
|
||||
}
|
||||
|
||||
private async updateApiConfiguration(apiConfiguration: ApiConfiguration) {
|
||||
|
|
|
|||
169
src/core/webview/openCursorInstance.ts
Normal file
169
src/core/webview/openCursorInstance.ts
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
import { spawn, ChildProcess } from "child_process"
|
||||
import * as path from "path"
|
||||
import * as vscode from "vscode"
|
||||
import * as fs from "fs/promises"
|
||||
|
||||
interface CursorInstance {
|
||||
process: ChildProcess
|
||||
projectDir: string
|
||||
prompt: string
|
||||
mode?: string
|
||||
}
|
||||
|
||||
// Track active cursor instances
|
||||
const activeCursorInstances: Map<string, CursorInstance> = new Map()
|
||||
|
||||
/**
|
||||
* Gets the path to the Cursor application
|
||||
* @returns Promise<{command: string, args: string[]}> Command and args to launch Cursor
|
||||
*/
|
||||
async function getCursorLaunchCommand(projectDir: string): Promise<{ command: string; args: string[] }> {
|
||||
// Use code command with Cursor profile
|
||||
return {
|
||||
command: "cursor",
|
||||
args: ["--new-window", projectDir],
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new instance of Cursor at a specific project directory
|
||||
* @param prompt The initial prompt to send to Roo Code
|
||||
* @param mode Optional mode to start in (code, ask, architect)
|
||||
* @param projectDir The directory to open Cursor in
|
||||
* @returns Promise<string> Instance ID if successful
|
||||
*/
|
||||
export async function openCursorInstance(prompt: string, mode: string = "code", projectDir: string): Promise<string> {
|
||||
try {
|
||||
// Ensure project directory exists
|
||||
const normalizedPath = path.normalize(projectDir)
|
||||
await fs.access(normalizedPath)
|
||||
|
||||
// Generate unique instance ID
|
||||
const instanceId = `cursor-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
||||
|
||||
// Get platform-specific launch command
|
||||
const { command, args } = await getCursorLaunchCommand(normalizedPath)
|
||||
|
||||
// Spawn process with inherited stdio
|
||||
const cursorProcess = spawn(command, args, {
|
||||
detached: false,
|
||||
stdio: "inherit",
|
||||
})
|
||||
|
||||
// Handle process error
|
||||
cursorProcess.on("error", (error) => {
|
||||
console.error(`Error launching Cursor instance ${instanceId}:`, error)
|
||||
activeCursorInstances.delete(instanceId)
|
||||
throw error
|
||||
})
|
||||
|
||||
// Store instance information
|
||||
const instance: CursorInstance = {
|
||||
process: cursorProcess,
|
||||
projectDir: normalizedPath,
|
||||
prompt,
|
||||
mode,
|
||||
}
|
||||
|
||||
activeCursorInstances.set(instanceId, instance)
|
||||
|
||||
console.log(instance)
|
||||
cursorProcess.stdin?.write(prompt)
|
||||
|
||||
// Show information message
|
||||
vscode.window.showInformationMessage(`New Cursor instance opened at ${normalizedPath}`)
|
||||
|
||||
return instanceId
|
||||
} catch (error) {
|
||||
console.error("Failed to open Cursor instance:", error)
|
||||
if (error instanceof Error) {
|
||||
vscode.window.showErrorMessage(`Failed to open Cursor: ${error.message}`)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active cursor instances
|
||||
* @returns Map of active cursor instances
|
||||
*/
|
||||
export function getActiveCursorInstances(): Map<string, CursorInstance> {
|
||||
return new Map(activeCursorInstances)
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a specific cursor instance
|
||||
* @param instanceId The ID of the instance to close
|
||||
* @returns boolean indicating if the instance was successfully closed
|
||||
*/
|
||||
export function closeCursorInstance(instanceId: string): boolean {
|
||||
const instance = activeCursorInstances.get(instanceId)
|
||||
if (!instance) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
instance.process.kill()
|
||||
activeCursorInstances.delete(instanceId)
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error(`Error closing Cursor instance ${instanceId}:`, error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all active cursor instances
|
||||
*/
|
||||
export function closeAllCursorInstances(): void {
|
||||
for (const [instanceId] of activeCursorInstances) {
|
||||
closeCursorInstance(instanceId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to the Roo Code extension in a specific Cursor instance
|
||||
* @param instanceId The ID of the Cursor instance to send the command to
|
||||
* @param command The Roo Code command to execute (e.g., 'startNewTask')
|
||||
* @param args Optional arguments for the command
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
export async function sendRooCodeCommand(instanceId: string, command: string, args?: any): Promise<void> {
|
||||
const instance = activeCursorInstances.get(instanceId)
|
||||
if (!instance) {
|
||||
throw new Error(`No active Cursor instance found with ID: ${instanceId}`)
|
||||
}
|
||||
|
||||
try {
|
||||
// Wait for Cursor to be ready
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000))
|
||||
|
||||
// Focus the window first
|
||||
await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(instance.projectDir), true)
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
|
||||
// Send the command
|
||||
await vscode.commands.executeCommand(command, args)
|
||||
|
||||
// Log command for debugging
|
||||
console.log(`Executed command in Cursor instance ${instanceId}:`, command, args)
|
||||
} catch (error) {
|
||||
console.error(`Failed to send command to Cursor instance ${instanceId}:`, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new Roo Code task in a specific Cursor instance
|
||||
* @param instanceId The ID of the Cursor instance
|
||||
* @param prompt The prompt for the new task
|
||||
* @param mode Optional mode to start in (code, ask, architect)
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
export async function startRooCodeTask(instanceId: string, prompt: string, mode: string = "code"): Promise<void> {
|
||||
await sendRooCodeCommand(instanceId, "roo-cline.startTask", {
|
||||
prompt,
|
||||
mode,
|
||||
projectDir: activeCursorInstances.get(instanceId)?.projectDir,
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue