feat: engine audio mute support — hooks.json audio tag + engine skips muted hooks

This commit is contained in:
AIOSAI
2026-05-22 18:10:03 -07:00
parent 40eb295e41
commit 2215fcb260
3 changed files with 16 additions and 4 deletions
+4
View File
@@ -10,6 +10,7 @@
},
"email_notification": {
"enabled": true,
"audio": true,
"handler": "aipass.hooks.apps.handlers.notification.email.handle",
"matcher": ""
},
@@ -28,6 +29,7 @@
"PreToolUse": {
"tool_use_sound": {
"enabled": true,
"audio": true,
"handler": "aipass.hooks.apps.handlers.notification.tool_sound.handle",
"matcher": "Bash|Edit|MultiEdit|Write|Read|Grep|Glob|WebSearch|WebFetch|Task"
},
@@ -74,6 +76,7 @@
"Stop": {
"stop_sound": {
"enabled": true,
"audio": true,
"handler": "aipass.hooks.apps.handlers.notification.stop_sound.handle",
"matcher": ""
}
@@ -82,6 +85,7 @@
"Notification": {
"notification_sound": {
"enabled": true,
"audio": true,
"handler": "aipass.hooks.apps.handlers.notification.announce.handle",
"matcher": ""
}
+6 -4
View File
@@ -27,10 +27,12 @@ versioned release with notes.
can enable, disable, or customize individual hooks without touching
provider-level settings. Previously hooks fired globally with no
per-project control.
- **Audio feedback on hook events** using Piper TTS. Tool usage, response
completion, notifications, email alerts, and sub-agent activity each
produce distinct spoken audio cues so operators can monitor sessions
without watching the terminal.
- **Audio feedback on hook events** using Piper TTS (muted by default).
Tool usage, response completion, notifications, email alerts, and
sub-agent activity each produce distinct spoken audio cues so operators
can monitor sessions without watching the terminal. Toggle with
`drone hook-sounds on|off`. Audio hooks are tagged `"audio": true` in
`.aipass/hooks.json` and the engine skips them when muted.
- **Hooks agent** — the 13th citizen in the AIPass registry, owning all
hook infrastructure: the engine, bridge, handlers, and configuration
schema.
+6
View File
@@ -108,12 +108,18 @@ def dispatch(event_type: str, stdin_data: str, config: dict) -> str:
outputs = []
total_start = time.monotonic()
muted = Path("/tmp/aipass-hooks-muted").exists()
for hook_name, hook_def in event_hooks.items():
if not hook_def.get("enabled", True):
logger.info("[HOOKS] %s.%s skipped (disabled)", event_type, hook_name)
_log({"ts": time.time(), "event": event_type, "hook": hook_name, "action": "skipped_disabled"})
continue
if muted and hook_def.get("audio"):
_log({"ts": time.time(), "event": event_type, "hook": hook_name, "action": "skipped_muted"})
continue
handler = hook_def.get("handler", "")
command = hook_def.get("command", "")
matcher = hook_def.get("matcher", "")