qwen-code/docs/design/shell-command-card.md
ytahdn eda1c1d8b6
feat(web-shell): present structured shell execution results (#12311)
* feat(web-shell): present structured shell execution results

* fix(shell): preserve cleanup notices and clarify result fallbacks

* fix(test): sync shell result source mappings

* fix(web-shell): address shell command card review findings (#12311)

- Documents: stop duplicating the command above the fallback text and
  label an empty legacy result as 'No output' (maintainer N1/N2)
- Escape control and bidi characters at every shell-card render site
  while keeping clipboard copies byte-exact
- Render a string rawOutput display instead of model-facing content so
  background-promotion and refusal messages stay visible
- Show a finished command's elapsed time from startTime/endTime
- Suppress the Command section when the legacy envelope already leads
  with the same command, keeping it once per expanded card
- Pin the wasCancelled status, the background timeout gates, the
  synthetic exit-zero headline and the status icons; freeze the
  running-elapsed fixture's clock
- Tag the card smoke test and wait for the SSE connection before
  driving live frames
- Drop the dead .expandedBash selector and align both design docs with
  the undisclosed live-frame transport for line/byte counts

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* test(core): isolate gitPush tests from host git config (#12311)

The deterministic verification gate ran the core suite on a persistent
runner whose real ~/.gitconfig carries remote.pushDefault=gd, and the
three gitPush tests that resolve the push remote failed with
'fatal: gd does not appear to be a git repository'. gitEnv strips only
the GIT_CONFIG_* env overrides, so the code under test still honors the
host HOME config — the exact gap the file's hermeticEnv() helper
documents and every gitPull test already guards against.

Pass hermeticEnv() at all six gitPush call sites so host config can no
longer steer push resolution. Reproduced with a poisoned HOME
(remote.pushDefault=gd): the three gate failures appear on the pre-fix
tree and the file is 107/107 green after, in both clean and poisoned
environments.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(core): stage browser-use runtime on demand in core prebuild (#12311)

The deterministic verification gate rebuilds core with a scoped
npm run build --workspace packages/core, but the review-address job
installs with QWEN_SKIP_PREPARE=1 and restores only the root and core
dist artifacts, so packages/browser-use/dist is absent and the core
build dies in copyBrowserUseAssets. The dependency on the built
browser-use runtime was only expressed through the root build's
ordering, leaving every scoped core build (the gate's, or a
developer's on a prepare-skipped install) broken.

Add a prebuild that stages the browser-use runtime only when its
dist/index.js sentinel is missing. The root build keeps building
browser-use first, so the prebuild is a no-op skip there and the
fallback fires exactly when the runtime is absent.

Probe matrix: scoped core build fails without the runtime pre-fix
(the gate rejection, reproduced locally), passes with the runtime
absent (fallback stages it), and passes unchanged with the runtime
present (skip path).

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

* fix(web-shell): treat empty string shell display as authoritative (#12311)

A persisted empty display string from a silent command is falsy, so the
card fell back to the model-facing envelope in content and the
legacyOutputRepeatsCommand guard then suppressed the Command panel,
rendering a bare envelope with no copy action. Gate the string branch on
the type alone so an empty string renders as empty output next to the
command.

* fix(core): preserve shell display and recording diagnostics

---------

Co-authored-by: 钉萁 <dingqi.jww@alibaba-inc.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen Autofix <autofix@qwen-code.ai>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-09-21 11:32:42 +00:00

5 KiB

Shell command card

English | 简体中文

Running cards share the same layout, with a spinning status icon and elapsed time. Only recognized structured rawOutput ANSI snapshots render as styled text; ordinary JSON stdout stays verbatim and unknown live structures fall back to full JSON. Structured results distinguish empty output from literal (empty) without inspecting text; the supplied timeout stays in execution details. Line/byte counts come from the live-frame snapshot described below, so they stay hidden until a transport delivers them. Copy uses displayed plain text. Heartbeat-only ACP events are already ignored by the SDK, preserving output even across card collapse; unknown text stays intact. Output follows updates only while the reader stays near the bottom. Active shell input previews are not output. Current ACP drops ordinary streaming chunks and the SDK filters heartbeat metadata, so a real command may display Waiting for output until completion; frontend elapsed time uses the tool start timestamp, not backend heartbeat metrics.

Problem and scope

The Web Shell repeats the tool name, description and command, then renders a model-facing result envelope as one muted block. The initial presentation change is extended by structured Shell results. Preserve model-facing output, approval UI and other tools.

Design

Reuse the existing semantic summary and card styles. The expanded Shell card retains its localized tool title and execution status. The sections are ordered Command, Output, Execution details. Command and Output are expanded by default, with readable ANSI-aware output. Command, Output and Execution details use the same subtle theme-aware background with small rounded corners and no border. Stronger category headings and 16px section spacing establish hierarchy. Each content region has a 200px maximum height with internal scrolling; category headings and Copy stay above and outside its scroll area. Collapsed categories show only their headings. Document exports remain unbounded. Command and Output each have an icon-only copy button in their heading row; content uses the full card width. Command copy preserves the exact command; output copy copies the displayed text without ANSI styling. Each button independently switches to a check temporarily after successful copying, following the existing copy feedback. Success and failure have matching icons. Put directory, exit code and PGID in native details. Foreground commands also show the explicit timeout in milliseconds, even while running; absent values are labeled Use default without inferring the backend configuration. Background commands omit the foreground timeout. Execution failures and termination signals stay visible outside details; non-error exit codes remain available in details.

Completed foreground results use versioned structured rawOutput fields for output, outcome and execution metadata. No envelope regex parsing remains. Historical text and unknown versions retain their original fallback text without guessing metadata. Unknown exit status is Completed, never Success. Running and cancelled states retain their lifecycle meaning. Exported document mode opens disclosures so content remains available.

Files and decisions

Update ToolGroup, add a focused ShellToolOutput component and its tests, and reuse ToolChrome CSS, shared Button, clipboard helper and copied feedback hook. Add English/Chinese labels and a browser regression in the existing mock-daemon harness. No new dependencies. The structured-result companion design covers producer and transport changes.

Validation and acceptance

Verify successful output is separated from metadata and commands appear once in the expanded body. Verify nonzero exit, errors, signals, multiline commands, raw fallback, empty output, ANSI, copy and document rendering. Use a global CLI baseline plus browser tests with a mocked daemon; these browser tests validate presentation, not real command execution. Run build, typecheck, focused tests and two clean self-audit passes.

Risks and open questions

Historical records have no structured metadata and remain verbatim. This may retain clutter but avoids inventing fields from command output. No open product decisions.

Shell outcome follows the existing exit-error policy: exit 1 from grep/rg/diff/test is a completed negative result, not an execution failure. Web Shell trusts the structured outcome and retains the numeric exit code in details. PostToolUse and PostToolBatch hooks keep string display fields through shared normalization; UI/history retain structured data. Running elapsed time is visible beside the status.

When an exported document has only legacy text, render the command and complete fallback text without category disclosures or inferred execution metadata. Structured directory values are resolved execution paths. Hide exit codes for cancelled, timed-out or signal-terminated commands; keep their outcome and signal visible.