You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]: TUI plugin API: render synthetic messages with a plugin component #59432
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Plugins can add synthetic messages with session.synthetic({ text, description, metadata }). The V2 TUI shows each synthetic message as one notice row: an icon and the description, cut to one line (SessionNoticeMessageV2 in packages/tui/src/routes/session/index.tsx). A plugin cannot change how its own synthetic messages look.
Example: a plugin sends messages between sessions. It puts the sender, the intent and the send time in metadata, and the message body in text. The user wants a small box that shows the sender, the time and the first lines of the body. Today the plugin can only set a one-line description.
Proposal: a TUI plugin registration for synthetic messages, selected by a metadata field. For example:
The host calls this renderer when metadata.renderer is "my-plugin.mail". If no plugin gives a renderer for that name, or if the renderer has an error, the host shows the current notice row. The model context does not change. Only the TUI view changes.
This is the same pattern as the markdown code-block renderer registration and the per-message footer slot in #46268. Related: #48644 (UI-only notices).
Thanks for the detailed proposal, @iceteaSA! You're asking for a TUI plugin registration that lets a plugin draw its own synthetic messages: the host would pick the renderer by a metadata field such as metadata.renderer, fall back to the current one-line notice row if no renderer matches or the renderer fails, and leave model context unchanged.
I checked the current code. SessionNoticeMessageV2 always draws one truncated line from description, and the TUI plugin API has a code-block renderer, routes and slots but no hook for message rendering. So this can't be done from a plugin today and would need a new API. Maintainers will look at the design; please wait for their feedback before you start the change.
A smaller step that would cover a lot of this: let a synthetic message pick its notice icon, e.g. metadata.icon. Today SessionNoticeMessageV2 hard-codes ◎ for the goal source and ◈ for everything else, so a plugin's notices all look alike and the only way to tell a plugin's own kind apart is a host special case. On my fork I have exactly that kind of special case for a plugin that delivers messages between sessions (✉, cevr@509357d); a generic field would replace it:
The full renderer registration proposed here would still be the way to draw a card; the icon is a one-line, TUI-only change that needs no new API surface.
Activity
opencode-agent commentedon Oct 26, 2026
Thanks for the detailed proposal, @iceteaSA! You're asking for a TUI plugin registration that lets a plugin draw its own synthetic messages: the host would pick the renderer by a metadata field such as
metadata.renderer, fall back to the current one-line notice row if no renderer matches or the renderer fails, and leave model context unchanged.I checked the current code.
SessionNoticeMessageV2always draws one truncated line fromdescription, and the TUI plugin API has a code-block renderer, routes and slots but no hook for message rendering. So this can't be done from a plugin today and would need a new API. Maintainers will look at the design; please wait for their feedback before you start the change.Related issues:
cevr commentedon Nov 6, 2026
A smaller step that would cover a lot of this: let a synthetic message pick its notice icon, e.g.
metadata.icon. TodaySessionNoticeMessageV2hard-codes◎for the goal source and◈for everything else, so a plugin's notices all look alike and the only way to tell a plugin's own kind apart is a host special case. On my fork I have exactly that kind of special case for a plugin that delivers messages between sessions (✉, cevr@509357d); a generic field would replace it:The full renderer registration proposed here would still be the way to draw a card; the icon is a one-line, TUI-only change that needs no new API surface.