This commit is contained in:
tintinweb
2026-03-22 20:22:18 +01:00
parent 312f8323f2
commit e1726d7c2a
5 changed files with 483 additions and 708 deletions
+3
View File
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.4.0] - 2026-03-22
### Added
- **RPC-based subagent spawning** — `TaskExecute` now communicates with `@tintinweb/pi-subagents` via a standardized RPC envelope (`rpcCall` helper) with protocol version negotiation and timeout handling.
- **RPC-based subagent stopping** — `stopSubagent` sends stop requests via `subagents:rpc:stop` event bus RPC.
@@ -109,6 +111,7 @@ Initial release — Claude Code-style task tracking and coordination for pi.
- **Background process tracker** — output buffering (stdout + stderr), waiter notification, graceful stop with timeout escalation (SIGTERM → 5s → SIGKILL).
- **78 unit tests** — task store CRUD, dependencies, warnings, file persistence; widget rendering, icons, spinners, token/duration formatting; process tracker lifecycle.
[0.4.0]: https://github.com/tintinweb/pi-tasks/releases/tag/v0.4.0
[0.3.3]: https://github.com/tintinweb/pi-tasks/releases/tag/v0.3.3
[0.3.2]: https://github.com/tintinweb/pi-tasks/releases/tag/v0.3.2
[0.3.1]: https://github.com/tintinweb/pi-tasks/releases/tag/v0.3.1
+8 -5
View File
@@ -96,7 +96,7 @@ Blocked by: #1
Blocks: #3
```
Shows owner (if set) and ALL dependency edges (including completed blockers) — raw data.
Shows owner (if set) and open (non-completed) dependency edges. Non-empty metadata is displayed as JSON.
### `TaskUpdate`
@@ -132,17 +132,19 @@ Retrieve output from a background task process.
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `task_id` | string | — | Task ID (required) |
| `task_id` | string | — | Task ID or agent ID (required) |
| `block` | boolean | `true` | Wait for completion |
| `timeout` | number | `30000` | Max wait time in ms (max 600000) |
Both task IDs and agent IDs (including partial prefixes) are accepted — agent IDs are resolved via the internal `agentTaskMap`.
### `TaskStop`
Stop a running background task process. Sends SIGTERM, waits 5 seconds, then SIGKILL.
Stop a running background task process. Sends SIGTERM, waits 5 seconds, then SIGKILL. For subagent tasks, sends a stop RPC.
| Parameter | Type | Description |
|-----------|------|-------------|
| `task_id` | string | Task ID to stop |
| `task_id` | string | Task ID or agent ID to stop |
### `TaskExecute`
@@ -199,6 +201,7 @@ Settings (`taskScope`, `autoCascade`) are saved to `<cwd>/.pi/tasks-config.json`
| `PI_TASKS` | `/abs/path/tasks.json` | Explicit absolute file path |
| `PI_TASKS` | `./tasks.json` | Relative path resolved from cwd |
| *(unset)* | | Uses `taskScope` setting (default: `session`) |
| `PI_TASKS_DEBUG` | `1` | Trace RPC communication (request/reply/timeout) and spawn errors to stderr |
Named and explicit paths use a file-locked store with stale-lock detection — safe for multiple pi sessions coordinating on the same task list.
@@ -304,7 +307,7 @@ src/
```bash
npm install
npm run typecheck # TypeScript validation
npm test # Run unit tests (116 tests)
npm test # Run unit tests (125 tests)
```
## License
+466 -697
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@tintinweb/pi-tasks",
"version": "0.3.3",
"version": "0.4.0",
"description": "A pi extension that brings Claude Code-style task tracking and coordination to pi.",
"author": "tintinweb",
"license": "MIT",
@@ -22,8 +22,8 @@
"coordination"
],
"dependencies": {
"@mariozechner/pi-coding-agent": "^0.57.1",
"@mariozechner/pi-tui": "^0.57.1",
"@mariozechner/pi-coding-agent": "^0.61.1",
"@mariozechner/pi-tui": "^0.61.1",
"@sinclair/typebox": "latest"
},
"scripts": {
+3 -3
View File
@@ -164,7 +164,7 @@ describe("TaskExecute", () => {
});
const result = await freshMock.executeTool("TaskExecute", { task_ids: ["1"] });
expect(result.content[0].text).toContain("requires the @tintinweb/pi-subagents extension");
expect(result.content[0].text).toContain("Subagent execution is currently unavailable");
});
it("rejects non-existent tasks", async () => {
@@ -505,7 +505,7 @@ describe("Standalone operation (no subagents extension)", () => {
agentType: "general-purpose",
});
const result = await mock.executeTool("TaskExecute", { task_ids: ["1"] });
expect(result.content[0].text).toContain("requires the @tintinweb/pi-subagents extension");
expect(result.content[0].text).toContain("Subagent execution is currently unavailable");
});
it("subagents lifecycle events are silently ignored without mapped agents", () => {
@@ -607,7 +607,7 @@ describe("RPC protocol correctness", () => {
agentType: "general-purpose",
});
let result = await mock.executeTool("TaskExecute", { task_ids: ["1"] });
expect(result.content[0].text).toContain("requires the @tintinweb/pi-subagents extension");
expect(result.content[0].text).toContain("Subagent execution is currently unavailable");
// Reset task status
await mock.executeTool("TaskUpdate", { taskId: "1", status: "pending" });