mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
IPC commands
This commit is contained in:
parent
7fc42d70ea
commit
fdfec4617d
3 changed files with 77 additions and 3 deletions
|
|
@ -1,8 +1,10 @@
|
|||
import fs from "fs"
|
||||
import os from "os"
|
||||
import path from "path"
|
||||
import { fileURLToPath } from "url"
|
||||
|
||||
import { createElement } from "react"
|
||||
import pWaitFor from "p-wait-for"
|
||||
|
||||
import { setLogger } from "@roo-code/vscode-shim"
|
||||
|
||||
|
|
@ -64,7 +66,11 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
|
|||
const effectiveReasoningEffort =
|
||||
flagOptions.reasoningEffort || settings.reasoningEffort || DEFAULT_FLAGS.reasoningEffort
|
||||
const effectiveProvider = flagOptions.provider ?? settings.provider ?? (rooToken ? "roo" : "openrouter")
|
||||
const effectiveWorkspacePath = flagOptions.workspace ? path.resolve(flagOptions.workspace) : process.cwd()
|
||||
const effectiveWorkspacePath = flagOptions.workspace
|
||||
? path.resolve(flagOptions.workspace)
|
||||
: process.env.ROO_CODE_WORKSPACE_PATH
|
||||
? path.resolve(process.env.ROO_CODE_WORKSPACE_PATH)
|
||||
: process.cwd()
|
||||
const effectiveDangerouslySkipPermissions =
|
||||
flagOptions.yes || flagOptions.dangerouslySkipPermissions || settings.dangerouslySkipPermissions || false
|
||||
const effectiveExitOnComplete = flagOptions.print || flagOptions.oneshot || settings.oneshot || false
|
||||
|
|
@ -84,6 +90,25 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
|
|||
exitOnComplete: effectiveExitOnComplete,
|
||||
}
|
||||
|
||||
// IPC (headless) mode detection.
|
||||
// Activates when: --ipc flag is set, or ROO_CODE_IPC_SOCKET_PATH is set without a prompt.
|
||||
const isIpcMode = !!flagOptions.ipc || (!!process.env.ROO_CODE_IPC_SOCKET_PATH && !prompt && !flagOptions.print)
|
||||
|
||||
// Resolve the IPC socket path: --ipc <path> > ROO_CODE_IPC_SOCKET_PATH > auto-generated temp path.
|
||||
let ipcSocketPath: string | undefined
|
||||
if (isIpcMode) {
|
||||
ipcSocketPath =
|
||||
(typeof flagOptions.ipc === "string" ? flagOptions.ipc : undefined) ||
|
||||
process.env.ROO_CODE_IPC_SOCKET_PATH ||
|
||||
path.join(os.tmpdir(), `roo-ipc-${process.pid}.sock`)
|
||||
|
||||
// Set the env var so the extension picks it up during activation.
|
||||
process.env.ROO_CODE_IPC_SOCKET_PATH = ipcSocketPath
|
||||
|
||||
extensionHostOptions.disableOutput = true
|
||||
extensionHostOptions.exitOnComplete = false
|
||||
}
|
||||
|
||||
// Roo Code Cloud Authentication
|
||||
|
||||
if (isOnboardingEnabled) {
|
||||
|
|
@ -187,7 +212,7 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
|
|||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!isTuiEnabled) {
|
||||
if (!isTuiEnabled && !isIpcMode) {
|
||||
if (!prompt) {
|
||||
console.error("[CLI] Error: prompt is required in print mode")
|
||||
console.error("[CLI] Usage: roo <prompt> --print [options]")
|
||||
|
|
@ -202,7 +227,51 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
|
|||
|
||||
// Run!
|
||||
|
||||
if (isTuiEnabled) {
|
||||
if (isIpcMode) {
|
||||
const host = new ExtensionHost(extensionHostOptions)
|
||||
|
||||
async function shutdown(signal: string, exitCode: number): Promise<void> {
|
||||
console.error(`\n[IPC] Received ${signal}, shutting down...`)
|
||||
await host.dispose()
|
||||
|
||||
if (ipcSocketPath && fs.existsSync(ipcSocketPath)) {
|
||||
try {
|
||||
fs.unlinkSync(ipcSocketPath)
|
||||
} catch {
|
||||
// Socket may already be cleaned up.
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(exitCode)
|
||||
}
|
||||
|
||||
process.on("SIGINT", () => shutdown("SIGINT", 130))
|
||||
process.on("SIGTERM", () => shutdown("SIGTERM", 0))
|
||||
|
||||
try {
|
||||
await host.activate()
|
||||
|
||||
// Verify the IPC socket is ready. The extension creates the IPC server
|
||||
// internally during activation, but ipc.serve() is async so we poll
|
||||
// for the socket file.
|
||||
await pWaitFor(() => fs.existsSync(ipcSocketPath!), { interval: 100, timeout: 10_000 })
|
||||
|
||||
console.error(`[IPC] IPC server ready: ${ipcSocketPath}`)
|
||||
|
||||
// Stay alive indefinitely until SIGTERM/SIGINT.
|
||||
await new Promise<never>(() => {})
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error(`[IPC] Error: ${errorMessage}`)
|
||||
|
||||
if (error instanceof Error) {
|
||||
console.error(error.stack)
|
||||
}
|
||||
|
||||
await host.dispose()
|
||||
process.exit(1)
|
||||
}
|
||||
} else if (isTuiEnabled) {
|
||||
try {
|
||||
const { render } = await import("ink")
|
||||
const { App } = await import("../../ui/App.js")
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ program
|
|||
.option("--exit-on-error", "Exit on API request errors instead of retrying", false)
|
||||
.option("--ephemeral", "Run without persisting state (uses temporary storage)", false)
|
||||
.option("--oneshot", "Exit upon task completion", false)
|
||||
.option(
|
||||
"--ipc [socket-path]",
|
||||
"Run as a headless IPC server (optionally specify socket path, or set ROO_CODE_IPC_SOCKET_PATH)",
|
||||
)
|
||||
.option(
|
||||
"--output-format <format>",
|
||||
'Output format (only works with --print): "text" (default), "json" (single result), or "stream-json" (realtime streaming)',
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export type FlagOptions = {
|
|||
ephemeral: boolean
|
||||
oneshot: boolean
|
||||
outputFormat?: OutputFormat
|
||||
ipc?: boolean | string
|
||||
}
|
||||
|
||||
export enum OnboardingProviderChoice {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue