@agent-plan/pi-adapter 0.2.19-next.13 → 0.2.19-next.15
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +157 -23
- package/package.json +3 -3
- package/web-ui-dist/assets/index-DNjqMsl7.js +263 -0
- package/web-ui-dist/assets/index-zZFIH6DD.css +1 -0
- package/web-ui-dist/index.html +2 -2
- package/web-ui-dist/assets/index-B-VyxR0L.css +0 -1
- package/web-ui-dist/assets/index-Co7MlHI7.js +0 -253
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,iCAAiC,CAAC;AAmvBtF,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAwmG9D"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - inject context into prompts
|
|
10
10
|
*/
|
|
11
11
|
import { Type } from "typebox";
|
|
12
|
-
import { ExportService, PlanStore, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, needsMotivation, findPhaseByRef, findTaskByRef, buildRecap } from "@agent-plan/core";
|
|
12
|
+
import { ExportService, PlanStore, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, needsMotivation, findPhaseByRef, findTaskByRef, buildRecap, addChecklistItem, removeChecklistItem, toggleChecklistItem } from "@agent-plan/core";
|
|
13
13
|
import { createChecklistItemId, createFeatureId, createPhaseId, createShortId, createTaskId, clampSlug, normalizeSlug, formatPhaseRef, formatFeatureRef, featureNumberOfPhase } from "@agent-plan/core/naming";
|
|
14
14
|
import { join, dirname } from "node:path";
|
|
15
15
|
import { homedir } from "node:os";
|
|
@@ -124,6 +124,9 @@ const PLANNER_COMMAND_COMPLETIONS = [
|
|
|
124
124
|
{ value: "task delete", label: "task delete", description: "Delete a task" },
|
|
125
125
|
{ value: "task start", label: "task start", description: "Mark a task in-progress" },
|
|
126
126
|
{ value: "task complete", label: "task complete", description: "Mark a task done" },
|
|
127
|
+
{ value: "task checklist-add", label: "task checklist-add", description: "Add a checklist step: /planner task checklist-add <T00x> <title>" },
|
|
128
|
+
{ value: "task checklist-remove", label: "task checklist-remove", description: "Remove a step: /planner task checklist-remove <T00x> <C{n}|title>" },
|
|
129
|
+
{ value: "task checklist-toggle", label: "task checklist-toggle", description: "Tick/untick a step: /planner task checklist-toggle <T00x> <C{n}|title> [on|off]" },
|
|
127
130
|
{ value: "handoff list", label: "handoff list", description: "List phases with a handoff" },
|
|
128
131
|
{ value: "handoff prepare", label: "handoff prepare", description: "Tell the agent to write the handoff (legacy file-based)" },
|
|
129
132
|
{ value: "handoff show", label: "handoff show [P00x]", description: "Show a phase handoff (default: in-progress phase)" },
|
|
@@ -1770,7 +1773,7 @@ export default function planPiExtension(pi) {
|
|
|
1770
1773
|
// ═══════════════════════════════════════════════════════════════
|
|
1771
1774
|
if (a === "task") {
|
|
1772
1775
|
if (!b) {
|
|
1773
|
-
ctx.ui.notify("task actions: add | show [id] | discuss [id|name] | delete | update | start [id] | complete [id]", "info");
|
|
1776
|
+
ctx.ui.notify("task actions: add | show [id] | discuss [id|name] | delete | update | start [id] | complete [id] | checklist-add <T00x> <title> | checklist-remove <T00x> <C{n}|title> | checklist-toggle <T00x> <C{n}|title> [on|off]", "info");
|
|
1774
1777
|
return;
|
|
1775
1778
|
}
|
|
1776
1779
|
if (b === "add") {
|
|
@@ -2086,7 +2089,75 @@ export default function planPiExtension(pi) {
|
|
|
2086
2089
|
ctx.ui.notify(`✅ Task completed: ${formatPhaseRef(phase.number, featureNumberOfPhase(phase, (await st.loadFeatures()).features))}/T${String(task.number).padStart(3, "0")} — ${task.title} (done)${task.shortId ? ` · ${task.shortId}` : ""}`, "info");
|
|
2087
2090
|
return;
|
|
2088
2091
|
}
|
|
2089
|
-
|
|
2092
|
+
// checklist-add <T00x> <title> / checklist-remove <T00x> <C{n}|title> / checklist-toggle <T00x> <C{n}|title> [on|off]
|
|
2093
|
+
if (b === "checklist-add" || b === "checklist-remove" || b === "checklist-toggle") {
|
|
2094
|
+
const [taskRef, ...itemParts] = rest;
|
|
2095
|
+
const itemText = itemParts.join(" ").trim();
|
|
2096
|
+
if (!taskRef || !itemText) {
|
|
2097
|
+
ctx.ui.notify(`Usage: /planner task ${b} <T00x> <${b === "checklist-add" ? "title" : "C{n}|title"}>${b === "checklist-toggle" ? " [on|off]" : ""}`, "warning");
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
const resolved = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, taskRef.trim());
|
|
2101
|
+
if (!resolved) {
|
|
2102
|
+
ctx.ui.notify(`Task not found: ${taskRef}`, "warning");
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
let checked;
|
|
2106
|
+
if (b === "checklist-toggle") {
|
|
2107
|
+
const m = itemText.match(/\s+(on|off)$/i);
|
|
2108
|
+
if (m) {
|
|
2109
|
+
checked = m[1].toLowerCase() === "on";
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
const selector = b === "checklist-toggle" ? itemText.replace(/\s+(on|off)$/i, "").trim() : itemText;
|
|
2113
|
+
let msg = "";
|
|
2114
|
+
await st.updatePhase(resolved.phase.id, (phase) => {
|
|
2115
|
+
const task = phase.tasks.find((t) => t.id === resolved.task.id);
|
|
2116
|
+
if (!task) {
|
|
2117
|
+
msg = `Task not found: ${taskRef}`;
|
|
2118
|
+
return phase;
|
|
2119
|
+
}
|
|
2120
|
+
const ck = task.checklist ?? [];
|
|
2121
|
+
if (b === "checklist-add") {
|
|
2122
|
+
const item = addChecklistItem(ck, task.id, selector);
|
|
2123
|
+
ck.push(item);
|
|
2124
|
+
task.checklist = ck;
|
|
2125
|
+
msg = `Added C${item.number} "${item.title}" (${ck.length} items)`;
|
|
2126
|
+
}
|
|
2127
|
+
else if (b === "checklist-remove") {
|
|
2128
|
+
if (ck.length === 0) {
|
|
2129
|
+
msg = `Task "${task.title}" has no checklist.`;
|
|
2130
|
+
return phase;
|
|
2131
|
+
}
|
|
2132
|
+
const removed = removeChecklistItem(ck, selector);
|
|
2133
|
+
if (!removed) {
|
|
2134
|
+
msg = `No checklist item matching "${selector}".`;
|
|
2135
|
+
return phase;
|
|
2136
|
+
}
|
|
2137
|
+
msg = `Removed C${removed.number} "${removed.title}" (${ck.length} items left)`;
|
|
2138
|
+
}
|
|
2139
|
+
else {
|
|
2140
|
+
if (ck.length === 0) {
|
|
2141
|
+
msg = `Task "${task.title}" has no checklist.`;
|
|
2142
|
+
return phase;
|
|
2143
|
+
}
|
|
2144
|
+
const target = toggleChecklistItem(ck, selector, checked);
|
|
2145
|
+
if (!target) {
|
|
2146
|
+
msg = `No checklist item matching "${selector}".`;
|
|
2147
|
+
return phase;
|
|
2148
|
+
}
|
|
2149
|
+
const doneCount = ck.filter((i) => i.checked).length;
|
|
2150
|
+
msg = `C${target.number} "${target.title}" → ${target.checked ? "done" : "open"} (${doneCount}/${ck.length} checked)`;
|
|
2151
|
+
}
|
|
2152
|
+
task.updatedAt = nowISO();
|
|
2153
|
+
phase.updatedAt = nowISO();
|
|
2154
|
+
return phase;
|
|
2155
|
+
});
|
|
2156
|
+
await st.writeGenerated();
|
|
2157
|
+
ctx.ui.notify(`✅ ${msg}`, "info");
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
ctx.ui.notify(`Unknown task action "${b}". Try: add, show, discuss, delete, update, start, complete, checklist-add, checklist-remove, checklist-toggle`, "warning");
|
|
2090
2161
|
return;
|
|
2091
2162
|
}
|
|
2092
2163
|
// ── discuss (legacy alias) ──
|
|
@@ -3339,6 +3410,7 @@ export default function planPiExtension(pi) {
|
|
|
3339
3410
|
description: Type.String({ description: "REQUIRED — execution context: code references (file:line), current state vs desired state, structs/traits to modify, concrete implementation steps, edge cases. Not a one-liner. Prefix with 'design-only' for pre-implementation design tasks.", minLength: 50 }),
|
|
3340
3411
|
status: Type.Optional(Type.String({ description: "Initial status. Default: planned" })),
|
|
3341
3412
|
shortName: Type.Optional(Type.String({ description: "Short slug for the task id. Auto-derived from title if omitted." })),
|
|
3413
|
+
checklist: Type.Optional(Type.Array(Type.String(), { description: "Initial checklist items (plain strings). Seeded as C1, C2, … (unchecked)." })),
|
|
3342
3414
|
}),
|
|
3343
3415
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
3344
3416
|
const st = await requirePlan(ctx);
|
|
@@ -3367,7 +3439,10 @@ export default function planPiExtension(pi) {
|
|
|
3367
3439
|
statusLog: [],
|
|
3368
3440
|
decisions: [],
|
|
3369
3441
|
acceptedDecisions: [],
|
|
3370
|
-
checklist:
|
|
3442
|
+
checklist: params.checklist
|
|
3443
|
+
? params.checklist.map((itemTitle, index) => ({ number: index + 1, id: createChecklistItemId(taskId, index + 1, itemTitle), title: itemTitle, checked: false }))
|
|
3444
|
+
: [],
|
|
3445
|
+
subtasks: [],
|
|
3371
3446
|
dependsOn: [],
|
|
3372
3447
|
startedAt: initialStatus === "in-progress" || initialStatus === "done" ? now : "",
|
|
3373
3448
|
completedAt: initialStatus === "done" ? now : "",
|
|
@@ -3614,32 +3689,91 @@ export default function planPiExtension(pi) {
|
|
|
3614
3689
|
result = `Task "${found.task.title}" has no checklist.`;
|
|
3615
3690
|
return phase;
|
|
3616
3691
|
}
|
|
3617
|
-
|
|
3618
|
-
const cMatch = params.item.match(/^C(\d+)$/i);
|
|
3619
|
-
if (cMatch) {
|
|
3620
|
-
const idx = parseInt(cMatch[1], 10) - 1;
|
|
3621
|
-
if (idx < 0 || idx >= ck.length) {
|
|
3622
|
-
result = `C${idx + 1} not found (1..${ck.length}).`;
|
|
3623
|
-
return phase;
|
|
3624
|
-
}
|
|
3625
|
-
target = ck[idx];
|
|
3626
|
-
}
|
|
3627
|
-
else {
|
|
3628
|
-
const needle = params.item.trim().toLowerCase();
|
|
3629
|
-
target = ck.find((i) => i.id === params.item)
|
|
3630
|
-
?? ck.find((i) => i.title.trim().toLowerCase() === needle)
|
|
3631
|
-
?? ck.find((i) => i.title.trim().toLowerCase().includes(needle));
|
|
3632
|
-
}
|
|
3692
|
+
const target = toggleChecklistItem(ck, params.item, params.checked);
|
|
3633
3693
|
if (!target) {
|
|
3634
3694
|
result = `No checklist item matching "${params.item}".`;
|
|
3635
3695
|
return phase;
|
|
3636
3696
|
}
|
|
3637
|
-
const newValue = params.checked ?? !target.checked;
|
|
3638
|
-
target.checked = newValue;
|
|
3639
3697
|
task.updatedAt = nowISO();
|
|
3640
3698
|
phase.updatedAt = nowISO();
|
|
3641
3699
|
const doneCount = ck.filter((i) => i.checked).length;
|
|
3642
|
-
result = `C${target.number} "${target.title}" → ${
|
|
3700
|
+
result = `C${target.number} "${target.title}" → ${target.checked ? "done" : "open"} (${doneCount}/${ck.length} checked)`;
|
|
3701
|
+
return phase;
|
|
3702
|
+
});
|
|
3703
|
+
await st.writeGenerated();
|
|
3704
|
+
return { content: [{ type: "text", text: `✅ ${result}` }], details: {} };
|
|
3705
|
+
},
|
|
3706
|
+
});
|
|
3707
|
+
pi.registerTool({
|
|
3708
|
+
name: "task_checklist_add",
|
|
3709
|
+
label: "Task Checklist Add",
|
|
3710
|
+
description: "Add a single checklist item (a 'step') to a task without rewriting the list. The new item is appended as C{n} (next progressive number, stable id, unchecked). Use this to subdivide a task into smaller steps INSTEAD of spawning sub-tasks — the checklist keeps description, notes, statusLog and steps concentrated in one task (sub-tasks disperse context). Also use for granular adds instead of replacing the whole checklist via task_update.",
|
|
3711
|
+
parameters: Type.Object({
|
|
3712
|
+
taskId: Type.String({ description: "Task ref: F00x/P00x/T00x, bare T00x (global), 5-char shortId, UUID, or title" }),
|
|
3713
|
+
title: Type.String({ description: "Checklist item text (a single step)" }),
|
|
3714
|
+
}),
|
|
3715
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
3716
|
+
const st = await requirePlan(ctx);
|
|
3717
|
+
if (!st)
|
|
3718
|
+
return { content: [{ type: "text", text: "No .planner/ found." }], details: {} };
|
|
3719
|
+
const found = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, params.taskId.trim());
|
|
3720
|
+
if (!found)
|
|
3721
|
+
return { content: [{ type: "text", text: `Task not found: ${params.taskId}` }], details: {} };
|
|
3722
|
+
let result = "";
|
|
3723
|
+
await st.updatePhase(found.phase.id, (phase) => {
|
|
3724
|
+
const task = phase.tasks.find((t) => t.id === found.task.id);
|
|
3725
|
+
if (!task) {
|
|
3726
|
+
result = `Task not found: ${params.taskId}`;
|
|
3727
|
+
return phase;
|
|
3728
|
+
}
|
|
3729
|
+
const ck = task.checklist ?? [];
|
|
3730
|
+
const item = addChecklistItem(ck, task.id, params.title);
|
|
3731
|
+
ck.push(item);
|
|
3732
|
+
task.checklist = ck;
|
|
3733
|
+
task.updatedAt = nowISO();
|
|
3734
|
+
phase.updatedAt = nowISO();
|
|
3735
|
+
result = `Added C${item.number} "${item.title}" (${ck.length} items)`;
|
|
3736
|
+
return phase;
|
|
3737
|
+
});
|
|
3738
|
+
await st.writeGenerated();
|
|
3739
|
+
return { content: [{ type: "text", text: `✅ ${result}` }], details: {} };
|
|
3740
|
+
},
|
|
3741
|
+
});
|
|
3742
|
+
pi.registerTool({
|
|
3743
|
+
name: "task_checklist_remove",
|
|
3744
|
+
label: "Task Checklist Remove",
|
|
3745
|
+
description: "Remove a single checklist item (a 'step') from a task by C{n} (e.g. C2), item id, or title (case-insensitive). Remaining items are renumbered C1..Cn for readability; their stable ids are preserved. Use this for granular removes instead of replacing the whole checklist via task_update.",
|
|
3746
|
+
parameters: Type.Object({
|
|
3747
|
+
taskId: Type.String({ description: "Task ref: F00x/P00x/T00x, bare T00x (global), 5-char shortId, UUID, or title" }),
|
|
3748
|
+
item: Type.String({ description: "Checklist item selector: C{n} (e.g. C2), item id, or title (case-insensitive)" }),
|
|
3749
|
+
}),
|
|
3750
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
3751
|
+
const st = await requirePlan(ctx);
|
|
3752
|
+
if (!st)
|
|
3753
|
+
return { content: [{ type: "text", text: "No .planner/ found." }], details: {} };
|
|
3754
|
+
const found = findTaskByRef(await st.loadAllPhases(), (await st.loadFeatures()).features, params.taskId.trim());
|
|
3755
|
+
if (!found)
|
|
3756
|
+
return { content: [{ type: "text", text: `Task not found: ${params.taskId}` }], details: {} };
|
|
3757
|
+
let result = "";
|
|
3758
|
+
await st.updatePhase(found.phase.id, (phase) => {
|
|
3759
|
+
const task = phase.tasks.find((t) => t.id === found.task.id);
|
|
3760
|
+
if (!task) {
|
|
3761
|
+
result = `Task not found: ${params.taskId}`;
|
|
3762
|
+
return phase;
|
|
3763
|
+
}
|
|
3764
|
+
const ck = task.checklist ?? [];
|
|
3765
|
+
if (ck.length === 0) {
|
|
3766
|
+
result = `Task "${found.task.title}" has no checklist.`;
|
|
3767
|
+
return phase;
|
|
3768
|
+
}
|
|
3769
|
+
const removed = removeChecklistItem(ck, params.item);
|
|
3770
|
+
if (!removed) {
|
|
3771
|
+
result = `No checklist item matching "${params.item}".`;
|
|
3772
|
+
return phase;
|
|
3773
|
+
}
|
|
3774
|
+
task.updatedAt = nowISO();
|
|
3775
|
+
phase.updatedAt = nowISO();
|
|
3776
|
+
result = `Removed C${removed.number} "${removed.title}" (${ck.length} items left)`;
|
|
3643
3777
|
return phase;
|
|
3644
3778
|
});
|
|
3645
3779
|
await st.writeGenerated();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/pi-adapter",
|
|
3
|
-
"version": "0.2.19-next.
|
|
3
|
+
"version": "0.2.19-next.15",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Pi agent extension for Agent Plan — structured project planning in .planner/",
|
|
6
6
|
"keywords": [
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"typebox": "^1.1.24",
|
|
30
30
|
"zod": "^3.24.0",
|
|
31
|
-
"@agent-plan/core": "0.2.19-next.
|
|
32
|
-
"@agent-plan/server": "0.2.19-next.
|
|
31
|
+
"@agent-plan/core": "0.2.19-next.15",
|
|
32
|
+
"@agent-plan/server": "0.2.19-next.15"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@earendil-works/pi-coding-agent": "^0.74.0",
|