Skip to content

Commit be7f2bf

Browse files
committed
Add an API for resuming tasks by ID
1 parent 44086e4 commit be7f2bf

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

packages/ipc/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# IPC (Inter-Process Communication)
2+
3+
This package provides IPC functionality for Roo Code, allowing external applications to communicate with the extension through a socket-based interface.
4+
5+
## Available Commands
6+
7+
The IPC interface supports the following task commands:
8+
9+
### StartNewTask
10+
11+
Starts a new task with optional configuration and initial message.
12+
13+
**Parameters:**
14+
15+
- `configuration`: RooCode settings object
16+
- `text`: Initial task message (string)
17+
- `images`: Array of image data URIs (optional)
18+
- `newTab`: Whether to open in a new tab (boolean, optional)
19+
20+
### CancelTask
21+
22+
Cancels a running task.
23+
24+
**Parameters:**
25+
26+
- `data`: Task ID to cancel (string)
27+
28+
### CloseTask
29+
30+
Closes a task and performs cleanup.
31+
32+
**Parameters:**
33+
34+
- `data`: Task ID to close (string)
35+
36+
### ResumeTask
37+
38+
Resumes a task from history.
39+
40+
**Parameters:**
41+
42+
- `data`: Task ID to resume (string)
43+
44+
## Usage Example
45+
46+
```typescript
47+
import { IpcClient } from "@roo-code/ipc"
48+
49+
const client = new IpcClient("/path/to/socket")
50+
51+
// Resume a task
52+
client.sendCommand({
53+
commandName: "ResumeTask",
54+
data: "task-123",
55+
})
56+
57+
// Start a new task
58+
client.sendCommand({
59+
commandName: "StartNewTask",
60+
data: {
61+
configuration: {
62+
/* RooCode settings */
63+
},
64+
text: "Hello, world!",
65+
images: [],
66+
newTab: false,
67+
},
68+
})
69+
```
70+
71+
## Events
72+
73+
The IPC interface also emits task events that clients can listen to:
74+
75+
- `TaskStarted`: When a task begins
76+
- `TaskCompleted`: When a task finishes
77+
- `TaskAborted`: When a task is cancelled
78+
- `Message`: When a task sends a message
79+
80+
## Socket Path
81+
82+
The socket path is typically located in the system's temporary directory and follows the pattern:
83+
84+
- Unix/Linux/macOS: `/tmp/roo-code-{id}.sock`
85+
- Windows: `\\.\pipe\roo-code-{id}`
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { describe, it, expect } from "vitest"
2+
import { TaskCommandName, taskCommandSchema } from "../ipc.js"
3+
4+
describe("IPC Types", () => {
5+
describe("TaskCommandName", () => {
6+
it("should include ResumeTask command", () => {
7+
expect(TaskCommandName.ResumeTask).toBe("ResumeTask")
8+
})
9+
10+
it("should have all expected task commands", () => {
11+
const expectedCommands = ["StartNewTask", "CancelTask", "CloseTask", "ResumeTask"]
12+
const actualCommands = Object.values(TaskCommandName)
13+
14+
expectedCommands.forEach((command) => {
15+
expect(actualCommands).toContain(command)
16+
})
17+
})
18+
})
19+
20+
describe("taskCommandSchema", () => {
21+
it("should validate ResumeTask command with taskId", () => {
22+
const resumeTaskCommand = {
23+
commandName: TaskCommandName.ResumeTask,
24+
data: "task-123",
25+
}
26+
27+
const result = taskCommandSchema.safeParse(resumeTaskCommand)
28+
expect(result.success).toBe(true)
29+
30+
if (result.success) {
31+
expect(result.data.commandName).toBe("ResumeTask")
32+
expect(result.data.data).toBe("task-123")
33+
}
34+
})
35+
36+
it("should reject ResumeTask command with invalid data", () => {
37+
const invalidCommand = {
38+
commandName: TaskCommandName.ResumeTask,
39+
data: 123, // Should be string
40+
}
41+
42+
const result = taskCommandSchema.safeParse(invalidCommand)
43+
expect(result.success).toBe(false)
44+
})
45+
46+
it("should reject ResumeTask command without data", () => {
47+
const invalidCommand = {
48+
commandName: TaskCommandName.ResumeTask,
49+
// Missing data field
50+
}
51+
52+
const result = taskCommandSchema.safeParse(invalidCommand)
53+
expect(result.success).toBe(false)
54+
})
55+
})
56+
})

packages/types/src/ipc.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export enum TaskCommandName {
4444
StartNewTask = "StartNewTask",
4545
CancelTask = "CancelTask",
4646
CloseTask = "CloseTask",
47+
ResumeTask = "ResumeTask",
4748
}
4849

4950
/**
@@ -68,6 +69,10 @@ export const taskCommandSchema = z.discriminatedUnion("commandName", [
6869
commandName: z.literal(TaskCommandName.CloseTask),
6970
data: z.string(),
7071
}),
72+
z.object({
73+
commandName: z.literal(TaskCommandName.ResumeTask),
74+
data: z.string(),
75+
}),
7176
])
7277

7378
export type TaskCommand = z.infer<typeof taskCommandSchema>

src/extension/api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
7878
await vscode.commands.executeCommand("workbench.action.files.saveFiles")
7979
await vscode.commands.executeCommand("workbench.action.closeWindow")
8080
break
81+
case TaskCommandName.ResumeTask:
82+
this.log(`[API] ResumeTask -> ${data}`)
83+
await this.resumeTask(data)
84+
break
8185
}
8286
})
8387
}

0 commit comments

Comments
 (0)