Suppress OS notifications for subagent (child) sessions (#236)
This PR prevents OS notification spam from spawned subagent sessions by
skipping OS-level notifications for any session that is a child thread
(`parentId !== null`).
What changed
- `packages/ui/src/stores/session-events.ts`
- Added `isChildSession(...)` +
`shouldSendOsNotificationForSession(...)`
- Applied the check to OS notifications emitted from:
- `handleSessionIdle(...)`
- `handlePermissionUpdated(...)`
- `handleQuestionAsked(...)`
- If a session is not yet hydrated in the client store, we
conservatively *do not* emit an OS notification (avoids early subagent
spam).
Why
- Subagent sessions are represented as child sessions in the UI thread
model; OS notifications were previously emitted for all sessions
indiscriminately.
Testing
- Not run here: `bun run typecheck` fails in this environment due to
missing installed deps/types (e.g. `solid-js`).
Closes #228
--
Yours,
[CodeNomadBot](https://github.com/NeuralNomadsAI/CodeNomad)
Co-authored-by: Shantur Rathore <i@shantur.com>
This commit is contained in:
committed by
GitHub
parent
313e82880b
commit
823dd2d687
@@ -77,6 +77,29 @@ function shouldSendOsNotification(kind: "needsInput" | "idle"): boolean {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isChildSession(instanceId: string, sessionId: string): boolean | null {
|
||||||
|
const session = sessions().get(instanceId)?.get(sessionId)
|
||||||
|
if (!session) return null
|
||||||
|
return session.parentId !== null && session.parentId !== undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldSendOsNotificationForSession(
|
||||||
|
kind: "needsInput" | "idle",
|
||||||
|
instanceId: string,
|
||||||
|
sessionId: string | undefined | null,
|
||||||
|
): boolean {
|
||||||
|
if (!shouldSendOsNotification(kind)) return false
|
||||||
|
if (!sessionId) return true
|
||||||
|
|
||||||
|
const child = isChildSession(instanceId, sessionId)
|
||||||
|
|
||||||
|
// Avoid notification spam from spawned child/subagent sessions arriving before hydration.
|
||||||
|
if (child === null) return false
|
||||||
|
if (child) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
function getInstanceDisplayName(instanceId: string): string {
|
function getInstanceDisplayName(instanceId: string): string {
|
||||||
const instanceFolder = instances().get(instanceId)?.folder ?? instanceId
|
const instanceFolder = instances().get(instanceId)?.folder ?? instanceId
|
||||||
return instanceFolder.split(/[\\/]/).filter(Boolean).pop() ?? instanceFolder
|
return instanceFolder.split(/[\\/]/).filter(Boolean).pop() ?? instanceFolder
|
||||||
@@ -492,7 +515,7 @@ function handleSessionIdle(instanceId: string, event: EventSessionIdle): void {
|
|||||||
const sessionId = event.properties?.sessionID
|
const sessionId = event.properties?.sessionID
|
||||||
if (!sessionId) return
|
if (!sessionId) return
|
||||||
|
|
||||||
if (shouldSendOsNotification("idle")) {
|
if (shouldSendOsNotificationForSession("idle", instanceId, sessionId)) {
|
||||||
const title = getInstanceDisplayName(instanceId)
|
const title = getInstanceDisplayName(instanceId)
|
||||||
const label = getSessionTitle(instanceId, sessionId)
|
const label = getSessionTitle(instanceId, sessionId)
|
||||||
const body = label ? `Session "${label}" is idle` : "Session is idle"
|
const body = label ? `Session "${label}" is idle` : "Session is idle"
|
||||||
@@ -607,9 +630,10 @@ function handlePermissionUpdated(instanceId: string, event: { type: string; prop
|
|||||||
addPermissionToQueue(instanceId, permission)
|
addPermissionToQueue(instanceId, permission)
|
||||||
upsertPermissionV2(instanceId, permission)
|
upsertPermissionV2(instanceId, permission)
|
||||||
|
|
||||||
if (shouldSendOsNotification("needsInput")) {
|
const sessionId = getPermissionSessionId(permission)
|
||||||
|
|
||||||
|
if (shouldSendOsNotificationForSession("needsInput", instanceId, sessionId)) {
|
||||||
const title = getInstanceDisplayName(instanceId)
|
const title = getInstanceDisplayName(instanceId)
|
||||||
const sessionId = getPermissionSessionId(permission)
|
|
||||||
const label = getSessionTitle(instanceId, sessionId)
|
const label = getSessionTitle(instanceId, sessionId)
|
||||||
const body = label ? `Session "${label}" needs permission` : "Session needs permission"
|
const body = label ? `Session "${label}" needs permission` : "Session needs permission"
|
||||||
fireOsNotification({ title, body })
|
fireOsNotification({ title, body })
|
||||||
@@ -634,9 +658,10 @@ function handleQuestionAsked(instanceId: string, event: { type: string; properti
|
|||||||
addQuestionToQueue(instanceId, request)
|
addQuestionToQueue(instanceId, request)
|
||||||
upsertQuestionV2(instanceId, request)
|
upsertQuestionV2(instanceId, request)
|
||||||
|
|
||||||
if (shouldSendOsNotification("needsInput")) {
|
const sessionId = getQuestionSessionId(request)
|
||||||
|
|
||||||
|
if (shouldSendOsNotificationForSession("needsInput", instanceId, sessionId)) {
|
||||||
const title = getInstanceDisplayName(instanceId)
|
const title = getInstanceDisplayName(instanceId)
|
||||||
const sessionId = getQuestionSessionId(request)
|
|
||||||
const label = getSessionTitle(instanceId, sessionId)
|
const label = getSessionTitle(instanceId, sessionId)
|
||||||
const body = label ? `Session "${label}" needs input` : "Session needs input"
|
const body = label ? `Session "${label}" needs input` : "Session needs input"
|
||||||
fireOsNotification({ title, body })
|
fireOsNotification({ title, body })
|
||||||
|
|||||||
Reference in New Issue
Block a user