feat(web): list a turn's produced files under its closing message

The paths come from the mutation tools' follow-along locations, not from the
closing prose, so a turn's output is listed whether or not the model named
it. Each chip opens through the same openFile the tool rows use.

Reads contribute nothing (looking at a file does not produce it), a failed
mutation contributes nothing, a file touched twice is one entry, and the row
shows six with an explicit remainder rather than burying the answer.
This commit is contained in:
ZiyaZhang
2026-07-31 22:13:34 -07:00
parent 00390ae851
commit 35e9122a65
7 changed files with 213 additions and 3 deletions

View File

@@ -30,7 +30,7 @@ import type {
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'
import { IconChevronDownOutline14 } from '@deepseek-ai/dsh-client-ui-primitives'
import type { ChatViewSlotProps } from '../contract/slots.ts'
import { assistantActionsSeqs, deriveChatFlow, type ChatFlowItem } from './chat-flow.ts'
import { assistantActionsSeqs, deriveChatFlow, turnDeliverables, type ChatFlowItem } from './chat-flow.ts'
import { AssistantMarkdown } from './AssistantMarkdown.tsx'
import { GenericCommandCard } from './GenericCommandCard.tsx'
import { GenericToolCard } from './GenericToolCard.tsx'
@@ -252,6 +252,9 @@ export function ChatView({
// Only the last content assistant of each turn owns IconActions; mid-turn
// text (before tools) omits `time` so AssistantMarkdown stays chrome-free.
const actionSeqs = useMemo(() => assistantActionsSeqs(nodes), [nodes])
// Produced files per closing assistant: derived from the mutation tools'
// locations, so a turn's output is listed whether or not the model named it.
const produced = useMemo(() => turnDeliverables(nodes), [nodes])
const listRef = useRef<HTMLDivElement | null>(null)
const atBottomRef = useRef(true)
@@ -402,6 +405,8 @@ export function ChatView({
time={actionSeqs.has(node.seq) ? node.time : undefined}
seq={node.seq}
onFork={forkAt}
produced={produced.get(node.seq)}
openFile={openFile}
t={t}
/>
)