feat(pi-notifications): add PI_NOTIFICATION_DEBUG mode with visible steer signal

- Add PI_NOTIFICATION_DEBUG=true env var
- When enabled, calls ctx.ui.steer() instead of desktop notification
- Lets you verify trigger logic in the agent loop without actual notifications
- Synced to both monorepo and auto-discovery extension paths
This commit is contained in:
2026-04-28 12:09:06 +01:00
parent ce4d6c5971
commit 45a13fd08c
6 changed files with 265 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
// Desktop notifications for pi agent events
// Uses osascript (macOS) to trigger Notification Center alerts
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { execSync } from "node:child_process";
// Configuration via environment variables
const enabled = process.env.PI_NOTIFICATIONS_ENABLED !== "false";
const agentEndEnabled = process.env.PI_NOTIFICATION_AGENT_END !== "false";
const debug = process.env.PI_NOTIFICATION_DEBUG === "true";
const title = process.env.PI_NOTIFICATION_TITLE || "pi";
const sound = process.env.PI_NOTIFICATION_SOUND || "default";
function notify(body: string, subtitle?: string): void {
if (!enabled) return;
try {
const sub = subtitle ? `subtitle "${subtitle}"` : "";
const snd = sound ? `sound "${sound}"` : "";
execSync(
`osascript -e 'display notification "${body}" with title "${title}" ${sub} ${snd}'`.trim(),
{ stdio: "ignore" }
);
} catch {
// osascript not available (non-macOS) — silently fail
}
}
export default function (pi: ExtensionAPI) {
console.log("[pi-notifications] loaded (enabled=" + enabled + ", agentEnd=" + agentEndEnabled + ")");
pi.on("session_start", async (_event, ctx) => {
if (debug) {
ctx.ui.steer("[pi-notifications] session_start — debug mode, skipping actual notification");
return;
}
if (enabled) {
notify("pi-notifications active", "Listening for agent_end");
}
});
pi.on("agent_end", async (event, ctx) => {
if (!agentEndEnabled) return;
if (debug) {
ctx.ui.steer(`[pi-notifications] agent_end — debug mode, skipping actual notification (${event.messages?.length ?? 0} messages)`);
return;
}
console.log(`[pi-notifications] agent_end: messages=${JSON.stringify(event.messages?.map((m: any) => m.type))}`);
notify("Agent finished", `${event.messages?.length ?? 0} turns`);
});
}