pi-note 0.33.3 → 0.33.4
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 +5 -12
- package/package.json +1 -1
- package/remote/exit.ts +2 -38
- package/remote/ui.ts +2 -5
- package/remote.ts +1 -1
package/README.md
CHANGED
|
@@ -90,20 +90,13 @@ client-local and is never sent to the service or persisted as launch state.
|
|
|
90
90
|
Only a fresh session can consume it. The service must share the GUI's database;
|
|
91
91
|
missing/stale revisions fail closed. Resume, reload and `/new` never replay the
|
|
92
92
|
handoff or replace another selection. Pi keeps its normal endpoint/token settings.
|
|
93
|
-
With pi-note 0.33.
|
|
94
|
-
**Complete task and exit**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
If Git fails, times out (30 seconds), or the session/draft changes, Pi stays open;
|
|
98
|
-
the task remains completed and is not retried. Check Git manually, then `/quit`.
|
|
99
|
-
With pi-note 0.33.3+, directories outside Git, repositories without remotes, and
|
|
100
|
-
branches without a configured upstream skip the pull and exit without a warning.
|
|
101
|
-
Broken Git configuration, detached HEAD in a remote-backed repository, and failures
|
|
102
|
-
to pull a configured upstream still keep Pi open.
|
|
103
|
-
`/quit` and Exit without completing do not pull.
|
|
93
|
+
With pi-note 0.33.4+, completing the launched task from the menu, footer or
|
|
94
|
+
**Complete task and exit** exits Pi directly, so Kitty closes its dedicated tab
|
|
95
|
+
(or the standalone window's last tab). Completion never runs Git commands;
|
|
96
|
+
Git configuration and network availability do not affect closing the session.
|
|
104
97
|
This ownership survives `/reload`, but not `/new`, resume, fork, tree navigation
|
|
105
98
|
or process restart. Completing a different task or an externally completed task
|
|
106
|
-
does not
|
|
99
|
+
does not close Pi; failed/uncertain completion stays open.
|
|
107
100
|
|
|
108
101
|
### Agent tools and context
|
|
109
102
|
|
package/package.json
CHANGED
package/remote/exit.ts
CHANGED
|
@@ -1,43 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CustomEditor, type ExtensionAPI, type ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
1
|
+
import { CustomEditor, type ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
3
2
|
import { truncateToWidth } from '@earendil-works/pi-tui';
|
|
4
3
|
import { clean } from './protocol.ts';
|
|
5
4
|
import type { RemoteSession } from './session.ts';
|
|
6
5
|
|
|
7
|
-
/** Completion is already committed: pull failures must never retry the task action. */
|
|
8
|
-
export async function pullBeforeExit(pi: ExtensionAPI, ctx: ExtensionContext, signal: AbortSignal, current: () => boolean): Promise<boolean> {
|
|
9
|
-
const sessionId = ctx.sessionManager.getSessionId(), branch = ctx.sessionManager.getLeafId();
|
|
10
|
-
const draft = ctx.ui.getEditorText();
|
|
11
|
-
const unchanged = () => current() && !signal.aborted && ctx.isIdle() &&
|
|
12
|
-
ctx.sessionManager.getSessionId() === sessionId && ctx.sessionManager.getLeafId() === branch && ctx.ui.getEditorText() === draft;
|
|
13
|
-
if (!unchanged()) return false;
|
|
14
|
-
try {
|
|
15
|
-
const git = (args: string[]) => spawnSync('git', args, {
|
|
16
|
-
cwd: ctx.cwd, encoding: 'utf8', timeout: 3000, env: { ...process.env, LC_ALL: 'C' },
|
|
17
|
-
});
|
|
18
|
-
const repository = git(['rev-parse', '--show-toplevel']);
|
|
19
|
-
if (!repository.error && repository.status === 128 && repository.stderr.startsWith('fatal: not a git repository (or any ')) return unchanged();
|
|
20
|
-
if (repository.error || repository.status !== 0 || !unchanged()) throw new Error('Git repository check failed');
|
|
21
|
-
const remotes = git(['remote']);
|
|
22
|
-
if (remotes.error || remotes.status !== 0) throw new Error('Git remote check failed');
|
|
23
|
-
if (!remotes.stdout.trim()) return unchanged();
|
|
24
|
-
const branch = git(['symbolic-ref', '--quiet', 'HEAD']);
|
|
25
|
-
if (branch.error || branch.status !== 0 || !branch.stdout.startsWith('refs/heads/')) throw new Error('Git branch check failed');
|
|
26
|
-
const branchName = branch.stdout.trim().slice('refs/heads/'.length);
|
|
27
|
-
const upstream = git(['config', '--get', `branch.${branchName}.merge`]);
|
|
28
|
-
if (upstream.error || (upstream.status !== 0 && upstream.status !== 1)) throw new Error('Git upstream check failed');
|
|
29
|
-
if (upstream.status === 1) return unchanged();
|
|
30
|
-
if (!upstream.stdout.trim() || !unchanged()) throw new Error('Git upstream or session changed');
|
|
31
|
-
ctx.ui.notify('Task completed. Running git pull --ff-only before closing Pi…', 'info');
|
|
32
|
-
const result = await pi.exec('git', ['pull', '--ff-only', '--no-rebase', '--no-autostash'], { cwd: ctx.cwd, signal, timeout: 30_000 });
|
|
33
|
-
if (result.code === 0 && !result.killed && unchanged()) return true;
|
|
34
|
-
} catch { /* Completion succeeded; only the local pull failed. */ }
|
|
35
|
-
if (current()) ctx.ui.notify('Task completed, but Pi stayed open: git pull failed or the session changed. Check Git manually, then /quit. Completion will not be retried.', 'warning');
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
6
|
/** Default remote companion. /quit and nonempty-editor exit input remain Pi-owned. */
|
|
40
|
-
export function registerRemoteExit(pi: ExtensionAPI, getSession: () => RemoteSession | undefined
|
|
7
|
+
export function registerRemoteExit(pi: ExtensionAPI, getSession: () => RemoteSession | undefined): void {
|
|
41
8
|
let invalidate: (() => void) | undefined;
|
|
42
9
|
let stop: (() => void) | undefined;
|
|
43
10
|
let confirm: ((reason: 'exit' | 'new') => Promise<boolean>) | undefined;
|
|
@@ -88,9 +55,6 @@ export function registerRemoteExit(pi: ExtensionAPI, getSession: () => RemoteSes
|
|
|
88
55
|
await session.action(view, done, undefined, () => current() && ctx.isIdle() && ctx.sessionManager.getLeafId() === branch);
|
|
89
56
|
if (!current()) return false;
|
|
90
57
|
if (session.view && session.view.state.selectedId == null) {
|
|
91
|
-
if (reason === 'exit' && typeof view.state.selectedId === 'number' && ownsLaunch(view.state.selectedId)) {
|
|
92
|
-
return await pullBeforeExit(pi, ctx, operation.signal, current);
|
|
93
|
-
}
|
|
94
58
|
return true;
|
|
95
59
|
}
|
|
96
60
|
ctx.ui.notify('Pinote: Pi stayed in this session because the selection was not cleared. Refresh /pinote before retrying.', 'warning');
|
package/remote/ui.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { NativeFooter } from './footer.ts';
|
|
|
4
4
|
import { clean, cleanUnbounded, editorText, footerText, literal, type NativeControl, type NativeView } from './protocol.ts';
|
|
5
5
|
import { RemoteFailure } from './client.ts';
|
|
6
6
|
import { RemoteSession } from './session.ts';
|
|
7
|
-
import { pullBeforeExit } from './exit.ts';
|
|
8
7
|
import { inlineHeight, remoteMenu, type MenuState } from './menu.ts';
|
|
9
8
|
|
|
10
9
|
const line = (text: string) => clean(text).replace(/\n/g, ' ');
|
|
@@ -114,10 +113,8 @@ export class RemoteUI {
|
|
|
114
113
|
if (!current()) return false;
|
|
115
114
|
if (control.id === 'done' && ctx.isIdle() && typeof view.state.selectedId === 'number' &&
|
|
116
115
|
this.session.view && this.session.view.state.selectedId == null && this.exitOnComplete(view.state.selectedId)) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
ctx.shutdown();
|
|
120
|
-
}
|
|
116
|
+
this.closing = true;
|
|
117
|
+
ctx.shutdown();
|
|
121
118
|
return true;
|
|
122
119
|
}
|
|
123
120
|
if (result.preview) this.pi.appendEntry('pinote-remote-preview', { title: line(view.title), text: clean(result.preview) });
|
package/remote.ts
CHANGED
|
@@ -112,5 +112,5 @@ export default function pinoteRemote(pi: ExtensionAPI): void {
|
|
|
112
112
|
(char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`),
|
|
113
113
|
].join('\n\n');
|
|
114
114
|
});
|
|
115
|
-
registerRemoteExit(pi, () => session
|
|
115
|
+
registerRemoteExit(pi, () => session);
|
|
116
116
|
}
|