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:
@@ -0,0 +1,38 @@
|
||||
# pi-notifications
|
||||
|
||||
Desktop notifications for pi agent events via macOS Notification Center.
|
||||
|
||||
## What it does
|
||||
|
||||
Shows a system notification when the agent finishes a turn, so you can step away and get alerted when input is needed.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Env var | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `PI_NOTIFICATIONS_ENABLED` | `true` | Set to `false` to disable all notifications |
|
||||
| `PI_NOTIFICATION_AGENT_END` | `true` | Notification when agent finishes |
|
||||
| `PI_NOTIFICATION_TITLE` | `pi` | Notification title |
|
||||
| `PI_NOTIFICATION_SOUND` | `default` | macOS sound (Bottle, Ping, Pop, etc.) or `""` for silent |
|
||||
|
||||
## Usage
|
||||
|
||||
Add to `~/.pi/agent/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"packages": [
|
||||
"/path/to/packages/pi-notifications"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Then reload pi:
|
||||
|
||||
```bash
|
||||
/reload
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "pi-notifications",
|
||||
"version": "0.1.0",
|
||||
"description": "Desktop notifications for pi agent events",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"keywords": ["pi-package"],
|
||||
"pi": {
|
||||
"extensions": ["src/index.ts"]
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mariozechner/pi-coding-agent": "*"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
@@ -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`);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user