@pi-archimedes/notify 2.8.0 → 2.9.1

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 CHANGED
@@ -29,9 +29,9 @@ After installing Pi, choose one installation command above, then `cd` into your
29
29
  ## Triggers
30
30
 
31
31
  - **Settled runs** — on Pi's `agent_settled` event: the run has fully settled (no automatic retry, compaction, or queued continuation still to fire), not merely "a turn ended".
32
- - **Blocking prompts** — on `ui_prompt_start`: any extension prompt is waiting on you (a tabbed ask, a sudo password prompt, an MCP OAuth loader) — direct **or** subagent-relayed, since the event fires in the parent process.
32
+ - **Blocking prompts** — on `ui_prompt_start`: any extension prompt is waiting on you (a tabbed ask, a sudo password or command-confirm prompt) — direct **or** subagent-relayed, since the event fires in the parent process.
33
33
 
34
- The alert fires after a fixed `delayMs` (30 s by default) from the trigger. It is a delay, not an idle timer: nothing measures how long you've been reading. Any input in the terminal cancels pending alerts immediately, a new agent run cancels them, and a prompt that closes without you typing (say, the OAuth loader finishing from the browser) cancels its own timer — so a long-gone question can't ring.
34
+ The alert fires after a fixed `delayMs` (30 s by default) from the trigger. It is a delay, not an idle timer: nothing measures how long you've been reading. Any input in the terminal cancels pending alerts immediately, a new agent run cancels them, and a prompt that closes without you typing (say, a confirm dialog that times out and auto-declines) cancels its own timer — so a long-gone question can't ring.
35
35
 
36
36
  ## Terminal delivery
37
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-archimedes/notify",
3
- "version": "2.8.0",
3
+ "version": "2.9.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/danielcherubini/pi-archimedes.git"
@@ -18,15 +18,15 @@
18
18
  ".": "./src/index.ts"
19
19
  },
20
20
  "dependencies": {
21
- "@pi-archimedes/core": "2.8.0"
21
+ "@pi-archimedes/core": "2.9.1"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "@earendil-works/pi-coding-agent": ">=0.84.4",
25
25
  "@earendil-works/pi-tui": ">=0.1.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@earendil-works/pi-coding-agent": "^0.85.1",
29
- "@earendil-works/pi-tui": "^0.85.1",
28
+ "@earendil-works/pi-coding-agent": "^0.87.0",
29
+ "@earendil-works/pi-tui": "^0.87.0",
30
30
  "typescript": "^6.0.0"
31
31
  },
32
32
  "pi": {
package/src/index.ts CHANGED
@@ -66,7 +66,7 @@ export function notifyOSC9(message: string): void {
66
66
  /** OSC 99 — Kitty terminal */
67
67
  export function notifyOSC99(title: string, body: string): void {
68
68
  const seq1 = `\x1b]99;i=1:d=0;${title}\x1b\\`;
69
- const seq2 = `\x1b]99;i=1:p=${body}\x1b\\`;
69
+ const seq2 = `\x1b]99;i=1:p=body;${body}\x1b\\`;
70
70
  process.stderr.write(wrapForTmux(seq1));
71
71
  process.stderr.write(wrapForTmux(seq2));
72
72
  }
@@ -185,16 +185,16 @@ function fireNotification(trigger: TriggerType | null): void {
185
185
  /** Register the notify extension with the Pi agent. */
186
186
  export function registerNotify(pi: ExtensionAPI): void {
187
187
  pi.on("agent_settled", () => scheduleNotify(TRIGGER.AGENT_SETTLED));
188
- // Any blocking extension UI prompt (ask, sudo, mcp OAuth) — fires in the
188
+ // Any blocking extension UI prompt (ask, sudo) — fires in the
189
189
  // parent process for direct and subagent-relayed prompts alike.
190
190
  pi.on("ui_prompt_start", (_event) => scheduleNotify(TRIGGER.UI_PROMPT));
191
191
  pi.on("input", () => cancelPending());
192
192
  pi.on("before_agent_start", () => cancelPending());
193
193
  pi.on("agent_start", () => cancelPending());
194
- // A prompt that closes without terminal input (e.g. the mcp OAuth
195
- // loader finishing from the browser's `done()`) cancels the question
196
- // timer so a long-gone prompt does not fire a stale "question needs
197
- // your answer". Scoped so it never wipes a pending "task complete" timer.
194
+ // A prompt that closes without terminal input (e.g. a ctx.ui.confirm
195
+ // that times out and auto-declines) cancels the question timer so a
196
+ // long-gone prompt does not fire a stale "question needs your answer".
197
+ // Scoped so it never wipes a pending "task complete" timer.
198
198
  pi.on("ui_prompt_end", () => {
199
199
  if (pendingTrigger === TRIGGER.UI_PROMPT) {
200
200
  cancelPending();
@@ -0,0 +1,21 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { notifyOSC99 } from "./index.js";
3
+
4
+ describe("notifyOSC99", () => {
5
+ afterEach(() => {
6
+ vi.restoreAllMocks();
7
+ vi.unstubAllEnvs();
8
+ });
9
+
10
+ it("emits the body text as the OSC 99 body payload, not as the payload type", () => {
11
+ vi.stubEnv("TMUX", "");
12
+ const write = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
13
+
14
+ notifyOSC99("Pi", "Task complete — waiting for input");
15
+
16
+ expect(write.mock.calls.map(([chunk]) => chunk)).toEqual([
17
+ "\x1b]99;i=1:d=0;Pi\x1b\\",
18
+ "\x1b]99;i=1:p=body;Task complete — waiting for input\x1b\\",
19
+ ]);
20
+ });
21
+ });