-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix(session-notification): revert PR #543 and add proper notification plugin conflict detection #575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(session-notification): revert PR #543 and add proper notification plugin conflict detection #575
Conversation
…iagnosed) This reverts commit 4a38e70 (PR code-yeongyu#543) and 2064568 (follow-up fix). ## Why This Revert The original diagnosis was incorrect. PR code-yeongyu#543 assumed Bun's ShellInterpreter GC bug was causing Windows crashes, but further investigation revealed the actual root cause: **The crash occurs when oh-my-opencode's session-notification runs alongside external notification plugins (e.g., @mohak34/opencode-notifier).** Evidence: - User removed opencode-notifier plugin → crashes stopped - Release version (with original ctx.$ code) works fine when used alone - No widespread crash reports from users without external notifiers - Both plugins listen to session.idle and send concurrent notifications The real issue is a conflict between two notification systems: 1. oh-my-opencode: ctx.$ → PowerShell → Windows.UI.Notifications 2. opencode-notifier: node-notifier → SnoreToast.exe A proper fix will detect and handle this conflict gracefully. Refs: code-yeongyu#543, oven-sh/bun#23177, oven-sh/bun#24368 See: docs/CRASH_INVESTIGATION_TIMELINE.md (in follow-up commit)
…tification plugins When oh-my-opencode's session-notification runs alongside external notification plugins like opencode-notifier, both listen to session.idle and send concurrent notifications. This can cause crashes on Windows due to resource contention between different notification mechanisms: - oh-my-opencode: ctx.$ → PowerShell → Windows.UI.Notifications - opencode-notifier: node-notifier → SnoreToast.exe This commit adds: 1. External plugin detection (checks opencode.json for known notifiers) 2. Auto-disable of session-notification when conflict detected 3. Console warning explaining the situation 4. Config option 'notification.force_enable' to override Known notification plugins detected: - opencode-notifier - @mohak34/opencode-notifier - mohak34/opencode-notifier This is the actual fix for the Windows crash issue previously misdiagnosed as a Bun.spawn GC bug (PR code-yeongyu#543). Refs: code-yeongyu#543
Documents the investigation journey from initial misdiagnosis (Bun GC bug) to discovering the actual root cause (notification plugin conflict). Key findings: - PR code-yeongyu#543 was based on incorrect assumption - The real issue is concurrent notification plugins - oh-my-opencode + opencode-notifier = crash on Windows - Either plugin alone works fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Greptile Overview
Greptile Summary
This PR correctly reverts PR #543 and implements proper conflict detection between oh-my-opencode's session-notification and external notification plugins like opencode-notifier, which was the actual root cause of Windows crashes.
Key Changes:
- Reverted
session-notification.tsto usectx.$(Bun shell) instead ofnode:child_process.spawn- the original implementation was never the problem - Added
external-plugin-detector.tsutility that scansopencode.jsonfor conflicting notification plugins - Modified
src/index.tsto auto-disable session-notification when external notifiers are detected (with console warning) - Added
notification.force_enableconfig option for users who want to override the auto-disable behavior - Excellent documentation in
CRASH_INVESTIGATION_TIMELINE.mdexplaining the investigation process and lessons learned
Minor Issue:
- The new
external-plugin-detector.tsreimplements JSONC parsing with a custom regex-basedstripJsonCommentsfunction, but the codebase already has a robustjsonc-parsermodule that should be used instead
Confidence Score: 4/5
- Safe to merge with one minor refactoring suggestion
- The PR correctly addresses the root cause with evidence-based reasoning, includes comprehensive tests (18 passing tests across both new and reverted files), and follows TDD principles. Score is 4 instead of 5 due to the duplicated JSONC parsing logic that should use the existing
jsonc-parsermodule for better maintainability src/shared/external-plugin-detector.tsshould be refactored to use the existingjsonc-parsermodule instead of custom regex-based comment stripping
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| src/shared/external-plugin-detector.ts | 4/5 | New conflict detection utility with custom JSONC parser; should use existing jsonc-parser module instead |
| src/hooks/session-notification.ts | 5/5 | Reverted to use ctx.$ - correctly restores original implementation that was working fine |
| src/index.ts | 5/5 | Added plugin conflict detection before creating session-notification hook with proper logging and config override support |
| src/config/schema.ts | 5/5 | Added NotificationConfigSchema with force_enable option - clean implementation following existing patterns |
Sequence Diagram
sequenceDiagram
participant Plugin as OhMyOpenCodePlugin
participant Detector as detectExternalNotificationPlugin
participant FS as FileSystem
participant Config as opencode.json
participant Hook as session-notification
participant User as User Console
Note over Plugin: Plugin initialization starts
Plugin->>Plugin: Check if session-notification enabled
alt session-notification enabled
Plugin->>Plugin: Check notification.force_enable config
alt force_enable = false (default)
Plugin->>Detector: detectExternalNotificationPlugin(ctx.directory)
Detector->>Detector: getConfigPaths(directory)
loop For each config path
Detector->>FS: Check if config file exists
FS-->>Detector: exists/not exists
alt Config exists
Detector->>Config: Read and parse JSONC
Config-->>Detector: { plugin: [...] }
Detector->>Detector: matchesNotificationPlugin(plugin)
alt Match found (e.g., "opencode-notifier")
Detector-->>Plugin: { detected: true, pluginName: "opencode-notifier" }
Plugin->>User: console.warn(conflict warning)
Plugin->>Plugin: sessionNotification = null (skip creation)
Note over Plugin,Hook: session-notification disabled
end
end
end
alt No conflict detected
Detector-->>Plugin: { detected: false }
Plugin->>Hook: createSessionNotification(ctx)
Note over Hook: Uses ctx.$ for notifications
end
else force_enable = true
Plugin->>Hook: createSessionNotification(ctx)
Note over Hook: Force-enabled by user config
end
end
Note over Plugin: Plugin continues initialization
rect rgb(240, 240, 255)
Note over Hook: When session.idle event occurs
Hook->>Hook: Check if main session
Hook->>Hook: Wait 1.5s idle confirmation
Hook->>Hook: Send notification via ctx.$
alt Windows
Hook->>Hook: PowerShell + Windows.UI.Notifications
else macOS
Hook->>Hook: osascript display notification
else Linux
Hook->>Hook: notify-send
end
end
Additional Comments (2)
The codebase already has a proper JSONC parser using the
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 issues found across 8 files
Confidence score: 3/5
- Custom JSONC parsing in
src/shared/external-plugin-detector.tsignores the documentedparseJsonc/readJsoncFileutilities, risking inconsistent behavior and future maintenance headaches. src/hooks/session-notification.tsdrops single-quote escaping forsoundPath, so PowerShell commands can break or be exploited when paths contain'characters.- Pay close attention to
src/shared/external-plugin-detector.ts,src/hooks/session-notification.ts- ensure JSONC parsing follows project utilities and PowerShell sound paths are properly escaped.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="src/hooks/session-notification.ts">
<violation number="1" location="src/hooks/session-notification.ts:125">
P2: Missing single quote escaping for `soundPath` in PowerShell command. If the path contains single quotes, the command will fail or could be exploited. The previous code escaped with `.replace(/'/g, "''")`.</violation>
</file>
<file name="src/shared/external-plugin-detector.ts">
<violation number="1" location="src/shared/external-plugin-detector.ts:61">
P2: Use the project's existing `parseJsonc` or `readJsoncFile` utility instead of custom `stripJsonComments` + `JSON.parse`. The project documentation explicitly lists this as an anti-pattern, and `src/shared/jsonc-parser.ts` already provides robust JSONC parsing via the `jsonc-parser` library.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
@sisyphus-dev-ai fix reviews on there, commit, push |
…ng JSONC parser - Add back single-quote escaping for PowerShell soundPath to prevent command failures - Replace custom stripJsonComments with existing parseJsoncSafe from jsonc-parser - All 655 tests pass
✅ Review Feedback AddressedFixed both issues identified by the AI reviewers: Issue 1: PowerShell Single-Quote Escaping (session-notification.ts:125)
Issue 2: Custom JSONC Parsing (external-plugin-detector.ts:61)
Verification
Ready for re-review! 🚀 |
Summary
This PR reverts PR #543 and implements the actual fix for the Windows crash issue.
What Changed
ctx.$usagedocs/CRASH_INVESTIGATION_TIMELINE.mdThe Investigation Story
Initial Diagnosis (Wrong)
PR #543 assumed Bun's ShellInterpreter GC bug was causing crashes. We replaced
ctx.$withnode:child_process.spawnto work around it.What Actually Happened
After PR #543 merged, crashes continued. Further investigation revealed the real pattern:
The Real Root Cause
When oh-my-opencode's
session-notificationruns alongside external notification plugins likeopencode-notifier, both listen tosession.idleand send concurrent notifications. This causes crashes on Windows due to resource contention:ctx.$→ PowerShell → Windows.UI.Notificationsnode-notifier→ SnoreToast.exeTwo different notification systems competing for the same Windows resources = crash.
Evidence
ctx.$) works fine aloneThe Proper Fix
1. External Plugin Detection
New
detectExternalNotificationPlugin()function that:opencode.jsonplugin list2. Auto-Disable on Conflict
When external notifier detected:
3. Config Override
Users can force-enable if needed:
{ "notification": { "force_enable": true } }Testing
Files Changed
src/hooks/session-notification.tsctx.$src/hooks/session-notification.test.tssrc/shared/external-plugin-detector.tssrc/shared/external-plugin-detector.test.tssrc/config/schema.tsnotification.force_enablesrc/index.tsdocs/CRASH_INVESTIGATION_TIMELINE.mdRelated
Lessons Learned
Summary by cubic
Restores session-notification's use of ctx.$ and adds detection of external notifier plugins. On conflict, session-notification is auto-disabled to prevent Windows crashes.
Bug Fixes
New Features
Written for commit 6230287. Summary will update on new commits.