From 384bc53bfd8f0da847806fecc6af5de2fbad451f Mon Sep 17 00:00:00 2001 From: mrosnerr Date: Tue, 28 Apr 2026 10:34:29 -0400 Subject: [PATCH] fix(notification): resolve platform in scheduler callbacks instead of using stale init value The idle notification scheduler was initialized with platform 'unsupported' before platform detection had run. This stale value was passed to send/playSound callbacks, causing sendSessionNotification to silently no-op (no switch case for 'unsupported'). Session-idle notifications never fired as a result. Fix: remove platform from scheduler options entirely. Callbacks now resolve platform via ensureNotificationPlatform() which is sync, cached, and already called by each event handler before scheduling. --- src/hooks/session-notification-scheduler.ts | 10 ++++------ src/hooks/session-notification.ts | 9 ++++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/hooks/session-notification-scheduler.ts b/src/hooks/session-notification-scheduler.ts index afea12c7f..298fbe95a 100644 --- a/src/hooks/session-notification-scheduler.ts +++ b/src/hooks/session-notification-scheduler.ts @@ -1,5 +1,4 @@ import type { PluginInput } from "@opencode-ai/plugin" -import type { Platform } from "./session-notification-sender" type SessionNotificationConfig = { playSound: boolean @@ -13,11 +12,10 @@ type SessionNotificationConfig = { export function createIdleNotificationScheduler(options: { ctx: PluginInput - platform: Platform config: SessionNotificationConfig hasIncompleteTodos: (ctx: PluginInput, sessionID: string) => Promise - send: (ctx: PluginInput, platform: Platform, sessionID: string) => Promise - playSound: (ctx: PluginInput, platform: Platform, soundPath: string) => Promise + send: (ctx: PluginInput, sessionID: string) => Promise + playSound: (ctx: PluginInput, soundPath: string) => Promise }) { const notifiedSessions = new Set() const pendingTimers = new Map>() @@ -136,10 +134,10 @@ export function createIdleNotificationScheduler(options: { notifiedSessions.add(sessionID) - await options.send(options.ctx, options.platform, sessionID) + await options.send(options.ctx, sessionID) if (options.config.playSound && options.config.soundPath) { - await options.playSound(options.ctx, options.platform, options.config.soundPath) + await options.playSound(options.ctx, options.config.soundPath) } } finally { executingNotifications.delete(sessionID) diff --git a/src/hooks/session-notification.ts b/src/hooks/session-notification.ts index f9a40f56d..c9178f0df 100644 --- a/src/hooks/session-notification.ts +++ b/src/hooks/session-notification.ts @@ -47,10 +47,10 @@ export function createSessionNotification(ctx: PluginInput, config: SessionNotif const scheduler = createIdleNotificationScheduler({ ctx, - platform: "unsupported", config: mergedConfig, hasIncompleteTodos, - send: async (hookCtx, platform, sessionID) => { + send: async (hookCtx, sessionID) => { + const platform = ensureNotificationPlatform() if (typeof hookCtx.client.session.get !== "function" && typeof hookCtx.client.session.messages !== "function") { await sessionNotificationSender.sendSessionNotification(hookCtx, platform, mergedConfig.title, mergedConfig.message) return @@ -64,7 +64,10 @@ export function createSessionNotification(ctx: PluginInput, config: SessionNotif await sessionNotificationSender.sendSessionNotification(hookCtx, platform, content.title, content.message) }, - playSound: sessionNotificationSender.playSessionNotificationSound, + playSound: async (hookCtx, soundPath) => { + const platform = ensureNotificationPlatform() + await sessionNotificationSender.playSessionNotificationSound(hookCtx, platform, soundPath) + }, }) const QUESTION_TOOLS = new Set(["question", "ask_user_question", "askuserquestion"])