fix(notifications): suppress permission notifs when session auto-accepts

Server now mirrors client-side Permission Auto-Accept via
POST /api/notifications/auto-accept and short-circuits permission.asked
dispatch (walking the session parent chain). Prior 500ms debounce raced
the client auto-response and leaked notifications.

Also hint under Summarize Last Message that templates must contain
{last_message} for the setting to take effect.
This commit is contained in:
Bohdan Triapitsyn
2026-04-22 19:22:50 +03:00
parent 1ad64cc69e
commit a2730b793e
7 changed files with 91 additions and 0 deletions
@@ -786,6 +786,11 @@ export const NotificationSettings: React.FC = () => {
/>
<span className="typography-ui-label text-foreground">Summarize Last Message</span>
</div>
<div className="pl-6 pb-1">
<span className="typography-meta text-muted-foreground">
Requires <code className="text-[var(--primary-base)]">{'{last_message}'}</code> in the notification template.
</span>
</div>
<div className={cn("flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8")}>
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
+24
View File
@@ -169,6 +169,15 @@ export const usePermissionStore = create<PermissionStore>()(
return { autoAccept };
});
// Mirror state to the server so it can suppress permission
// notifications at the source (otherwise the 500ms debounce
// races with the client's auto-response and can leak).
void fetch('/api/notifications/auto-accept', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionId, enabled }),
}).catch(() => { /* best-effort */ });
if (!enabled) {
return;
}
@@ -260,6 +269,21 @@ export const usePermissionStore = create<PermissionStore>()(
autoAccept: nextAutoAccept,
};
},
onRehydrateStorage: () => (state) => {
if (!state) return;
// Re-broadcast auto-accept state to the server after
// rehydration so server-side notification suppression
// survives page reloads / server restarts.
for (const [sid, enabled] of Object.entries(state.autoAccept || {})) {
if (enabled === true) {
void fetch('/api/notifications/auto-accept', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sessionId: sid, enabled: true }),
}).catch(() => { /* best-effort */ });
}
}
},
}
),
{ name: "permission-store" }