73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
/**
|
|
* Pi Done Notify Extension
|
|
*
|
|
* Sends a notification when Pi finishes a prompt.
|
|
* If on SSH/remote, SSHs back to Linux PC to play sound + show notification.
|
|
*/
|
|
|
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
|
|
// ============ CONFIGURATION ============
|
|
const REMOTE_HOST = "linux-pc"; // SSH host for remote notifications
|
|
const REMOTE_COMMAND = "paplay /usr/share/sounds/freedesktop/stereo/window-attention.oga & notify-send -i ~/.pi/agent/extensions/assets/pi-logo.svg 'Pi' 'Done. Ready for input.'";
|
|
const LOCAL_SOUND_MAC = "/System/Library/Sounds/Glass.aiff";
|
|
const LOCAL_SOUND_LINUX = "/usr/share/sounds/freedesktop/stereo/complete.oga";
|
|
// =======================================
|
|
|
|
function isSSH(): boolean {
|
|
if (process.env.SSH_CONNECTION || process.env.SSH_CLIENT || process.env.SSH_TTY) {
|
|
return true;
|
|
}
|
|
// Check for sshd-session process (works in tmux/zellij)
|
|
try {
|
|
const { execSync } = require("child_process");
|
|
const result = execSync("pgrep -u $USER -f sshd-session 2>/dev/null", {
|
|
encoding: "utf-8",
|
|
timeout: 1000,
|
|
});
|
|
return result.trim().length > 0;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function notifyRemote(): void {
|
|
const { exec } = require("child_process");
|
|
exec(`ssh -o ConnectTimeout=2 -o BatchMode=yes ${REMOTE_HOST} "${REMOTE_COMMAND}"`, { timeout: 5000 });
|
|
}
|
|
|
|
function notifyLocal(): void {
|
|
const { execFile, exec } = require("child_process");
|
|
if (process.platform === "darwin") {
|
|
execFile("afplay", [LOCAL_SOUND_MAC]);
|
|
} else if (process.platform === "linux") {
|
|
exec("paplay /usr/share/sounds/freedesktop/stereo/window-attention.oga & notify-send -i ~/.pi/agent/extensions/assets/pi-logo.svg 'Pi' 'Done. Ready for input.'");
|
|
}
|
|
}
|
|
|
|
function sendNotification(): void {
|
|
// On Mac or SSH session: notify remote Linux
|
|
// On Linux locally: notify local
|
|
if (process.platform === "darwin" || isSSH()) {
|
|
notifyRemote();
|
|
} else {
|
|
notifyLocal();
|
|
}
|
|
}
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
pi.on("agent_end", async (_event, ctx) => {
|
|
if (!ctx.hasUI) return;
|
|
sendNotification();
|
|
});
|
|
|
|
// Simple test command
|
|
pi.registerCommand("notify", {
|
|
description: "Test notification",
|
|
handler: async (_args, ctx) => {
|
|
sendNotification();
|
|
ctx.ui.notify("Notification sent!", "info");
|
|
},
|
|
});
|
|
}
|