FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(tui): session-scoped plugin toasts by nexxeln · Pull Request #49962 · anomalyco/opencode · GitHub

feat(tui): session-scoped plugin toasts - #49962

Merged
nexxeln merged 2 commits into
v2from
session-toasts
Sep 19, 2026
Merged

nexxeln merged 2 commits into
v2from
session-toasts

Conversation

nexxeln commented Sep 19, 2026

Copy link
Copy Markdown
Member

Why the change

TUI plugins can only show global toasts, so a notification about one session shows up identically while the user is looking at a different tab; this lets plugins tag a toast with a sessionID and have the TUI decide how to present it.

Special things to note

  • Behavior change in the built-in notifications plugin: a failed session you are not viewing now shows an error toast with an Open action. Previously it was dropped and only surfaced as an OS notification plus the tab's error marker.
  • Scoped to TUI plugins only. Server plugins still have no way to toast: tui.toast.show in packages/schema/src/tui-event.ts has listeners in app.tsx but no publisher in V2. Adding sessionID to that event and a publish path is a follow-up.
  • The policy lives in the plugin adapter, not in ui/toast.tsx, because ToastProvider mounts above RouteProvider and DataProvider and cannot see sessions.

Change outline

One optional field on the plugin contract:

 // packages/plugin/src/tui/context.ts
 export interface ToastOptions {
   readonly title?: string
   readonly message: string
   readonly variant?: ToastVariant
   readonly duration?: number
+  readonly sessionID?: string
 }

The adapter in packages/tui/src/plugin/api.tsx applies the presentation policy before handing off to the global toast queue:

ui.toast.show(options)
  if no sessionID
    show as-is
  if root(routed session) == root(options.sessionID)   # same family: parent or subagent open
    show as-is
  else
    title  = options.title ?? session.title
    action = "Open" -> route.navigate({ type: "session", sessionID })
    show

The built-in notifications plugin drops its hand-rolled route check and uses the field instead:

 // packages/tui/src/feature-plugins/system/notifications.ts
 notify(context, sessionID, event.data.error.message, "error")
-const route = context.ui.router.current()
-if (route.type === "session" && route.sessionID === sessionID)
-  context.ui.toast.show({ title: "Session failed", message, variant: "error" })
+context.ui.toast.show({ sessionID, title: "Session failed", message, variant: "error" })

Files:

 packages/plugin/src/tui/context.ts                     # ToastOptions.sessionID
 packages/tui/src/plugin/api.tsx                        # session-aware toast adapter
 packages/tui/src/feature-plugins/system/notifications.ts  # uses sessionID
 packages/tui/test/cli/cmd/tui/notifications.test.ts    # asserts tagged toast
+packages/tui/test/plugin-toast.test.tsx                # adapter policy tests

nexxeln merged commit 4b00dd2 into v2 Sep 19, 2026
8 checks passed
nexxeln deleted the session-toasts branch September 19, 2026 12:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant


Back | FazBrowse Home | New Git URL