From 383cb46fe738d35b822251301c74715c6a39774a Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Tue, 28 Apr 2026 12:10:30 +0100 Subject: [PATCH] feat(pi-notifications): add standalone test-notify.ts and fix AppleScript sound bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add packages/pi-notifications/src/test-notify.ts for isolated testing - Run with: node --input-type=module -e "import {createJiti} from ..." ./packages/pi-notifications/src/test-notify.ts - Decoupled from agent loop — verifies osascript in extension context - Fix: 'default' is a reserved word in AppleScript, skip sound param when sound='default' - Synced fix to auto-discovery extension path --- packages/pi-notifications/src/index.ts | 3 ++- packages/pi-notifications/src/test-notify.ts | 25 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packages/pi-notifications/src/test-notify.ts diff --git a/packages/pi-notifications/src/index.ts b/packages/pi-notifications/src/index.ts index 3fa5a42..38ab608 100644 --- a/packages/pi-notifications/src/index.ts +++ b/packages/pi-notifications/src/index.ts @@ -15,7 +15,8 @@ function notify(body: string, subtitle?: string): void { if (!enabled) return; try { const sub = subtitle ? `subtitle "${subtitle}"` : ""; - const snd = sound ? `sound "${sound}"` : ""; + // "default" is a reserved word in AppleScript, so only add sound param if it's a custom sound + const snd = sound && sound !== "default" ? `sound "${sound}"` : ""; execSync( `osascript -e 'display notification "${body}" with title "${title}" ${sub} ${snd}'`.trim(), { stdio: "ignore" } diff --git a/packages/pi-notifications/src/test-notify.ts b/packages/pi-notifications/src/test-notify.ts new file mode 100644 index 0000000..6d320b7 --- /dev/null +++ b/packages/pi-notifications/src/test-notify.ts @@ -0,0 +1,25 @@ +// Standalone notification tester — run from bash to verify osascript works +// Usage: npx jiti packages/pi-notifications/src/test-notify.ts +// +// This is completely decoupled from the agent loop. +// Use it to verify that the extension's notification machinery works +// before debugging event handler wiring. + +import { execSync } from "node:child_process"; + +const title = process.env.PI_NOTIFICATION_TITLE || "pi"; +const sound = process.env.PI_NOTIFICATION_SOUND || "default"; + +// "default" is a reserved word in AppleScript, so only add sound param if it's a custom sound +const soundArg = sound && sound !== "default" ? `sound "${sound}"` : ""; + +try { + const cmd = `osascript -e 'display notification "Test notification from pi-notifications" with title "${title}" ${soundArg}'`.trim(); + console.log("[test-notify] running:", cmd); + execSync(cmd, { stdio: ["ignore", "pipe", "pipe"] }); + console.log("[test-notify] ✅ Notification sent — check your Notification Center"); +} catch (e: any) { + console.error("[test-notify] ❌ Failed:", e.message); + console.error("[test-notify] Try running the command directly in bash to verify osascript works."); + process.exit(1); +}