fix(client-web): scroll the web_search source card instead of collapsing

Replace the WebBlock search card's head/tail collapse and expand button
with a fixed-height scroll container that lists every source the tool
returned. The model-facing side is unchanged: the seam still caps sources
at searchMaxResults and the truncated indicator stays, so model-visible
and frontend-visible sources remain identical.

Remove CHAT_WEB_MAX_SOURCES and DEFAULT_WEB_MAX_SOURCES: with scroll, the
chat row and details panel show the same full list.
This commit is contained in:
Chinesezjc
2026-08-03 15:38:26 +08:00
parent 8527ce23ae
commit a2ec6cefc2
11 changed files with 127 additions and 156 deletions

View File

@@ -30,7 +30,6 @@ import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'
import { CHAT_DIFF_MAX_LINES, type DiffCardModel } from '../contract/diff-card-model.ts'
import { CHAT_READ_MAX_LINES, type ReadCardModel } from '../contract/read-card-model.ts'
import { CHAT_SEARCH_MAX_LINES, type SearchCardModel } from '../contract/search-card-model.ts'
import { CHAT_WEB_MAX_SOURCES } from '../contract/web-card-model.ts'
import { terminalBlockLabels, type TerminalCardModel } from '../contract/terminal-card-model.ts'
import type { ToolRowState, ToolRowVariant } from '../contract/tool-call-model.ts'
import { DisclosureRow } from './DisclosureRow.tsx'
@@ -276,7 +275,7 @@ export function ToolRow({
</>
)
: webBody !== null
? <WebBlock {...webBody} maxSources={CHAT_WEB_MAX_SOURCES} className={css.webBody} />
? <WebBlock {...webBody} className={css.webBody} />
: isThink
? <div className={css.thinkBody}>{body}</div>
: (

View File

@@ -15,16 +15,6 @@
import type { WebBlockProps } from '@deepseek-ai/dsh-client-ui-primitives'
import type { ToolCallBlock } from './tool-call-model.ts'
/**
* Sources the chat row's web body shows before collapsing the middle — half
* the primitive's own default, which the details panel keeps. A chat row is a
* summary surface inside the message flow: the flow must stay scannable across
* many calls, while the details panel is the single-call reading surface. A
* design constant of this UI's row geometry, not a deployment choice, so it is
* fixed here rather than a plugin Config field.
*/
export const CHAT_WEB_MAX_SOURCES = 8
/**
* Derive the web-card props for a tool call, or null when this call is not a
* web card and belongs on the generic path.

View File

@@ -180,13 +180,12 @@ function OutputBody({ material, cwd, t }: { material: CallMaterial; cwd: string
)
}
const web = webCardModel(material.block)
// Full source-list allowance here (the panel is the single-call reading
// surface); the chat rows cap it at CHAT_WEB_MAX_SOURCES. Below the card the
// panel also renders the flattened result content — the model-visible text
// the card does not carry verbatim (a web_fetch card shows only the URL and
// status, so its fetched body lives only here; a search card's answer and
// sources are structured, so the flattened form repeats them as the raw text
// the model saw).
// The card shows every source the tool returned (the same list the model saw),
// scrolling within its own capped height. Below the card the panel also renders
// the flattened result content — the model-visible text the card does not carry
// verbatim (a web_fetch card shows only the URL and status, so its fetched body
// lives only here; a search card's answer and sources are structured, so the
// flattened form repeats them as the raw text the model saw).
if (web !== null) {
const settled = 'kind' in material.block ? material.block : null
const body = settled === null ? '' : resultText(settled)