gemini-cli - 💡(How to fix) Fix [AgentProtocol] Leverage agent_start/end for robust UI coalescence [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
google-gemini/gemini-cli#25041Fetched 2026-04-10 03:45:04
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Author
Participants
Assignees
Timeline (top)
labeled ×2assigned ×1parent_issue_added ×1unlabeled ×1

The TUI currently uses fragile lookahead logic and timers to group parallel agent tool calls and prevent "visual tearing" when tools finish at slightly different times. It also has to guess when a model's activity is "final" enough to be moved from the pending live-state to static history.

The `AgentProtocol` already defines `agent_start` and `agent_end` events, which are correlated via `streamId`. These events should serve as the foundation for coalescing all activity within a single agent loop (thoughts, messages, tool calls) into an atomic unit for finalization.

Root Cause

The TUI currently uses fragile lookahead logic and timers to group parallel agent tool calls and prevent "visual tearing" when tools finish at slightly different times. It also has to guess when a model's activity is "final" enough to be moved from the pending live-state to static history.

The `AgentProtocol` already defines `agent_start` and `agent_end` events, which are correlated via `streamId`. These events should serve as the foundation for coalescing all activity within a single agent loop (thoughts, messages, tool calls) into an atomic unit for finalization.

RAW_BUFFERClick to expand / collapse

Parent tracking issue: #22702

Context

The TUI currently uses fragile lookahead logic and timers to group parallel agent tool calls and prevent "visual tearing" when tools finish at slightly different times. It also has to guess when a model's activity is "final" enough to be moved from the pending live-state to static history.

The `AgentProtocol` already defines `agent_start` and `agent_end` events, which are correlated via `streamId`. These events should serve as the foundation for coalescing all activity within a single agent loop (thoughts, messages, tool calls) into an atomic unit for finalization.

Tasks

  • Refactor `useAgentStream.ts` to use `agent_start` and `agent_end` for turn buffering:
    • When an `agent_start` is received, initialize a buffer for the given `streamId`.
    • Collect all incoming events (messages, tool calls, thoughts) for that `streamId` into the buffer.
    • When `agent_end` is received for that `streamId`, flush the entire buffered "turn" to the permanent history manager as a single cohesive unit.
  • Remove legacy finalization hacks:
    • Delete `flushCompletedTools`, `contigAgentsComplete` logic, and any other manual lookahead/batching timers.
  • Ensure `LegacyAgentProtocol` accurately emits `agent_end` only after all work in the current loop (including all scheduled tool responses) is fully processed and emitted.

Relevant Files

  • `packages/core/src/agent/legacy-agent-session.ts`: Ensure precise timing of `agent_end` emission.
  • `packages/cli/src/ui/hooks/useAgentStream.ts`: Implement stream-buffered history management.

Acceptance Criteria

  • Parallel tool calls and model messages are finalized in the UI as a single atomic unit upon `agent_end`.
  • The UI no longer relies on timers or lookahead hacks to prevent visual tearing.
  • The `streamId` is used as the primary key for coalescing related events into logical turns.

extent analysis

TL;DR

Refactor useAgentStream.ts to utilize agent_start and agent_end events for turn buffering to coalesce related events into logical turns.

Guidance

  • Implement a buffer in useAgentStream.ts to collect incoming events for a given streamId when an agent_start event is received.
  • Flush the buffered "turn" to the permanent history manager as a single cohesive unit when an agent_end event is received for the corresponding streamId.
  • Remove legacy finalization hacks, including flushCompletedTools and contigAgentsComplete logic, to rely solely on agent_start and agent_end events for turn buffering.
  • Ensure LegacyAgentProtocol accurately emits agent_end only after all work in the current loop is fully processed and emitted.

Example

// useAgentStream.ts
const buffer = {};

function handleAgentStart(streamId) {
  buffer[streamId] = [];
}

function handleAgentEnd(streamId) {
  const turn = buffer[streamId];
  // Flush the turn to the permanent history manager
  flushTurnToHistory(turn);
  delete buffer[streamId];
}

function collectEvent(streamId, event) {
  if (buffer[streamId]) {
    buffer[streamId].push(event);
  }
}

Notes

The provided solution assumes that the agent_start and agent_end events are correctly emitted by the AgentProtocol and that the streamId is properly correlated between these events.

Recommendation

Apply the workaround by refactoring useAgentStream.ts to utilize agent_start and agent_end events for turn buffering, as this approach eliminates the need for fragile lookahead logic and timers, reducing the likelihood of visual tearing.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

gemini-cli - 💡(How to fix) Fix [AgentProtocol] Leverage agent_start/end for robust UI coalescence [1 participants]