// 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"; const targetApp = process.env.PI_NOTIFICATION_APP || "Ghostty"; // "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}"` : ""; function tryNotify(tellApp: string): string { const cmd = `osascript -e 'tell application "${tellApp}" to display notification "Test notification from pi-notifications" with title "${title}" ${soundArg}'`.trim(); return cmd; } function tryPlainNotify(): string { const cmd = `osascript -e 'display notification "Test notification from pi-notifications" with title "${title}" ${soundArg}'`.trim(); return cmd; } let cmd = tryNotify(targetApp); let success = false; let lastError: string | undefined; // Try telling the target app first, fall back to plain display notification for (const attempt of [ { cmd: tryNotify(targetApp), label: `tell "${targetApp}"` }, { cmd: tryPlainNotify(), label: "plain" }, ]) { try { console.log(`[test-notify] trying ${attempt.label}:`, attempt.cmd); execSync(attempt.cmd, { stdio: ["ignore", "pipe", "pipe"] }); success = true; break; } catch (e: any) { lastError = e.message; console.log(`[test-notify] ${attempt.label} failed:`, e.message.split("\n")[0]); } } if (success) { console.log("[test-notify] ✅ Notification sent — check your Notification Center"); } else { console.error("[test-notify] ❌ Failed:", lastError); process.exit(1); }