mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
* feat: add DeleteQueuedMessage IPC command for queue removal * Delete .changeset/delete-queued-message-ipc.md * fix: add try/catch to DeleteQueuedMessage IPC handler and early return in deleteQueuedMessage --------- Co-authored-by: Roo Code <roomote@roocode.com> Co-authored-by: Hannes Rudolph <hrudolph@gmail.com>
147 lines
3.1 KiB
TypeScript
147 lines
3.1 KiB
TypeScript
import EventEmitter from "node:events"
|
|
import * as crypto from "node:crypto"
|
|
|
|
import ipc from "node-ipc"
|
|
|
|
import {
|
|
type TaskCommand,
|
|
type IpcClientEvents,
|
|
type IpcMessage,
|
|
IpcOrigin,
|
|
IpcMessageType,
|
|
TaskCommandName,
|
|
ipcMessageSchema,
|
|
} from "@roo-code/types"
|
|
|
|
export class IpcClient extends EventEmitter<IpcClientEvents> {
|
|
private readonly _socketPath: string
|
|
private readonly _id: string
|
|
private readonly _log: (...args: unknown[]) => void
|
|
private _isConnected = false
|
|
private _clientId?: string
|
|
|
|
constructor(socketPath: string, log = console.log) {
|
|
super()
|
|
|
|
this._socketPath = socketPath
|
|
this._id = `roo-code-evals-${crypto.randomBytes(6).toString("hex")}`
|
|
this._log = log
|
|
|
|
ipc.config.silent = true
|
|
|
|
ipc.connectTo(this._id, this.socketPath, () => {
|
|
ipc.of[this._id]?.on("connect", () => this.onConnect())
|
|
ipc.of[this._id]?.on("disconnect", () => this.onDisconnect())
|
|
ipc.of[this._id]?.on("message", (data) => this.onMessage(data))
|
|
})
|
|
}
|
|
|
|
private onConnect() {
|
|
if (this._isConnected) {
|
|
return
|
|
}
|
|
|
|
this.log("[client#onConnect]")
|
|
this._isConnected = true
|
|
this.emit(IpcMessageType.Connect)
|
|
}
|
|
|
|
private onDisconnect() {
|
|
if (!this._isConnected) {
|
|
return
|
|
}
|
|
|
|
this.log("[client#onDisconnect]")
|
|
this._isConnected = false
|
|
this.emit(IpcMessageType.Disconnect)
|
|
}
|
|
|
|
private onMessage(data: unknown) {
|
|
if (typeof data !== "object") {
|
|
this.log(`[client#onMessage] invalid data -> ${JSON.stringify(data)}`)
|
|
return
|
|
}
|
|
|
|
const result = ipcMessageSchema.safeParse(data)
|
|
|
|
if (!result.success) {
|
|
this.log(
|
|
`[client#onMessage] invalid payload -> ${JSON.stringify(result.error.issues)} -> ${JSON.stringify(data)}`,
|
|
)
|
|
return
|
|
}
|
|
|
|
const payload = result.data
|
|
|
|
if (payload.origin === IpcOrigin.Server) {
|
|
switch (payload.type) {
|
|
case IpcMessageType.Ack:
|
|
this._clientId = payload.data.clientId
|
|
this.emit(IpcMessageType.Ack, payload.data)
|
|
break
|
|
case IpcMessageType.TaskEvent:
|
|
this.emit(IpcMessageType.TaskEvent, payload.data)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
private log(...args: unknown[]) {
|
|
this._log(...args)
|
|
}
|
|
|
|
public sendCommand(command: TaskCommand) {
|
|
const message: IpcMessage = {
|
|
type: IpcMessageType.TaskCommand,
|
|
origin: IpcOrigin.Client,
|
|
clientId: this._clientId!,
|
|
data: command,
|
|
}
|
|
|
|
this.sendMessage(message)
|
|
}
|
|
|
|
public sendTaskMessage(text?: string, images?: string[]) {
|
|
this.sendCommand({
|
|
commandName: TaskCommandName.SendMessage,
|
|
data: { text, images },
|
|
})
|
|
}
|
|
|
|
public deleteQueuedMessage(messageId: string) {
|
|
this.sendCommand({
|
|
commandName: TaskCommandName.DeleteQueuedMessage,
|
|
data: messageId,
|
|
})
|
|
}
|
|
|
|
public sendMessage(message: IpcMessage) {
|
|
ipc.of[this._id]?.emit("message", message)
|
|
}
|
|
|
|
public disconnect() {
|
|
try {
|
|
ipc.disconnect(this._id)
|
|
} catch (error) {
|
|
this.log(
|
|
`[client#disconnect] error disconnecting -> ${error instanceof Error ? error.message : String(error)}`,
|
|
)
|
|
}
|
|
}
|
|
|
|
public get socketPath() {
|
|
return this._socketPath
|
|
}
|
|
|
|
public get clientId() {
|
|
return this._clientId
|
|
}
|
|
|
|
public get isConnected() {
|
|
return this._isConnected
|
|
}
|
|
|
|
public get isReady() {
|
|
return this._isConnected && this._clientId !== undefined
|
|
}
|
|
}
|