Skip to content

fix(tui): hide plugin-injected system reminders from transcript#32

Merged
ZouR-Ma merged 3 commits into
stepfun-ai:mainfrom
li-xiu-qi:fix/hide-injected-system-reminders
Jul 15, 2026
Merged

fix(tui): hide plugin-injected system reminders from transcript#32
ZouR-Ma merged 3 commits into
stepfun-ai:mainfrom
li-xiu-qi:fix/hide-injected-system-reminders

Conversation

@li-xiu-qi

@li-xiu-qi li-xiu-qi commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Closes #33

Problem

The subagent-plugin injects a Delegation reminder system message via beforeModelRequest on every user turn. Because the TUI renders every system message, the reminder appears repeatedly in the conversation transcript, cluttering the UI. Plan-plugin and skill-plugin inject similar internal status messages that also leak into the transcript.

Solution

Add an optional hidden flag to plugin-injected system messages. Hidden messages are still included in the model context (so behavior is unchanged), but they are skipped by the TUI transcript renderer and clipboard export.

Changes

  • packages/protocol/src/index.ts: add hidden?: boolean to SystemMessage.
  • packages/core/src/plugins/types.ts: add hidden?: boolean to PluginInjectedMessage.
  • packages/core/src/plugins/manager.ts: preserve the hidden flag when aggregating injected messages.
  • packages/core/src/agent/agent-loop.ts: pass hidden from injected messages into memory.
  • packages/core/src/agent/conversation-memory.ts: preserve hidden when cloning/restoring system messages so it survives checkpoints.
  • src/runtime/local-opentui-bridge.ts: forward hidden to transcript entries.
  • src/tui/types.ts: add hidden?: boolean to StepCliTuiTranscriptEntry.
  • src/tui/app.tsx: filter hidden entries out of buildTranscriptItems.
  • src/tui/transcript-export.ts: filter hidden entries from clipboard export.
  • skills/builtin/src/subagent-plugin.ts: mark MAIN_ORCHESTRATION_REMINDER as hidden: true.
  • skills/builtin/src/plan-plugin.ts: mark plan-status injection as hidden: true.
  • skills/builtin/src/skill-plugin.ts: mark skill-context injection as hidden: true.

Verification

  • pnpm exec tsc --noEmit passes.
  • pnpm build succeeds.
  • pnpm exec vitest run packages/core/src/agent/conversation-memory.test.ts packages/core/src/agent/conversation-memory-checkpoint.test.ts passes (23/23).
  • pnpm check passes after chore(docs): format pr-review-decision.md with Prettier #38 (formatting fix) is applied; only pre-existing lint warnings remain.
  • The TUI launches without errors and no longer renders repeated SYSTEM Delegation reminder / Plan status / Skill context blocks.

Related

@li-xiu-qi
li-xiu-qi force-pushed the fix/hide-injected-system-reminders branch 4 times, most recently from a738627 to 7bf6444 Compare June 12, 2026 13:32
@ZouR-Ma

ZouR-Ma commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the contribution!

To get this ready to merge:

  • Reference an issue in the description with Closes #<number> (our link-check CI requires it; open one first if needed).
  • Make sure pnpm check passes locally (lint, type-check, dependency/dead-code guards, formatting, and tests — also enforced in CI).

Full conventions:
https://github.com/stepfun-ai/Step-Realtime-CLI/blob/main/CONTRIBUTING.md

