pi-note 0.7.1 → 0.8.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/README.md +23 -4
- package/index.ts +23 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,10 +56,10 @@ standalone `settings/pi/extensions/pinote.ts` entry if installed; load only one
|
|
|
56
56
|
|
|
57
57
|
## Use
|
|
58
58
|
|
|
59
|
-
`/pi-note` picks a task, marks it in progress, and adds this prompt to the editor:
|
|
59
|
+
`/pi-note` picks a task, marks it in progress, and adds this default prompt to the editor:
|
|
60
60
|
“Read the current Pinote task. Summarize your understanding, but don’t start work yet.”
|
|
61
61
|
The agent fetches current task text and saved handoff fields when you submit;
|
|
62
|
-
they are not copied into the draft. The prompt asks for a summary, not implementation.
|
|
62
|
+
they are not copied into the draft. The default prompt asks for a summary, not implementation.
|
|
63
63
|
Existing drafts are preserved; nothing is submitted automatically.
|
|
64
64
|
With a selected task it offers **Continue**, **Done**, and **Switch task**.
|
|
65
65
|
Type in the task picker to filter by text, ID, tag, or state (all words must match).
|
|
@@ -74,14 +74,33 @@ Resume restores that session's task; a new session starts unselected and does no
|
|
|
74
74
|
an older per-folder selection. Pi saves the session after the first submitted message;
|
|
75
75
|
quitting before that leaves the next launch unselected, while the task stays in progress.
|
|
76
76
|
Use **Continue**
|
|
77
|
-
to insert the same
|
|
77
|
+
to insert the same configured prompt. Completing, removing, or scheduling a task clears it
|
|
78
78
|
from sessions that refresh it. Switching does not complete or reset the previous task.
|
|
79
79
|
Task fields such as `Worktree` and `PR` stay on the task, so sessions can use separate
|
|
80
80
|
worktrees and pull requests. Task status refreshes at session start, before/after
|
|
81
81
|
agent activity, and after commands/tools. The CLI's per-directory `agent selected`
|
|
82
82
|
command is not this session memory.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
### Handoff prompt configuration
|
|
85
|
+
|
|
86
|
+
Set `handoffPrompt` in `~/.pi/agent/pi-note.json` (or in the agent directory set
|
|
87
|
+
by `PI_CODING_AGENT_DIR`):
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"handoffPrompt": "Read the current Pinote task. Summarize your understanding and proposed approach, but don’t start work yet."
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Both task selection and **Continue** read this file each time; no `/reload` is
|
|
96
|
+
needed after edits. The value is literal text, not a prompt template; use `\n`
|
|
97
|
+
in JSON strings for multiple lines. It must be a nonblank string without control
|
|
98
|
+
characters other than tabs and newlines. A missing file or key uses the default.
|
|
99
|
+
Invalid/unreadable configuration reports an error without starting/switching a
|
|
100
|
+
task or changing the editor. **Done** and agent tools are unaffected. This is
|
|
101
|
+
user-level configuration only; project-local files are not read.
|
|
102
|
+
|
|
103
|
+
### Agent tools
|
|
85
104
|
|
|
86
105
|
- `pinote_get_current`: read this session's selected task, including its revision.
|
|
87
106
|
Takes no arguments; returns null when this session has no selected task.
|
package/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { getAgentDir, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
4
5
|
import { stripVTControlCharacters } from "node:util";
|
|
5
6
|
import { Type } from "typebox";
|
|
6
7
|
import { createPRWatcher } from "./pr-watch.ts";
|
|
@@ -34,6 +35,26 @@ const clean = (value: string) => stripVTControlCharacters(value).replace(/[\x00-
|
|
|
34
35
|
const firstLine = (task: Summary) => clean(task.text.split("\n", 1)[0]).replace(/\s+/gu, " ").trim();
|
|
35
36
|
const title = (task: Summary) => truncateToWidth(`#${task.id} ${firstLine(task)}`, 60);
|
|
36
37
|
|
|
38
|
+
const defaultHandoffPrompt = "Read the current Pinote task. Summarize your understanding, but don’t start work yet.";
|
|
39
|
+
function handoffPrompt(): string {
|
|
40
|
+
const path = join(getAgentDir(), "pi-note.json");
|
|
41
|
+
let raw: string;
|
|
42
|
+
try {
|
|
43
|
+
raw = readFileSync(path, "utf8");
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return defaultHandoffPrompt;
|
|
46
|
+
throw new Error(`Cannot read ${path}. Check the pi-note configuration.`);
|
|
47
|
+
}
|
|
48
|
+
let config: unknown;
|
|
49
|
+
try { config = JSON.parse(raw); } catch { throw new Error(`Invalid JSON in ${path}.`); }
|
|
50
|
+
if (!record(config)) throw new Error(`Expected a JSON object in ${path}.`);
|
|
51
|
+
if (!("handoffPrompt" in config)) return defaultHandoffPrompt;
|
|
52
|
+
if (!text(config.handoffPrompt) || !config.handoffPrompt.trim()) {
|
|
53
|
+
throw new Error(`handoffPrompt in ${path} must be a nonblank string without control characters (except tabs/newlines).`);
|
|
54
|
+
}
|
|
55
|
+
return config.handoffPrompt;
|
|
56
|
+
}
|
|
57
|
+
|
|
37
58
|
function parse(raw: string): unknown {
|
|
38
59
|
try { return JSON.parse(raw); } catch { throw new Error(compatible); }
|
|
39
60
|
}
|
|
@@ -333,6 +354,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
333
354
|
if (currentSession()) ctx.ui.notify(`Pinote #${current.id} completed.`, "info");
|
|
334
355
|
return;
|
|
335
356
|
}
|
|
357
|
+
const handoff = handoffPrompt();
|
|
336
358
|
let id: number;
|
|
337
359
|
if (action === "Continue" && current) {
|
|
338
360
|
id = current.id;
|
|
@@ -349,7 +371,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
349
371
|
const chosen = await startTask(id, canAct);
|
|
350
372
|
if (!chosen || !canAct()) return;
|
|
351
373
|
const draft = ctx.ui.getEditorText();
|
|
352
|
-
const handoff = "Read the current Pinote task. Summarize your understanding, but don’t start work yet.";
|
|
353
374
|
ctx.ui.setEditorText(draft ? `${draft}\n\n${handoff}` : handoff);
|
|
354
375
|
ctx.ui.notify(`Pinote #${chosen.id} is in progress. Task added to input.`, "info");
|
|
355
376
|
} catch (error) {
|