fix(web): address web card review — panel body, ol numbering, safe links, docs
- DetailsPanel: render the flattened result content below the web card, so a web_fetch's fetched body (and a search's answer/source markdown) stays visible on the panel's single-call reading surface — the card is a summary. - WebBlock: the collapsed source tail keeps each source's original citation number via <li value>, and the expand control is a marker-less <li> so the <ol> is valid HTML; an empty-hostname URL (file:/data:) falls back to the raw URL so a label is never blank. - web-row / GenericToolCard: both spread WebBlock uniformly with maxSources (fetch ignores it, like TerminalBlock's maxLines), dropping the duplicated per-kind conditional. - Docs: WebBlock added to the ui-primitives README (both languages) with a Web retrieval section; the ui-conversation README's "inline licensed for this intent alone" claim de-absolutized and a web-card paragraph added; the Agent Note's safe-link description corrected to the http(s) subset of MarkdownText's allowlist (mailto excluded). Fixture source comment aligned with its data. - Tests: ol numbering + marker-less expander, empty-hostname label fallback, the fetched body visible in the panel.
This commit is contained in:
@@ -56,10 +56,7 @@ export function GenericToolCard({ toolName, block, cwd, openFile }: ToolRowOwner
|
||||
return (
|
||||
<div className={css.card}>
|
||||
{row}
|
||||
<WebBlock
|
||||
{...(web.kind === 'search' ? { ...web, maxSources: CHAT_WEB_MAX_SOURCES } : web)}
|
||||
className={css.web}
|
||||
/>
|
||||
<WebBlock {...web} maxSources={CHAT_WEB_MAX_SOURCES} className={css.web} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -152,8 +152,20 @@ function OutputBody({ material, cwd }: { material: CallMaterial; cwd: string | u
|
||||
}
|
||||
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.
|
||||
if (web !== null) return <WebBlock {...web} className={css.web} />
|
||||
// surface); the chat rows cap it at CHAT_WEB_MAX_SOURCES. The card is a
|
||||
// summary — a web_fetch card shows only the URL and status — so the details
|
||||
// panel also renders the flattened result content below it (the fetched body,
|
||||
// the search answer + source markdown), which the card does not carry.
|
||||
if (web !== null) {
|
||||
const settled = 'kind' in material.block ? material.block : null
|
||||
const body = settled === null ? '' : renderResult(settled)
|
||||
return (
|
||||
<>
|
||||
<WebBlock {...web} className={css.web} />
|
||||
{body !== '' && <pre className={css.code}>{body}</pre>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
// A settled call always carries the result node the flattened form needs;
|
||||
// the running shape has no result to flatten.
|
||||
if (!('kind' in material.block)) return <div className={css.empty}>运行中…</div>
|
||||
|
||||
@@ -66,10 +66,7 @@ export function WebRow({ toolName, block }: ToolRowProps) {
|
||||
<span className={css.summary}>{model.summary}</span>
|
||||
</div>
|
||||
{web !== null && (
|
||||
<WebBlock
|
||||
{...(web.kind === 'search' ? { ...web, maxSources: CHAT_WEB_MAX_SOURCES } : web)}
|
||||
className={css.web}
|
||||
/>
|
||||
<WebBlock {...web} maxSources={CHAT_WEB_MAX_SOURCES} className={css.web} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user