Skip to content

merge upstream notification support into guardrails fork#27

Merged
terisuke merged 5 commits intofix/guardrails-bootstrap-and-openrouterfrom
fork/pr-20963-notifications
Apr 4, 2026
Merged

merge upstream notification support into guardrails fork#27
terisuke merged 5 commits intofix/guardrails-bootstrap-and-openrouterfrom
fork/pr-20963-notifications

Conversation

@terisuke
Copy link
Copy Markdown

@terisuke terisuke commented Apr 4, 2026

Summary

  • bring in upstream PR feat(tui): built-in system notifications for session completion anomalyco/opencode#20963 for built-in TUI system notifications, toast polish, and the new tui.json notification toggle
  • add follow-up hardening so macOS focus detection uses normalized exact matches and Windows toast payloads flow through stdin instead of PowerShell interpolation
  • sync the latest upstream dev CI fix needed to keep JUnit output directories created during tests

Verification

  • bun test test/notification.test.ts
  • bun typecheck

kitlangton and others added 5 commits April 4, 2026 14:44
- Add Notification service with zero dependencies (darwin/linux/win32)
- macOS notifications attributed to Terminal.app (fixes click target)
- Add terminal focus detection to avoid notifications when focused
- Add 'notifications' config option to tui.json (default: true)
- Listen to session.idle for completion notifications
- Update session.error to also show system notifications
- Fix documentation plugin example (osascript attribution)
- Beautify TUI toast: full borders + variant icons (✓✗ℹ⚠)
- Add .catch() to session.idle notification to prevent crashes
- Use proper escapeForOsascript function for macOS
- Add more terminals to detection list (vscode, code)
- Restore escapeXml for Windows branch
Copilot AI review requested due to automatic review settings April 4, 2026 05:47
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 4, 2026

Hey! Your PR title merge upstream notification support into guardrails fork doesn't follow conventional commit format.

Please update it to start with one of:

  • feat: or feat(scope): new feature
  • fix: or fix(scope): bug fix
  • docs: or docs(scope): documentation changes
  • chore: or chore(scope): maintenance tasks
  • refactor: or refactor(scope): code refactoring
  • test: or test(scope): adding or updating tests

Where scope is the package name (e.g., app, desktop, opencode).

See CONTRIBUTING.md for details.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 4, 2026

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges upstream TUI system-notification support into the fork, adds follow-up hardening (macOS focus detection + Windows toast payload handling), and updates docs/CI to match the new notification behavior and reporting output paths.

Changes:

  • Add a cross-platform notification utility and wire it into the TUI for session.idle / session.error.
  • Introduce a notifications toggle in tui.json schema/config and update UI copy + docs to reference built-in notifications.
  • Add tests for terminal-name normalization + Windows toast XML escaping, and ensure CI creates/upload artifact directories correctly.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/web/src/content/docs/zh-tw/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/zh-cn/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/tr/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/th/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/ru/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/pt-br/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/plugins.mdx Updates notification plugin example and mentions built-in TUI notifications toggle.
packages/web/src/content/docs/pl/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/nb/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/ko/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/ja/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/it/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/fr/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/es/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/de/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/da/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/bs/plugins.mdx Updates macOS osascript notification example.
packages/web/src/content/docs/ar/plugins.mdx Updates macOS osascript notification example.
packages/opencode/test/notification.test.ts Adds tests for terminal-name normalization and XML escaping.
packages/opencode/src/notification/index.ts Introduces notification implementation for macOS/Linux/Windows (PowerShell stdin XML).
packages/opencode/src/config/tui-schema.ts Adds notifications option to tui.json schema.
packages/opencode/src/cli/cmd/tui/ui/toast.tsx Toast polish: border/icon treatment + safer unknown error typing.
packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx Updates tip text to promote built-in notifications toggle.
packages/opencode/src/cli/cmd/tui/app.tsx Hooks session events to show system notifications when appropriate.
packages/opencode/package.json Ensures .artifacts/unit exists before writing JUnit output.
packages/app/package.json Ensures .artifacts/unit exists before writing JUnit output.
.github/workflows/test.yml Uploads hidden files so .artifacts/... is included in artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +28 to +29
.optional()
.describe("Show system notifications when sessions complete or error. Requires terminal focus-loss detection."),
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notifications is declared as .boolean().default(true).optional(). In Zod, calling .optional() after .default() prevents the default from being applied when the value is undefined, so notifications will parse to undefined instead of true. Reorder to .optional().default(true) (or drop .optional() entirely) so the runtime config and generated schema correctly reflect the default.

Also, the description implies notifications require focus-loss detection, but terminalIsFocused() currently returns false on non-macOS, meaning notifications will fire even when the terminal is focused on Linux/Windows; consider clarifying the description accordingly.

Suggested change
.optional()
.describe("Show system notifications when sessions complete or error. Requires terminal focus-loss detection."),
.describe(
"Show system notifications when sessions complete or error. Terminal focus detection may vary by platform.",
),

Copilot uses AI. Check for mistakes.
Comment on lines +840 to +842
void Notification.terminalIsFocused().then((focused) => {
if (focused) return
if (tuiConfig.notifications === false) return
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the session.error handler, Notification.terminalIsFocused() runs unconditionally and only checks tuiConfig.notifications === false inside the .then(...). If notifications are disabled, this still executes osascript on macOS (potentially prompting for permissions / adding overhead) even though the result is discarded. Consider guarding on tuiConfig.notifications before calling terminalIsFocused() (similar to the session.idle handler).

Suggested change
void Notification.terminalIsFocused().then((focused) => {
if (focused) return
if (tuiConfig.notifications === false) return
if (tuiConfig.notifications === false) return
void Notification.terminalIsFocused().then((focused) => {
if (focused) return

Copilot uses AI. Check for mistakes.
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
await $`osascript -e 'tell application "Terminal" to display notification "Session completed!" with title "opencode"'`
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AppleScript example wraps display notification in tell application "Terminal" .... On macOS this can trigger an Automation permission prompt (“osascript wants to control Terminal”) and may fail if the user denies it. If the goal is just to post a notification, consider using display notification ... without targeting Terminal (or add a short note explaining the permission prompt / why Terminal is targeted).

Suggested change
await $`osascript -e 'tell application "Terminal" to display notification "Session completed!" with title "opencode"'`
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`

Copilot uses AI. Check for mistakes.
@terisuke terisuke merged commit 6393d95 into fix/guardrails-bootstrap-and-openrouter Apr 4, 2026
8 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants