feat(chat): stream partial tool output during live agent response

Live tool calls that produce output while running (e.g. streaming bash
stdout from Codex) now render their partial output in real time instead
of appearing blank until the tool completes. The tool card keeps its
running visual state — spinner and 24KB tail truncation — while chunks
arrive, and transitions to the completed state once the final status
lands. A WeakMap keyed on the ACP reducer's chunks-array identity
memoizes the joined output so repeated renders don't re-run O(n) string
concatenation.
This commit is contained in:
xintaofei
2026-04-15 19:16:50 +08:00
parent 189399e5cf
commit 2cec462594
3 changed files with 104 additions and 21 deletions

View File

@@ -292,13 +292,22 @@ export function MessageListView({
const { threadItems, nonStreamingAdapted } = useMemo(() => {
const allTurns = timelineTurns.map((item) => item.turn)
const streamingIndices = new Set<number>()
const inProgressToolCallIdsByIndex = new Map<number, Set<string>>()
timelineTurns.forEach((item, i) => {
if (item.phase === "streaming") streamingIndices.add(i)
if (item.phase === "streaming") {
streamingIndices.add(i)
if (item.inProgressToolCallIds && item.inProgressToolCallIds.size > 0) {
inProgressToolCallIdsByIndex.set(i, item.inProgressToolCallIds)
}
}
})
const allAdapted = adaptMessageTurns(
allTurns,
adapterText,
streamingIndices.size > 0 ? streamingIndices : undefined
streamingIndices.size > 0 ? streamingIndices : undefined,
inProgressToolCallIdsByIndex.size > 0
? inProgressToolCallIdsByIndex
: undefined
)
// Collect non-streaming adapted messages for plan extraction