Skip to content

[FEATURE]: Plugins have no way to transform assistant text for display (or on completion) on v2 #53019

Description

@ualtinok

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Use case

Some plugins have the model write small markers into its own replies. For example, a context-management plugin asks the model to tag messages with §N§ so it can refer back to them. These markers are meant for the plugin, not the user. On v1, experimental.text.complete lets a plugin rewrite an assistant text part when it completes, before it is saved, so the markers never reach the stored transcript or the UI.

On v2 there is no equivalent, so the markers are saved in session_message and shown in the timeline.

What v2 offers today (checked at upstream/v2 d1f8f5b, same as v2.0.22)

  • SessionHooks (packages/plugin/src/promise/session.ts) is prompt, context, compaction, generate, title, model.request, http.request, http.response, experimental.ws.handshake, experimental.ws.send, experimental.ws.receive and retry. Nothing runs between the parsed model reply and persistence, or before rendering.
  • The TUI plugin API's only markdown seam is markdown.registerCodeBlockRenderer(language, render) (packages/plugin/src/tui/context.ts), which handles fenced code blocks by language, not prose. The slot map has no per-message or per-part slot.
  • The closest workaround is to replace the provider's raw response in http.response (or edit frames in experimental.ws.receive) and strip the markers from the wire stream before OpenCode parses it. That works, but it is provider-specific: a marker can be split across SSE events or JSON-escaped deltas, and every protocol (Anthropic, OpenAI Responses, Gemini, ...) needs its own parser.

Proposal (either would cover it; the first is preferred)

  1. A display hook that runs before assistant text is rendered, in the TUI and the app, letting a plugin hide its own markers from what the user sees. The stored text and what is sent back to the model stay exactly as the provider returned them. This is the better fit because it doesn't change history: prompt-cache prefixes stay byte-stable, and the WebSocket continuation path, which compares stored output byte for byte, is unaffected.
  2. A text.complete equivalent: a session hook that runs when an assistant text part completes, with the part text mutable, before it is persisted. This is what v1 does today.

Related issues

These cover nearby ground on v1 and are closed, so none of them tracks v2:

Activity

  1. changed the title [-]Plugins have no way to transform assistant text for display (or on completion) on v2[/-] [+][FEATURE]: Plugins have no way to transform assistant text for display (or on completion) on v2[/+] on Oct 4, 2026
  2. github-actions commented on Oct 4, 2026

    @github-actions
    Contributor

    Thanks for updating the issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions