@pify/plan-mode 0.1.0 → 0.2.0
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/extensions/plan-mode.ts +13 -2
- package/package.json +13 -5
- package/src/plans.ts +17 -1
package/extensions/plan-mode.ts
CHANGED
|
@@ -26,7 +26,7 @@ import type {
|
|
|
26
26
|
import { Type } from "typebox";
|
|
27
27
|
|
|
28
28
|
import { classifyToolCall } from "../src/policy.ts";
|
|
29
|
-
import { createPlanFile } from "../src/plans.ts";
|
|
29
|
+
import { createPlanFile, listPlanFiles } from "../src/plans.ts";
|
|
30
30
|
import {
|
|
31
31
|
ENTER_REMINDER,
|
|
32
32
|
EXIT_REMINDER,
|
|
@@ -347,9 +347,20 @@ export default function planMode(pi: ExtensionAPI) {
|
|
|
347
347
|
// ── Command & shortcut ───────────────────────────────────────────────
|
|
348
348
|
|
|
349
349
|
pi.registerCommand("plan", {
|
|
350
|
-
description: "Toggle read-only plan mode: /plan [off | <first planning prompt>]",
|
|
350
|
+
description: "Toggle read-only plan mode: /plan [off | list | <first planning prompt>]",
|
|
351
351
|
handler: async (args, ctx) => {
|
|
352
352
|
const text = (args ?? "").trim();
|
|
353
|
+
if (text.toLowerCase() === "list") {
|
|
354
|
+
const plans = listPlanFiles(ctx.cwd);
|
|
355
|
+
notify(
|
|
356
|
+
ctx,
|
|
357
|
+
plans.length > 0
|
|
358
|
+
? `${plans.map((p) => `${p.file} (${p.size} chars)`).join("\n")}\nLocation: .pi/plans/`
|
|
359
|
+
: "No saved plans yet (.pi/plans/ is empty).",
|
|
360
|
+
"info",
|
|
361
|
+
);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
353
364
|
if (text.toLowerCase() === "off") {
|
|
354
365
|
if (!state.active) {
|
|
355
366
|
notify(ctx, "Plan mode is not active.", "info");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pify/plan-mode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Read-only planning mode for pi with an explicit approve-then-execute gate: enforced tool policy, plan files, approach options, fresh-session handoff",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -31,8 +31,12 @@
|
|
|
31
31
|
"LICENSE"
|
|
32
32
|
],
|
|
33
33
|
"pi": {
|
|
34
|
-
"extensions": [
|
|
35
|
-
|
|
34
|
+
"extensions": [
|
|
35
|
+
"./extensions/plan-mode.ts"
|
|
36
|
+
],
|
|
37
|
+
"skills": [
|
|
38
|
+
"./skills"
|
|
39
|
+
]
|
|
36
40
|
},
|
|
37
41
|
"scripts": {
|
|
38
42
|
"typecheck": "tsc --noEmit",
|
|
@@ -44,8 +48,12 @@
|
|
|
44
48
|
"typebox": "*"
|
|
45
49
|
},
|
|
46
50
|
"peerDependenciesMeta": {
|
|
47
|
-
"@earendil-works/pi-coding-agent": {
|
|
48
|
-
|
|
51
|
+
"@earendil-works/pi-coding-agent": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"typebox": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
49
57
|
},
|
|
50
58
|
"devDependencies": {
|
|
51
59
|
"@earendil-works/pi-coding-agent": "^0.84.4",
|
package/src/plans.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, writeFileSync, existsSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
|
|
4
4
|
/** Plan files live in .pi/plans/, reviewable and committable. */
|
|
@@ -25,6 +25,22 @@ export function localDateStr(d: Date = new Date()): string {
|
|
|
25
25
|
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** List saved plan files, newest first (v0.2: saved-plan library, minimal form). */
|
|
29
|
+
export function listPlanFiles(cwd: string): Array<{ file: string; size: number }> {
|
|
30
|
+
const dir = plansDir(cwd);
|
|
31
|
+
try {
|
|
32
|
+
return readdirSync(dir)
|
|
33
|
+
.filter((f) => f.endsWith(".md"))
|
|
34
|
+
.map((f) => {
|
|
35
|
+
const full = join(dir, f);
|
|
36
|
+
return { file: f, size: statSync(full).size };
|
|
37
|
+
})
|
|
38
|
+
.sort((a, b) => b.file.localeCompare(a.file));
|
|
39
|
+
} catch {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
/** Create the plan file, uniquified when the slug collides on the same day. */
|
|
29
45
|
export function createPlanFile(cwd: string, title: string, content: string): string {
|
|
30
46
|
const dir = plansDir(cwd);
|