feat(tui): send native Windows toast notifications in Windows Terminal - #3075
feat(tui): send native Windows toast notifications in Windows Terminal#3075bj456736 wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: a082644 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@codex review |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a082644d1c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const child = execFile(file, args, () => { | ||
| // Intentionally empty: delivery errors are not actionable here. | ||
| }); | ||
| child.unref(); |
There was a problem hiding this comment.
Detach the toast subprocess's stdio before unref
When a user exits while PowerShell is still running—or PowerShell wedges—this is not actually fire-and-forget: execFile creates referenced stdout/stderr pipes for its callback, and child.unref() only unreferences the child-process handle, so those pipes keep Node's event loop alive until the subprocess exits. Spawn the notifier with ignored/detached stdio (while retaining an error handler), or otherwise close/unref the streams and impose a timeout, so toast delivery cannot delay or hang TUI shutdown.
Useful? React with 👍 / 👎.
Problem
Desktop notifications in the TUI are delivered via OSC 9 escape sequences, gated on a small allow-list (iTerm2 / WezTerm / Ghostty / Warp / Kitty). Every other terminal only gets a bare BEL. Windows Terminal does not support OSC 9 desktop notifications — its OSC 9 is taken by ConEmu progress semantics — so Windows Terminal users never get a visual notification when a task completes or approval is needed; they only get the bell.
Fix
When the session is Windows Terminal (
WT_SESSIONis set) and OSC 9 is not supported, the BEL fallback path now additionally fires a native Windows toast via the systempowershell.exe(WinRTWindows.UI.Notifications,ToastText01template, notifier idKimi Code). The spawn is fire-and-forget:execFilewith an error-swallowing callback, wrapped in try/catch, andunrefed — notification delivery can never crash or hang the TUI.Ported from the MIT-licensed pi-notify (credited in code comments), with two fixes over the original:
'→'') before being interpolated into the PowerShell script;execFilegets an error callback (the original passes none, so a missingpowershell.exewould raise an unhandled error and crash the process).No new npm dependencies, no binaries.
Design trade-offs
WT_SESSIONnon-empty, noprocess.platformcheck): under WSL,process.platformislinuxbutWT_SESSIONis inherited andpowershell.exeworks via interop.Kimi Codeand the single-textToastText01template; XML injection is a non-issue sinceCreateTextNodeescapes for us.Tests
New cases in
apps/kimi-code/test/tui/terminal-notification.test.ts:isWindowsTerminalSessiondetection with and withoutWT_SESSIONbuildWindowsToastCommandshape (powershell.exe -NoProfile -NonInteractive -Command …,ToastText01, notifier idKimi Code) and single-quote escapingemitTerminalNotification(withnode:child_processexecFilemocked): WT + no OSC 9 → BEL written and toast spawned; WT + OSC 9 → no spawn; non-WT + no OSC 9 → no spawn;execFilecallback invoked with anError→ no throw; empty message → no spawnLocal results:
vitest run test/tui/terminal-notification.test.ts— 31/31 passed;tsc --noEmittypecheck clean;oxlint --type-awareon the changed files reports 0 warnings / 0 errors.On-Windows verification (actual toast rendering in Windows Terminal) will be done by maintainer 瑞丰.