pi-note 0.32.0 → 0.33.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/LOCAL.md +12 -12
- package/README.md +7 -1
- package/index.ts +12 -12
- package/package.json +1 -1
- package/remote.ts +0 -1
- package/setup.ts +4 -4
package/LOCAL.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[npm](https://www.npmjs.com/package/pi-note) · [Pi package directory](https://pi.dev/packages/pi-note)
|
|
4
4
|
|
|
5
5
|
Persistent [pinote](https://github.com/kvidzibo/pinote) tasks and Markdown handoffs
|
|
6
|
-
in Pi: selected-task footer status, `/
|
|
6
|
+
in Pi: selected-task footer status, `/pinote`, and agent current-task read/update,
|
|
7
7
|
add, and tag-listing tools.
|
|
8
8
|
The extension and Python app share a repository but install separately.
|
|
9
9
|
|
|
@@ -30,8 +30,8 @@ Install [uv](https://docs.astral.sh/uv/getting-started/installation/) first and
|
|
|
30
30
|
restart Pi with `uv` on PATH. At startup the extension checks `note --version`
|
|
31
31
|
against its bundled CLI version (currently 0.4.0), without network requests:
|
|
32
32
|
|
|
33
|
-
- Missing/unrecognized CLI: `/
|
|
34
|
-
- Older CLI: `/
|
|
33
|
+
- Missing/unrecognized CLI: `/pinote` opens Settings directly, where **Install CLI** is available.
|
|
34
|
+
- Older CLI: `/pinote` opens Settings directly, where **Upgrade CLI** is available.
|
|
35
35
|
- Equal/newer CLI: neither installation action is shown; no upgrade notification.
|
|
36
36
|
|
|
37
37
|
Install and upgrade recheck the CLI version and ask before installing into uv's
|
|
@@ -54,7 +54,7 @@ Check `note --version`, then restart Pi or `/reload`. Network/build failures and
|
|
|
54
54
|
conflicting executables are reported without forcibly overwriting another
|
|
55
55
|
installer's commands. Fix the reported cause and retry; installs time out after
|
|
56
56
|
three minutes. Installation actions are unavailable while installation runs.
|
|
57
|
-
Setup hints direct users to `/
|
|
57
|
+
Setup hints direct users to `/pinote` → Settings.
|
|
58
58
|
Missing uv is reported with its installation link, not installed
|
|
59
59
|
automatically. The [GTK desktop app](../README.md#optional-gtk-checklist) is optional
|
|
60
60
|
and still requires separate system dependencies.
|
|
@@ -65,16 +65,16 @@ standalone `settings/pi/extensions/pinote.ts` entry if installed; load only one
|
|
|
65
65
|
|
|
66
66
|
## Use
|
|
67
67
|
|
|
68
|
-
When the CLI is ready and no task is selected, `/
|
|
68
|
+
When the CLI is ready and no task is selected, `/pinote` opens the task picker.
|
|
69
69
|
It marks the chosen task in progress and adds this default prompt to the editor:
|
|
70
70
|
“Read the current Pinote task. Summarize your understanding, but don’t start work yet.”
|
|
71
|
-
If the CLI is missing or older than the bundled version, `/
|
|
71
|
+
If the CLI is missing or older than the bundled version, `/pinote` opens Settings
|
|
72
72
|
directly so the relevant CLI installation action remains accessible. **Tab** opens
|
|
73
73
|
Settings from the picker or task view; **Tab** from Settings returns to tasks.
|
|
74
74
|
The agent fetches current task text and saved handoff fields when you submit;
|
|
75
75
|
they are not copied into the draft. The default prompt asks for a summary, not implementation.
|
|
76
76
|
Existing drafts are preserved; nothing is submitted automatically.
|
|
77
|
-
With a selected task, `/
|
|
77
|
+
With a selected task, `/pinote` offers **Continue**, **Done**, **Switch task**, and
|
|
78
78
|
**Settings**. Settings provides **Preview task**, **Complete task (new session)**,
|
|
79
79
|
**Accept suggestion**, and **Dismiss suggestion** when applicable, plus
|
|
80
80
|
**Install CLI** or **Upgrade CLI** only when needed. Settings also lists fields found
|
|
@@ -170,7 +170,7 @@ and selected tasks. Run `/reload` after changing this setting. Invalid policy
|
|
|
170
170
|
values or unreadable/malformed configuration suppress offers; interactive startup
|
|
171
171
|
warns until you fix the file and reload. No project-local configuration is read.
|
|
172
172
|
|
|
173
|
-
In `/
|
|
173
|
+
In `/pinote → Settings`, select **Task prompt** to edit the text inserted after
|
|
174
174
|
selection or **Continue**. **Shift+Enter** or **Ctrl+J** adds a newline; **Enter** saves it
|
|
175
175
|
globally, **Ctrl+C** clears the edit, and **Esc** cancels that unfinished edit.
|
|
176
176
|
|
|
@@ -219,7 +219,7 @@ configuration only; project-local files are not read.
|
|
|
219
219
|
|
|
220
220
|
Version 0.7.0 replaces `pinote_get`/`pinote_update` with these current-task tools
|
|
221
221
|
and removes `pinote_tag`, without aliases. Agents cannot read/update tasks by ID
|
|
222
|
-
or retag existing tasks; use `/
|
|
222
|
+
or retag existing tasks; use `/pinote` to select an existing task.
|
|
223
223
|
|
|
224
224
|
When allowed by `taskOfferPolicy`, the agent uses `pinote_propose` instead of
|
|
225
225
|
asking in chat. The pin footer shows a pending suggestion, distinct from a selected task:
|
|
@@ -242,7 +242,7 @@ The configured `footer.titleWidth` bounds the entire row (default 60 columns). C
|
|
|
242
242
|
|
|
243
243
|
Controls use the [Kitty preview handler](#display-only-preview), with no additional configuration. Fullscreen Kitty uses **Ctrl+Shift+click**. The Settings actions **Accept suggestion** and **Dismiss suggestion** perform the corresponding footer actions. No action submits input or starts an agent turn. Add and Dismiss preserve editor drafts; **Complete task** starts a clean session and reloads Pi, discarding the editor draft, so save unfinished input before completing a task.
|
|
244
244
|
|
|
245
|
-
Completion requires an idle Pi session and no pending Pinote operation. It rejects stale selected-task links and externally changed revisions. Accepted mutations drain even if the helper disconnects. On an error, check `/
|
|
245
|
+
Completion requires an idle Pi session and no pending Pinote operation. It rejects stale selected-task links and externally changed revisions. Accepted mutations drain even if the helper disconnects. On an error, check `/pinote` before retrying, because a write may already have committed. Failed or stale writes never restart Pi. If another extension cancels the new session, the task remains completed and Pi reports the cancellation. The reload runs through the new session's fresh context; retired contexts are not reused.
|
|
246
246
|
|
|
247
247
|
If another task fits better, the agent can replace an unaccepted suggestion by calling `pinote_propose` again, without waiting for dismissal. Replacement invalidates the old ✚/✖ links; only the latest suggestion can be accepted or dismissed. Pending suggestions survive `/reload` and session resume, including their full text and tag; new links replace stale capabilities. Accepted or dismissed suggestions never reappear on reload, but dismissal does not block new proposals—even in sessions saved by older versions. New sessions and forks start without a suggestion; selecting a task or navigating the tree clears it. Suggestion state is local, display-only session metadata, not model context. Pi saves the session after the first submitted message; quitting before that can still lose unsaved session state. Repeated acceptance cannot duplicate a note. A busy Pinote operation blocks acceptance. Noninteractive agents still ask in chat before using `pinote_add` with `select: true`. An existing selection is not replaced unless the user asks to switch. Reuse a saved
|
|
248
248
|
tag name when it fits.
|
|
@@ -310,7 +310,7 @@ Names are case-sensitive, trimmed and NFC-normalized, at most 64 characters;
|
|
|
310
310
|
accepted. Missing/blank values do not display and do not consume the field limit.
|
|
311
311
|
`[]` or `maxFields: 0` hides configured fields, including PR.
|
|
312
312
|
|
|
313
|
-
In `/
|
|
313
|
+
In `/pinote → Settings`, **Add field** adds a global display definition, not a
|
|
314
314
|
task value. Select any field to edit **Link**, **Label**, **Format**, and **Width**.
|
|
315
315
|
Label starts as the field name; clear it for no prefix. Link off displays plain
|
|
316
316
|
text without a clickable link. Toggles, field additions/removals, and edits confirmed
|
|
@@ -369,7 +369,7 @@ Pinote no longer polls GitHub, runs `gh`, watches completed tasks, or prompts on
|
|
|
369
369
|
PR merges. No GitHub authentication is required. `PINOTE_PR_POLL_SECONDS` is no
|
|
370
370
|
longer used. Other separately installed Pi PR/Git extensions are unaffected.
|
|
371
371
|
|
|
372
|
-
Tools work without a TUI. `/
|
|
372
|
+
Tools work without a TUI. `/pinote` works in a TUI while the agent is running:
|
|
373
373
|
you can select/switch tasks, use Continue, preview tasks, respond to suggestions,
|
|
374
374
|
and edit settings without interrupting the turn or submitting input. Completion
|
|
375
375
|
and CLI installation/upgrades still require an idle session. Another pending
|
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ state routing, tools and UI.
|
|
|
48
48
|
|
|
49
49
|
## Use
|
|
50
50
|
|
|
51
|
-
Open **`/pinote
|
|
51
|
+
Open **`/pinote`**. Select or create a task, preview it,
|
|
52
52
|
clear the selection, complete it, respond to suggestions, or edit shared settings.
|
|
53
53
|
Selecting an existing task starts it immediately and returns focus to the prompt,
|
|
54
54
|
with no extra confirmation. Creation and settings changes still require confirmation.
|
|
@@ -77,6 +77,8 @@ cannot guarantee selection persistence.
|
|
|
77
77
|
|
|
78
78
|
The GTK app's **Start in Kitty…** action (note 0.13.0+) chooses a working directory
|
|
79
79
|
and opens a named tab with this task selected, without submitting a prompt.
|
|
80
|
+
In note 0.16.0+, it uses the tag's default folder when available, otherwise keeps
|
|
81
|
+
the directory chooser. Set or clear defaults in **Manage tags…**.
|
|
80
82
|
With note 0.15.0+ and pi-note 0.32.0+, successful selection prefills an empty Pi editor
|
|
81
83
|
with `is task clear?`. Configure `gui.kitty_start_prompt` in the
|
|
82
84
|
[GUI config](../docs/gui.md#gui-configuration), or set it to `""` to disable; existing
|
|
@@ -121,6 +123,10 @@ separate from global display settings.
|
|
|
121
123
|
|
|
122
124
|
## Migration
|
|
123
125
|
|
|
126
|
+
Since pi-note 0.33.0, `/pinote` is the only slash command in both modes.
|
|
127
|
+
The `/pi-note` alias is removed; update saved shortcuts to `/pinote`.
|
|
128
|
+
The npm package name and `pi-note.json` configuration filename are unchanged.
|
|
129
|
+
|
|
124
130
|
1. Back up the service machine's Pinote data; keep `notes.db` local to that machine.
|
|
125
131
|
2. Start the standalone service against that same database and settings directory.
|
|
126
132
|
3. Remove Pinote's service entry and its unused package entry from the gateway
|
package/index.ts
CHANGED
|
@@ -107,7 +107,7 @@ function task(raw: string): Task | null {
|
|
|
107
107
|
}
|
|
108
108
|
function requiredTask(raw: string, id?: number): Task {
|
|
109
109
|
const value = task(raw);
|
|
110
|
-
if (!value) throw new Error("No selected pinote task. Select one with /
|
|
110
|
+
if (!value) throw new Error("No selected pinote task. Select one with /pinote first.");
|
|
111
111
|
if (id !== undefined && value.id !== id) throw new Error(compatible);
|
|
112
112
|
return value;
|
|
113
113
|
}
|
|
@@ -187,7 +187,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
187
187
|
if (!alive || generation !== epoch || setupAbort) return;
|
|
188
188
|
cliState = action;
|
|
189
189
|
if (suggest && action === "upgrade") {
|
|
190
|
-
ctx.ui.notify(`Pinote CLI ${bundledCLIVersion} is bundled with this extension. Open /
|
|
190
|
+
ctx.ui.notify(`Pinote CLI ${bundledCLIVersion} is bundled with this extension. Open /pinote → Settings → Upgrade CLI to update your older CLI.`, "info");
|
|
191
191
|
}
|
|
192
192
|
};
|
|
193
193
|
|
|
@@ -314,7 +314,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
314
314
|
if (alive && generation === epoch && serial === refreshSerial) {
|
|
315
315
|
previewBridge?.invalidate();
|
|
316
316
|
clearTaskFooter(ctx);
|
|
317
|
-
ctx.ui.setStatus("pinote", suggestionStatus(ctx) ?? `${ctx.ui.theme.bold(noteIcon)} Pinote unavailable · /
|
|
317
|
+
ctx.ui.setStatus("pinote", suggestionStatus(ctx) ?? `${ctx.ui.theme.bold(noteIcon)} Pinote unavailable · /pinote → Settings`);
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
};
|
|
@@ -357,10 +357,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
357
357
|
};
|
|
358
358
|
const timer = setTimeout(() => {
|
|
359
359
|
finish(false);
|
|
360
|
-
if (alive && activeContext === ctx) ctx.ui.notify("Pinote completion could not start. Open /
|
|
360
|
+
if (alive && activeContext === ctx) ctx.ui.notify("Pinote completion could not start. Open /pinote → Settings → Complete task.", "warning");
|
|
361
361
|
}, 4000);
|
|
362
362
|
completionDispatch = { token, selection, task: displayed, started: () => clearTimeout(timer), finish };
|
|
363
|
-
try { pi.sendUserMessage(`/
|
|
363
|
+
try { pi.sendUserMessage(`/pinote ${token}`, { expandPromptTemplates: true }); }
|
|
364
364
|
catch { finish(false); }
|
|
365
365
|
});
|
|
366
366
|
};
|
|
@@ -454,7 +454,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
454
454
|
} catch {
|
|
455
455
|
await bridge.stop();
|
|
456
456
|
if (previewBridge === bridge) previewBridge = undefined;
|
|
457
|
-
ctx.ui.notify("Pinote task link unavailable; open /
|
|
457
|
+
ctx.ui.notify("Pinote task link unavailable; open /pinote → Settings → Preview task.", "warning");
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
460
|
if (!alive || generation !== epoch) return;
|
|
@@ -553,7 +553,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
553
553
|
}
|
|
554
554
|
};
|
|
555
555
|
|
|
556
|
-
pi.registerCommand("
|
|
556
|
+
pi.registerCommand("pinote", {
|
|
557
557
|
description: "Continue, complete, switch tasks, or edit global settings (Tab)",
|
|
558
558
|
handler: async (args, ctx) => {
|
|
559
559
|
if (!ctx.hasUI || ctx.mode !== "tui") return;
|
|
@@ -564,7 +564,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
564
564
|
await completeSelected(token, ctx);
|
|
565
565
|
return;
|
|
566
566
|
}
|
|
567
|
-
if (token) { ctx.ui.notify("Usage: /
|
|
567
|
+
if (token) { ctx.ui.notify("Usage: /pinote", "warning"); return; }
|
|
568
568
|
if (pending || menuPending) {
|
|
569
569
|
ctx.ui.notify("Wait until the pinote operation has finished.", "warning");
|
|
570
570
|
return;
|
|
@@ -724,7 +724,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
724
724
|
const canRun = () => alive && generation === epoch && branch === branchEpoch && selectedId === id;
|
|
725
725
|
const current = await selected(ctx, signal);
|
|
726
726
|
if (!canRun()) throw new Error("Pinote operation cancelled: the session or selected task changed.");
|
|
727
|
-
if (!current) throw new Error("No selected pinote task. Select one with /
|
|
727
|
+
if (!current) throw new Error("No selected pinote task. Select one with /pinote first.");
|
|
728
728
|
const argv = ["agent", "update", String(current.id), "--expected-updated-at", params.expected_updated_at,
|
|
729
729
|
"--set-json", JSON.stringify(params.set ?? {})];
|
|
730
730
|
for (const label of params.remove ?? []) argv.push(`--remove=${label}`);
|
|
@@ -789,7 +789,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
789
789
|
return true;
|
|
790
790
|
} catch (error) {
|
|
791
791
|
if (alive && generation === epoch) ctx.ui.notify(
|
|
792
|
-
`Pinote suggestion: ${clean(String(error))}${created ? ` Note #${created.id} was created; use /
|
|
792
|
+
`Pinote suggestion: ${clean(String(error))}${created ? ` Note #${created.id} was created; use /pinote to select it. Do not add it again.` : " A write may have committed; check /pinote before retrying."}`, "error");
|
|
793
793
|
return false;
|
|
794
794
|
} finally {
|
|
795
795
|
if (pending === operation) pending = undefined;
|
|
@@ -854,10 +854,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
854
854
|
clearSuggestion(ctx);
|
|
855
855
|
try {
|
|
856
856
|
const created = requiredTask(await run(argv, signal, canAct, "0.4.0"));
|
|
857
|
-
if (!canAct()) throw new Error("Pinote operation cancelled: the session changed. The note was created; check /
|
|
857
|
+
if (!canAct()) throw new Error("Pinote operation cancelled: the session changed. The note was created; check /pinote before retrying.");
|
|
858
858
|
const chosen = await startTask(created.id, canAct, signal);
|
|
859
859
|
if (!chosen || !alive || generation !== epoch || branch !== branchEpoch || selectedId !== chosen.id) {
|
|
860
|
-
throw new Error("Pinote operation cancelled: the session changed. The note may have started; check /
|
|
860
|
+
throw new Error("Pinote operation cancelled: the session changed. The note may have started; check /pinote before retrying.");
|
|
861
861
|
}
|
|
862
862
|
return toolResult(chosen);
|
|
863
863
|
} finally {
|
package/package.json
CHANGED
package/remote.ts
CHANGED
|
@@ -35,7 +35,6 @@ export default function pinoteRemote(pi: ExtensionAPI): void {
|
|
|
35
35
|
await ui.open(ctx);
|
|
36
36
|
};
|
|
37
37
|
pi.registerCommand('pinote', { description: 'Open remote Pinote tasks and settings', handler: open });
|
|
38
|
-
pi.registerCommand('pi-note', { description: 'Open remote Pinote (compatibility alias)', handler: open });
|
|
39
38
|
const start = async (ctx: ExtensionContext, reason?: string, previous?: string) => {
|
|
40
39
|
const request = launchRequest; launchRequest = undefined; // Never replay an uncertain start.
|
|
41
40
|
ui?.detach(); await session?.stop();
|
package/setup.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { stripVTControlCharacters } from "node:util";
|
|
|
4
4
|
// Immutable source: the Python app is not yet published to PyPI.
|
|
5
5
|
export const cliSource = "https://github.com/kvidzibo/pinote/archive/1597baf60bff8bc96893be40781f152a001623d1.tar.gz";
|
|
6
6
|
export const bundledCLIVersion = "0.4.0";
|
|
7
|
-
export const setupHint = "Open /
|
|
7
|
+
export const setupHint = "Open /pinote → Settings to install or upgrade the CLI; note must be on PATH.";
|
|
8
8
|
export type CLIAction = "setup" | "upgrade" | "ready";
|
|
9
9
|
|
|
10
10
|
export function cliAction(version: string): CLIAction {
|
|
@@ -51,10 +51,10 @@ export async function setupCLI(
|
|
|
51
51
|
const action = await detectCLI(pi, signal);
|
|
52
52
|
if (!canAct() || signal.aborted) return;
|
|
53
53
|
if (action === "ready") {
|
|
54
|
-
ctx.ui.notify(`Pinote CLI is ready (bundled version ${bundledCLIVersion} or newer). Use /
|
|
54
|
+
ctx.ui.notify(`Pinote CLI is ready (bundled version ${bundledCLIVersion} or newer). Use /pinote.`, "info");
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
const command = `/
|
|
57
|
+
const command = `/pinote → Settings → ${action === "upgrade" ? "Upgrade CLI" : "Install CLI"}`;
|
|
58
58
|
if (upgrade !== (action === "upgrade")) {
|
|
59
59
|
ctx.ui.notify(`Use ${command} ${action === "upgrade" ? "to upgrade the older CLI" : "to install the missing CLI"}.`, "info");
|
|
60
60
|
return;
|
|
@@ -88,7 +88,7 @@ export async function setupCLI(
|
|
|
88
88
|
try {
|
|
89
89
|
const version = await exec("note", ["--version"]);
|
|
90
90
|
if (version.killed || version.code !== 0 || cliAction(version.stdout) !== "ready") throw new Error("note unavailable or older than bundled CLI");
|
|
91
|
-
if (canAct()) ctx.ui.notify(`${clean(version.stdout.trim())} is ready. Use /
|
|
91
|
+
if (canAct()) ctx.ui.notify(`${clean(version.stdout.trim())} is ready. Use /pinote. GTK is optional and installed separately.`, "info");
|
|
92
92
|
} catch {
|
|
93
93
|
if (canAct()) ctx.ui.notify("Pinote installed, but note on PATH is missing or older than the bundled CLI. Run uv tool dir --bin in your terminal, add that directory to PATH before older note executables, then restart Pi.", "warning");
|
|
94
94
|
}
|