@li-xiu-qi
li-xiu-qi force-pushed the fix/hide-injected-system-reminders branch from 7bf6444 to caf20d5 Compare June 18, 2026 06:26
@github-actions github-actions Bot added area/core packages/core area/protocol packages/protocol area/skills skills area/cli src/cli, src/commands, src/runtime, src/bootstrap, src/*.ts area/tui src/tui labels Jun 18, 2026
@li-xiu-qi

Copy link
Copy Markdown
Contributor Author

@ZouR-Ma Thanks for the review. I've rebased onto the latest main and confirmed pnpm check passes locally (Node 20.20.2). The PR description already references Closes #33. Please let me know if anything else is needed.

@ZouR-Ma

ZouR-Ma commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this PR — the design choice is right: an optional hidden flag on system messages, still delivered to the model context and only skipped at render and export time, is far more robust than content-pattern filtering. The details are also thought through: cloneChatMessage preserves the flag so it survives checkpoints, and the conditional spread in addSystem avoids stamping hidden: false onto every message. One thing before this lands:

  1. (Must) Add a test for hidden-flag persistence. The flag-preserving line in cloneChatMessage is the one link in this chain that a future refactor could silently drop — the clutter bug would return with no failing test. Please add a case to the existing packages/core/src/agent/conversation-memory.test.ts: after addSystem(content, { hidden: true }), run a clone/restore round-trip and assert the flag is still true; also assert that an unflagged message comes back without a hidden field. Acceptance criterion: the case exists and passes.

Two non-blocking suggestions besides that: PluginInjectedMessage allows role: "user" with a hidden flag, but the user branch in agent-loop silently ignores it — the builtin plugins only inject system messages so it never triggers today, but a third-party plugin would hit it; consider tightening the type or documenting "system-only" on the field. Also, your #69 and #72 overlap with this PR on app.tsx and local-opentui-bridge.ts — it's worth sequencing the three yourself; this one is the smallest, so landing it first minimizes the rebase churn for the other two. Ping us once the test is in.

Plugin hooks can inject system messages for the model (e.g. the
subagent delegation reminder). These should not be rendered as visible
SYSTEM entries in the TUI transcript because they repeat every turn and
clutter the conversation.

- Add optional  flag to , ,
  and .
- Preserve  through PluginManager, AgentLoop, ConversationMemory,
  and the OpenTUI bridge.
- Filter hidden entries out of TUI transcript rendering and clipboard export.
- Mark  as hidden in subagent-plugin.
@li-xiu-qi
li-xiu-qi force-pushed the fix/hide-injected-system-reminders branch from caf20d5 to aaf3917 Compare July 11, 2026 15:58
@li-xiu-qi

Copy link
Copy Markdown
Contributor Author

@ZouR-Ma Thanks for the review. I've added a test case to packages/core/src/agent/conversation-memory.test.ts covering hidden-flag persistence through an export/load round-trip:

  • addSystem(content, { hidden: true }) survives exportState -> loadState -> exportState with hidden still true.
  • An unflagged system message comes back without a hidden field.

pnpm test packages/core/src/agent/conversation-memory.test.ts passes (13/13), and pnpm exec tsc --noEmit is clean.

Please take another look when you have a moment.

ZouR-Ma added 2 commits July 15, 2026 13:15
PluginInjectedMessage allowed role "user" with a hidden flag that the
agent loop silently ignored. Model it as a discriminated union so the
flag only exists on the system variant, and document the constraint.
@ZouR-Ma

ZouR-Ma commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Re-review passed — this is ready to land. The new test is exactly the one we asked for: preserves hidden flag through export/load round-trip locks down the flag-preserving line in cloneChatMessage (the one fragile link in the whole chain), and it also asserts that unflagged messages come back without a hidden field — both halves of the acceptance criterion. All three CI lanes are green.

The one leftover from the review — PluginInjectedMessage allowing role: "user" with a hidden flag that the agent loop silently ignores — we took care of directly on this branch (maintainer edit, 7a626a9) so it doesn't cost you another round: the type is now a discriminated union where hidden only exists on the system variant, with the constraint documented on the field. Typecheck and the plugin/memory test suites pass; we also merged the latest main.

Merging once CI reruns on that touch-up. Your #69 and #72 overlap with this PR on a couple of files — worth rebasing them once this lands. Thanks for turning the test around the same day.

@ZouR-Ma ZouR-Ma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The hidden-persistence test matches the acceptance criterion exactly, the type is now tightened so the hidden flag only exists on system messages, and all required checks are green on the merged state. Approving.

@ZouR-Ma
ZouR-Ma merged commit 6cdbed7 into stepfun-ai:main Jul 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli src/cli, src/commands, src/runtime, src/bootstrap, src/*.ts area/core packages/core area/protocol packages/protocol area/skills skills area/tui src/tui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui: plugin-injected system reminders are rendered repeatedly in TUI

2 participants