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.
This commit is contained in:
mrosnerr
2026-04-28 10:34:29 -04:00
parent fbaeb032c0
commit 384bc53bfd
2 changed files with 10 additions and 9 deletions
+4 -6
View File
@@ -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<boolean>
send: (ctx: PluginInput, platform: Platform, sessionID: string) => Promise<void>
playSound: (ctx: PluginInput, platform: Platform, soundPath: string) => Promise<void>
send: (ctx: PluginInput, sessionID: string) => Promise<void>
playSound: (ctx: PluginInput, soundPath: string) => Promise<void>
}) {
const notifiedSessions = new Set<string>()
const pendingTimers = new Map<string, ReturnType<typeof setTimeout>>()
@@ -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)
+6 -3
View File
@@ -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"])