feat(cli): refactor tool rendering to declarative ToolDisplay system

This change completes the transition of the interactive agent session (`useAgentStream`)
to a declarative-first tool rendering system.

Key changes:
- Reverted experimental `ToolDisplay` logic from legacy UI components (`DenseToolMessage`, etc.)
  to establish a clean baseline.
- Introduced `HistoryItemToolDisplayGroup` and `ToolGroupDisplay` component in CLI.
- Added `display` property to `ToolCallRequestInfo` to carry declarative UI info natively.
- Populated tool request display information at the source (`Turn.ts` and `Scheduler.ts`)
  using dynamic descriptions from tool invocations.
- Updated `useAgentStream` to emit the new history item type, providing a standalone
  rendering path for interactive sessions.
- Ensured tool descriptions are updated when arguments are modified during confirmation.
This commit is contained in:
Michael Bleigh
2026-04-12 11:46:18 -07:00
parent 410e675837
commit 45eababfd8
10 changed files with 262 additions and 12 deletions
+19 -7
View File
@@ -26,7 +26,7 @@ import type {
HistoryItemWithoutId,
LoopDetectionConfirmationRequest,
IndividualToolCallDisplay,
HistoryItemToolGroup,
HistoryItemToolDisplayGroup,
} from '../types.js';
import { StreamingState, MessageType } from '../types.js';
import { findLastSafeSplitPoint } from '../utils/markdownUtilities.js';
@@ -415,9 +415,15 @@ export const useAgentStream = ({
backgroundTasks,
);
const historyItem: HistoryItemToolGroup = {
type: 'tool_group',
tools: toolsToPush,
const historyItem: HistoryItemToolDisplayGroup = {
type: 'tool_display_group',
tools: toolsToPush.map((tc) => ({
name: tc.name,
description: tc.description,
...tc.display,
status: tc.status,
originalRequestName: tc.originalRequestName,
})),
borderTop: isFirstToolInGroupRef.current,
borderBottom: isLastInBatch,
...appearance,
@@ -456,8 +462,14 @@ export const useAgentStream = ({
if (remainingTools.length > 0) {
items.push({
type: 'tool_group',
tools: remainingTools,
type: 'tool_display_group',
tools: remainingTools.map((tc) => ({
name: tc.name,
description: tc.description,
...tc.display,
status: tc.status,
originalRequestName: tc.originalRequestName,
})),
borderTop: pushedToolCallIds.size === 0,
borderBottom: false,
...appearance,
@@ -486,7 +498,7 @@ export const useAgentStream = ({
(anyVisibleInHistory || anyVisibleInPending)
) {
items.push({
type: 'tool_group' as const,
type: 'tool_display_group',
tools: [],
borderTop: false,
borderBottom: true,