Files
deepseek-harness/packages/client/ui-primitives
Chinesezjc 5081697aaf feat(web): render bash tool output as a terminal card
The bash tool already declares the `card: 'terminal'` render intent for
both its call and its result, and host/connection/runtime already deliver
it to the browser as callView/resultView. The Web client ignored it:
rows derived from raw args, and the details panel flattened every tool's
content into one soft-wrapping `<pre>`. Column-aligned output folded into
a paragraph and a long listing stretched the panel without bound.

`TerminalBlock` (ui-primitives) renders a command as a terminal surface:
a shortened-cwd prompt line, output at `white-space: pre` in a
horizontally scrolling box, a head/tail height cap with an expand
control, an exit-code/signal status pill, and a copy control for the raw
output. ANSI SGR runs are parsed with `anser` and resolved onto `--dsw-*`
theme tokens, with literal rgb kept for values the design system has no
token for. Geometry and fonts mirror CodeBlock; the clipboard write both
need moved into a package-internal `clipboard.ts`.

Both Web render sites for a bash call consume the intent through one
derivation (`terminal-card-model.ts`), so they cannot disagree about a
command, its cwd, or its exit status: the keyed BashRow carries the card
resident below its summary row, and the render-site fallback row keeps it
behind its existing expand control. Rows cap at 8 lines against the
panel's 16.

Inline output in the chat row reverses this package's stated
no-inline-output convention, on the owner's explicit decision; the Agent
Note records the reversal and its bound.

Tests: TerminalBlock/ansi/clipboard unit specs, ui-conversation wiring
specs at every render site, a built-client-graph snapshot covering both
chat-row shapes, and a real-browser e2e asserting the no-wrap layout and
the page's own Clipboard API.
2026-07-28 14:58:06 +08:00
..

@deepseek-ai/dsh-client-ui-primitives

English | 中文

Pure React atoms (zero cordis): StateDot, ic_ds_* icons, Button/Pill/Menu/Modal/Input, markdown family (MessageText/MarkdownText/JsonBlock), TerminalBlock. Contract: api-contracts v3 §8.

Markdown rendering

MarkdownText renders GFM from untrusted assistant output through React elements. It omits raw HTML, neutralizes relative and non-HTTP(S)/mailto links, opens HTTP(S) links with safe external-link attributes, and renders image alt text without loading remote resources; MessageText remains the literal-text primitive for user-authored content. Element spacing, tables, links, and inline code use the same --dsw-alias-markdown-* / --dsw-font-markdown-* tokens as deepsuite @deepseek/md. Fenced blocks render through CodeBlock (language banner, copy control, shiki for the registered grammars).

Terminal output

TerminalBlock renders a shell command as a terminal surface: a prompt line (shortened cwd label plus the command), the command's output, a status pill for a non-zero exit code or a terminating signal, and a copy control that writes the raw output prop. ANSI escape sequences are parsed with the anser runtime dependency into React spans; basic-16 foreground colors map onto --dsw-* tokens, while 256-palette and truecolor values pass through as literal rgb. Output keeps white-space: pre with horizontal scrolling, so column-aligned output holds its alignment instead of soft-wrapping, and collapses to a head slice plus a tail slice past maxLines (default 16, the TUI transcript's split arithmetic) behind an expand button. Rationale: the web terminal card note.

Model Experience

None, as the package renders pure React atoms in the browser; nothing here reaches a model request.

KV Cache effect

None; this package neither assembles nor sends a provider request.

Known Limitations and Deferred Work

  • Glyph-level icons are redrawn approximations — the fish logo (and the sparkle held by ui-conversation) come from font glyphs whose vector geometry is not exportable from the local design data; hand-authored recreations stand in until an exact export path exists.
  • Pill and Input have no design source — both atoms are self-defined; the sidebar search field and view-tab strip that resemble them are consumer-owned compositions, not these atoms.
  • StateDot Active variant is a hidden placeholder in the design — not implemented; the four shipped states (done/warning/ongoing/error) are the complete P-I surface.
  • TerminalBlock is not a terminal emulator — it renders settled or still-running command output, not an interactive session: SGR color and attributes are honored, while cursor movement, screen clearing, and alternate-screen sequences are stripped. Basic-16 magenta and cyan have no token equivalent and stay literal rgb.