@xynogen/pix-todo 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/package.json +1 -1
- package/src/todo.ts +57 -4
package/README.md
CHANGED
|
@@ -6,6 +6,22 @@ Pi tool — durable execution checklist (`todo`).
|
|
|
6
6
|
|
|
7
7
|
Registers the `todo` tool, which gives the agent a persistent task checklist that survives context compaction and session restore. The checklist is seeded by the model via the `set` action and tracks items through four statuses: `pending` (○), `in_progress` (◐), `done` (●), and `blocked` (⊘). State is persisted via Pi's `appendEntry("todo-state")` so the agent can recover its position after long runs or compaction events. The agent calls `todo(action:"list")` to resume where it left off. Actions: `list`, `set`, `add`, `update`, `clear`.
|
|
8
8
|
|
|
9
|
+
## Auto-collapse
|
|
10
|
+
|
|
11
|
+
The checklist card auto-collapses after a configurable delay (default 10 seconds, previously hardcoded). The delay and the per-tool toggle are read from `~/.pi/agent/pix.json`:
|
|
12
|
+
|
|
13
|
+
```jsonc
|
|
14
|
+
{
|
|
15
|
+
"collapse": {
|
|
16
|
+
"enabled": true,
|
|
17
|
+
"delayMs": 10000,
|
|
18
|
+
"tools": { "todo": true }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Set `collapse.tools.todo: false` to keep the checklist always expanded. See `@xynogen/pix-data/collapse` for the full API.
|
|
24
|
+
|
|
9
25
|
## Install
|
|
10
26
|
|
|
11
27
|
```bash
|
package/package.json
CHANGED
package/src/todo.ts
CHANGED
|
@@ -9,14 +9,66 @@
|
|
|
9
9
|
* checklist is seeded by the model via the tool's `set` action.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
12
14
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
13
15
|
import { Text } from "@earendil-works/pi-tui";
|
|
14
16
|
import { Type } from "typebox";
|
|
15
17
|
|
|
16
18
|
import { once } from "./once.ts";
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
// ── Collapse config from ~/.pi/agent/pix.json ────────────────────────────────
|
|
21
|
+
|
|
22
|
+
interface CollapseConf {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
delaySec: number;
|
|
25
|
+
tools: Record<string, boolean | undefined>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_COLLAPSE: CollapseConf = {
|
|
29
|
+
enabled: true,
|
|
30
|
+
delaySec: 10,
|
|
31
|
+
tools: {},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function readCollapseConfig(): CollapseConf {
|
|
35
|
+
try {
|
|
36
|
+
const home = process.env.HOME ?? "";
|
|
37
|
+
if (!home) return DEFAULT_COLLAPSE;
|
|
38
|
+
const p = join(home, ".pi/agent", "pix.json");
|
|
39
|
+
if (!existsSync(p)) return DEFAULT_COLLAPSE;
|
|
40
|
+
const raw = JSON.parse(readFileSync(p, "utf-8")) as Record<string, unknown>;
|
|
41
|
+
const c = raw?.collapse as Record<string, unknown> | undefined;
|
|
42
|
+
if (!c || typeof c !== "object") return DEFAULT_COLLAPSE;
|
|
43
|
+
return {
|
|
44
|
+
enabled: typeof c.enabled === "boolean" ? c.enabled : true,
|
|
45
|
+
delaySec:
|
|
46
|
+
typeof c.delaySec === "number" && c.delaySec > 0 ? c.delaySec : 10,
|
|
47
|
+
tools:
|
|
48
|
+
c.tools && typeof c.tools === "object"
|
|
49
|
+
? (c.tools as Record<string, boolean | undefined>)
|
|
50
|
+
: {},
|
|
51
|
+
};
|
|
52
|
+
} catch {
|
|
53
|
+
return DEFAULT_COLLAPSE;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let collapseConf: CollapseConf | null = null;
|
|
58
|
+
function getCollapseConfig(): CollapseConf {
|
|
59
|
+
if (!collapseConf) collapseConf = readCollapseConfig();
|
|
60
|
+
return collapseConf;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function shouldCollapseTodo(): boolean {
|
|
64
|
+
const c = getCollapseConfig();
|
|
65
|
+
const perTool = c.tools.todo;
|
|
66
|
+
return typeof perTool === "boolean" ? perTool : c.enabled;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function collapseDelayMs(): number {
|
|
70
|
+
return getCollapseConfig().delaySec * 1000;
|
|
71
|
+
}
|
|
20
72
|
|
|
21
73
|
export type TodoStatus = "pending" | "in_progress" | "done" | "blocked";
|
|
22
74
|
|
|
@@ -161,11 +213,12 @@ export default function registerTodo(pi: ExtensionAPI): void {
|
|
|
161
213
|
};
|
|
162
214
|
if (!state.snapshot) state.snapshot = todos.map((t) => ({ ...t }));
|
|
163
215
|
// Start the collapse timer once per row; invalidate() triggers rerender.
|
|
164
|
-
|
|
216
|
+
// Config-driven: reads from ~/.pi/agent/pix.json collapse section.
|
|
217
|
+
if (shouldCollapseTodo() && !state.collapsed && !state.timer) {
|
|
165
218
|
state.timer = setTimeout(() => {
|
|
166
219
|
state.collapsed = true;
|
|
167
220
|
context.invalidate();
|
|
168
|
-
},
|
|
221
|
+
}, collapseDelayMs());
|
|
169
222
|
}
|
|
170
223
|
const render = state.collapsed
|
|
171
224
|
? renderTodoSummaryLine
|