From 9c93086c0d4acaa1ed753488b12f72c2ca86a22c Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Mon, 1 Jun 2026 10:12:11 +0900 Subject: feat(notifications): add notifySubagents toggle to suppress subagent turn pings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A parent agent that spawns 8 subagents was producing 9 "Turn complete" notifications per round — almost always noise. New `notifySubagents` config flag (defaults to false) gates `turn-completed` and `turn-error` from any tab with a `parentTabId`. The flag is intentionally NOT applied to `permission-required` — a subagent's permission prompt still needs a human tap to proceed, so suppressing it would silently hang the subagent. `agent-spawned` is already top-level-only by construction. Wiring: - core/notifications/types.ts: NtfyConfig.notifySubagents: boolean - core/notifications/config.ts: defaults to false; normalize() tolerates missing / wrong-typed values and falls back to false - core/notifications/dispatcher.ts: new optional TabParentLookup option (getTabParentId). When notifySubagents=false AND the lookup returns a non-empty parent id string, turn-completed/turn-error are dropped. Lookup failures (no lookup configured, throws, returns undefined) fall back to "treat as top-level" so legitimate top-level events are never silently dropped when the DB is briefly unreadable. - api/app.ts: wires getTabParentId via core's getTab(id)?.parentTabId - frontend SettingsPanel.svelte: "Include subagent tabs" checkbox with an explanatory hint that permission prompts still fire Tests (+9): - 3 in config.test.ts: default-false, explicit-true, wrong-typed fallback - 6 in dispatcher.test.ts: suppression of turn-completed/turn-error from subagents, no suppression when flag is true, permission-required not gated, graceful fallback when lookup is missing/throws/returns undefined Live ntfy.sh round-trip re-verified (status: 200). --- packages/api/src/app.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'packages/api/src/app.ts') diff --git a/packages/api/src/app.ts b/packages/api/src/app.ts index 24cef24..0dabb0d 100644 --- a/packages/api/src/app.ts +++ b/packages/api/src/app.ts @@ -24,6 +24,17 @@ export const notificationDispatcher = new NotificationDispatcher({ return null; } }, + getTabParentId: (tabId) => { + try { + // `undefined` when the lookup fails (tab not found / DB unavailable) + // so the dispatcher falls back to "treat as top-level" rather than + // silently dropping notifications. + const row = getTab(tabId); + return row ? row.parentTabId : undefined; + } catch { + return undefined; + } + }, }); notificationDispatcher.attachToAgentManager(agentManager); notificationDispatcher.attachToPermissionManager(permissionManager); -- cgit v1.2.3