* 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>
5 KiB
Shell command card
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.