pi-note 0.39.2 → 0.39.3
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 +11 -5
- package/dist-mcp/mcp/core.js +1 -1
- package/mcp/core.ts +1 -1
- package/package.json +1 -1
- package/remote/ui.ts +6 -5
package/README.md
CHANGED
|
@@ -58,9 +58,10 @@ confirmation. **Clear selection** leaves its progress unchanged.
|
|
|
58
58
|
|
|
59
59
|
**Preview** opens a scrollable, read-only document. **Insert task prompt…** reviews
|
|
60
60
|
and inserts into an empty editor only; it never submits or replaces a draft.
|
|
61
|
-
Creation, suggestion acceptance and shared changes require complete review,
|
|
62
|
-
a separate Cancel-first confirmation. Menu completion also asks explicitly
|
|
63
|
-
|
|
61
|
+
Creation, menu suggestion acceptance and shared changes require complete review,
|
|
62
|
+
then a separate Cancel-first confirmation. Menu completion also asks explicitly.
|
|
63
|
+
Footer double-click directly approves suggestion acceptance or completion;
|
|
64
|
+
completion requires idle Pi. Failed or uncertain
|
|
64
65
|
writes offer refresh/verification, never automatic replay.
|
|
65
66
|
|
|
66
67
|
**Settings** groups prompts/guidance, task-offer policy, footer layout and field
|
|
@@ -73,7 +74,8 @@ Menus use Pi's native inline components, themes and configured selection keys.
|
|
|
73
74
|
Small terminals show compact menus or ask you to enlarge the window before acting.
|
|
74
75
|
Fullscreen has a clickable footer: **▤** opens Pinote; single-click a task title
|
|
75
76
|
to preview, or double-click to complete immediately without another confirmation
|
|
76
|
-
(requires idle Pi).
|
|
77
|
+
(requires idle Pi). Single-click a suggestion title to preview it; double-click
|
|
78
|
+
to accept, start and select it immediately without another confirmation.
|
|
77
79
|
Regular mode shows status; `/pinote` provides all actions. No Kitty action handler
|
|
78
80
|
is needed.
|
|
79
81
|
|
|
@@ -215,10 +217,14 @@ See [setup, script contract and safeguards](mcp/FIELD_EVENTS.md). Disabled by de
|
|
|
215
217
|
|
|
216
218
|
## Migration
|
|
217
219
|
|
|
220
|
+
Since pi-note 0.39.3, fullscreen suggestion-title double-click accepts immediately;
|
|
221
|
+
single-click still previews and menu acceptance still requires review/confirmation.
|
|
222
|
+
Update both client and service, then `/reload` Pi.
|
|
223
|
+
|
|
218
224
|
Since pi-note 0.39.2, fullscreen task-title double-click completes without another
|
|
219
225
|
confirmation; single-click still previews and menu completion still confirms.
|
|
220
226
|
Update the client and `/reload` Pi. The service must support footer double-click
|
|
221
|
-
(pi-note 0.39.1+).
|
|
227
|
+
(pi-note 0.39.1+).
|
|
222
228
|
|
|
223
229
|
Since pi-note 0.38.0, the default HTTP extension uses task-first navigation and
|
|
224
230
|
explicit completion/suggestion approval. Update the client and service together,
|
package/dist-mcp/mcp/core.js
CHANGED
|
@@ -264,7 +264,7 @@ function view(data, scoped = false, secondary = false, features = {}) {
|
|
|
264
264
|
if (task)
|
|
265
265
|
footer.push({ text: `${task.tag ? `[${task.tag}] ` : ''}${task.text.split('\n')[0].slice(0, 2000)}`, action: 'preview', ...(features.footerDoubleActions ? { doubleAction: 'done' } : {}), width: config.config.titleWidth });
|
|
266
266
|
else if (state.proposal)
|
|
267
|
-
footer.push({ text: `? ${suggestion.tag ? `[${suggestion.tag}] ` : ''}${suggestion.text.split('\n')[0].slice(0, 2000)}`, action: 'proposal:preview', ...(features.footerStyles ? { style: { italic: true, color: 'accent' } } : {}), width: config.config.titleWidth });
|
|
267
|
+
footer.push({ text: `? ${suggestion.tag ? `[${suggestion.tag}] ` : ''}${suggestion.text.split('\n')[0].slice(0, 2000)}`, action: 'proposal:preview', ...(features.footerDoubleActions ? { doubleAction: 'proposal:accept' } : {}), ...(features.footerStyles ? { style: { italic: true, color: 'accent' } } : {}), width: config.config.titleWidth });
|
|
268
268
|
else
|
|
269
269
|
footer.push({ text: 'Pinote · No task', width: config.config.titleWidth });
|
|
270
270
|
}
|
package/mcp/core.ts
CHANGED
|
@@ -229,7 +229,7 @@ function view(data: Snapshot, scoped = false, secondary = false, features: { foo
|
|
|
229
229
|
: [{ text: `${icons.note} `, width: 3 }];
|
|
230
230
|
if (features.footerNativeActions) {
|
|
231
231
|
if (task) footer.push({ text: `${task.tag ? `[${task.tag}] ` : ''}${task.text.split('\n')[0].slice(0, 2000)}`, action: 'preview', ...(features.footerDoubleActions ? { doubleAction: 'done' } : {}), width: config.config.titleWidth });
|
|
232
|
-
else if (state.proposal) footer.push({ text: `? ${suggestion!.tag ? `[${suggestion!.tag}] ` : ''}${suggestion!.text.split('\n')[0].slice(0, 2000)}`, action: 'proposal:preview', ...(features.footerStyles ? { style: { italic: true, color: 'accent' } as const } : {}), width: config.config.titleWidth });
|
|
232
|
+
else if (state.proposal) footer.push({ text: `? ${suggestion!.tag ? `[${suggestion!.tag}] ` : ''}${suggestion!.text.split('\n')[0].slice(0, 2000)}`, action: 'proposal:preview', ...(features.footerDoubleActions ? { doubleAction: 'proposal:accept' } : {}), ...(features.footerStyles ? { style: { italic: true, color: 'accent' } as const } : {}), width: config.config.titleWidth });
|
|
233
233
|
else footer.push({ text: 'Pinote · No task', width: config.config.titleWidth });
|
|
234
234
|
} else if (task) {
|
|
235
235
|
footer.push({ text: `${icons.check} `, action: 'done', width: 3 });
|
package/package.json
CHANGED
package/remote/ui.ts
CHANGED
|
@@ -43,8 +43,9 @@ export class RemoteUI {
|
|
|
43
43
|
if (this.opening || this.acting) return false;
|
|
44
44
|
if (item.openApp) { await this.open(ctx); return true; }
|
|
45
45
|
const control = view.controls.find((c) => c.id === action && c.kind === 'action');
|
|
46
|
-
//
|
|
47
|
-
|
|
46
|
+
// Deliberate footer double-click approves completion or suggestion acceptance.
|
|
47
|
+
const approved = (action === 'done' || action === 'proposal:accept') && item.doubleAction === action;
|
|
48
|
+
return control ? this.dispatch(ctx, view, control, undefined, approved) : false;
|
|
48
49
|
}, this.repaint);
|
|
49
50
|
}, { placement: 'belowEditor' });
|
|
50
51
|
this.render();
|
|
@@ -66,7 +67,7 @@ export class RemoteUI {
|
|
|
66
67
|
}) : 'Pinote · unavailable (/pinote to reconnect)');
|
|
67
68
|
this.repaint();
|
|
68
69
|
}
|
|
69
|
-
async dispatch(ctx: ExtensionContext, view: NativeView, control: NativeControl, value?: NativeControl['value'],
|
|
70
|
+
async dispatch(ctx: ExtensionContext, view: NativeView, control: NativeControl, value?: NativeControl['value'], footerConfirmed = false): Promise<boolean> {
|
|
70
71
|
if (ctx.mode !== 'tui') throw new Error('Pinote UI actions require TUI mode');
|
|
71
72
|
if (this.acting) return false;
|
|
72
73
|
if (control.id === 'done' && !ctx.isIdle()) {
|
|
@@ -76,14 +77,14 @@ export class RemoteUI {
|
|
|
76
77
|
const current = this.session.current(), signal = this.session.signal;
|
|
77
78
|
try {
|
|
78
79
|
if (typeof value === 'string') editorText(value);
|
|
79
|
-
if (control.id === 'done' && !
|
|
80
|
+
if (control.id === 'done' && !footerConfirmed) {
|
|
80
81
|
const exits = typeof view.state.selectedId === 'number' && this.exitOnComplete(view.state.selectedId);
|
|
81
82
|
const accept = exits ? 'Complete task and exit' : 'Complete task';
|
|
82
83
|
const summary = truncateToWidth(line(view.body ?? ''), 100);
|
|
83
84
|
if (await ctx.ui.select(`Pinote / ${accept} #${view.state.selectedId}\n${summary}\n${exits ? 'Closes this dedicated Pi session.' : 'Clears selection; keeps this conversation and editor.'}`,
|
|
84
85
|
['Cancel', accept], { signal }) !== accept) return false;
|
|
85
86
|
}
|
|
86
|
-
if (control.confirm) {
|
|
87
|
+
if (control.confirm && !(footerConfirmed && control.id === 'proposal:accept')) {
|
|
87
88
|
const details = control.kind === 'action' ? control.confirm : `${control.confirm}\n\n${control.id === 'add' || control.id === 'add-field' ? '' : `Before:\n${disclosure(control.value)}\n\n`}After:\n${disclosure(value)}`;
|
|
88
89
|
const accept = control.id === 'add' ? 'Create, start and select' : control.id === 'proposal:accept' ? 'Accept suggestion' :
|
|
89
90
|
control.id === 'remove-field' ? 'Remove display field' : control.id === 'add-field' ? 'Add field' : 'Save change';
|