PR #807 collapsed the top #code-agent-summary and per-message debug panels
into a 调试信息 dialog, but the conversation list still showed two hard-coded
System cards (界面模式 / Code Agent 状态) that fed availability into the
agent run path. Both appeared as full <article class="message-card
message-system"> bubbles before any user message on every session load,
contradicting the issue goal of a clean agent / user conversation feed.
- remove the ConversationPanel intro useMemo + [...intro, ...messages]
spread; the conversation list now only contains real agent / user
messages.
- move the static 界面模式 content to a small muted hint line under the
panel title (id=workspace-hint, .conversation-panel-hint).
- the live Code Agent availability snapshot is already covered by the
existing #code-agent-summary + 调试信息 dialog, so it is dropped.
- add a conversation-list empty-state placeholder so the panel keeps
height for layout smoke (messages.length === 0).
- delete the now-orphan MessageRuntimePath / MessageSessionContinuity /
MessagePendingContext components (no remaining callers per rg).
- extend tools/capture-issue-803-noise.mjs to report each .message-card
role plus systemMessageCount / roleCounts so layout-level evidence
can assert "no message-system in the conversation list".
web:check 12 pass / 0 fail; web:layout:build pass (desktop, narrow,
mobile). Issue: pikasTech/HWLAB#803
The Agent workspace (top #code-agent-summary and each agent message card)
exposed too many "未观测" / readiness / providerTrace / runtime-path rows
inline; per-message panels (MessageRuntimePath, MessageSessionContinuity,
MessagePendingContext) ate most of the card width and made the agent trace
events list (the only thing the user really wants to see) read at ~83% of
the card.
This change:
- introduces a reusable <DebugDialog> component (web/hwlab-cloud-web/src/components/shared/DebugDialog.tsx)
that surfaces the full availability / readiness / runnerTrace / raw JSON
payload only when the user clicks a 调试信息 button.
- shrinks codeAgentSummaryRows() in state/code-agent-status.ts to only
return rows with meaningful values; "未观测" / "字段缺失:证据不足" /
"DEGRADED:运行路径字段不完整" / "无"-only readiness blockers are
filtered out of the top summary and remain reachable via the dialog.
- rewrites MessageCard to drop the inline MessageRuntimePath /
MessageSessionContinuity / MessagePendingContext panels and to show a
single compact footer (timestamp + 调试信息 button). The pending running
hint is reduced to a one-line tag instead of a 7-row grid.
- makes .message-trace and .message-trace-events fill the message card so
the trace events list is the dominant element per the issue.
- adds tools/capture-issue-803-noise.mjs so CLI can log into the live or
local Cloud Web, capture the rendered #code-agent-summary / per-message
meta / trace widths into a JSON document, and diff before/after the
refactor.
web:check, web:layout, dev-cloud-workbench-smoke --static, and
dev-cloud-workbench-layout-smoke all pass on the local build.
Issue: pikasTech/HWLAB#803
Co-authored-by: HWLAB Agent <hwlab-agent@pikastech.local>
Fixes HWLAB #775 round-1 regression vs pre-React `app.ts` /
`app-conversation.ts` / `app-device-pod.ts` / `app-trace.ts` /
`code-agent-status.ts`. This PR lays the foundation for rounds 2-7
by restoring three of the three explicitly named regressions:
1. **Inactivity timeout** (the "应该是无活动超时,而非全超时" line)
- `services/api/client.ts` `fetchJson` / `fetchText` now accept
`activityRef`; an internal `schedule()` re-evaluates
`remainingMs = timeoutMs - (now - lastActivityAt)` every 1s, so
long-running fetches stay alive while upstream keeps emitting
trace events. The AbortError now distinguishes "总超时" vs
"无活动超时(idle Ns;waitingFor=…;lastEventLabel=…)".
- Mirrors pre-React `app-device-pod.ts:1219-1293` `fetchJson` contract.
2. **Code Agent status 23 rows** (the "裸 JSON 出现" line)
- New `state/code-agent-status.ts` (`classifyCodeAgentStatusSummary`,
`codeAgentRuntimePathFromMessage`, `codeAgentSummaryRows`) lifts
the 23-row pre-React `codeAgentSummaryRows` into React; rows cover
codeAgent.status, provider/mode/backend, capabilityLevel, session,
sessionId/status, 会话提示, workspace, sandbox, runnerKind,
protocol, implementationType, providerTrace.{command,terminalStatus,
failureKind}, 运行路径语义, toolCalls, skills, conversation facts,
runnerTrace, readiness blockers, last traceId, 当前部署 revision.
- ConversationPanel's `<CodeAgentSummary>` now renders the 23 rows
through `codeAgentSummaryRows(summary)`. Blockers render through a
collapsible "展开 readiness 原始 JSON" disclosure so unmodeled
blockers stay inspectable without dumping bare JSON inline.
3. **Rich trace panel** (the "Trace 过程事件实时滚动,事件渲染等全丢了" line)
- New `components/conversation/MessageTracePanel.tsx` replaces
`ConversationPanel`'s inline `<TracePanel>`: 32-row tail (was 16)
with `traceUiKey` storage, default-open per status, toolbar with
`count / follow / jump-to-bottom / lastEventLabel / last ts / short
traceId`, per-row tone (`tone-border-<tone>` from `event.status`),
follow-on-scroll, follow-on-`pre` body with markdown harden hook,
"等待后端事件" placeholder when events is empty, and
`markTraceScrollIntent`-equivalent scroll handler.
- Pre-React `app-conv.ts:1337-1500` semantics are now rendered through
the same `traceUiKey` storage and a follow/pause toggle.
4. **Beijing time formatting** (the "formatBeijingTime" regression)
- `utils.ts` adds `formatBeijingTime(value, {withSeconds, includeYear})`
using a shared `Intl.DateTimeFormat` Asia/Shanghai formatter; the
pre-existing `formatTimestamp` now delegates to it.
- `MessageCard` and `MessageTracePanel` now render `formatBeijingTime`
in `withSeconds: true` mode so users see `2026-06-03 19:56:20` not
raw ISO `2026-06-03T11:56:20.731Z`.
5. **`api.gateDiagnostics` and `api.cancelAgentMessage` clients** are now
declared alongside the existing `sendAgentMessage` / `getAgentChatResult`
so round 6 can wire `GateView` and round 3 can wire 取消当前请求
without another client surface churn.
## Verification
- `cd web/hwlab-cloud-web && bun run check` passes (Vite build + 2/2 dist
freshness test pass + 12 fresh dist files)
- `bun run scripts/tsc-check.ts` passes (strict React TSX, 0 explicit any)
- `bun test` 2 pass / 0 fail
- `bun run build` 9 dist files verified fresh; `app.js` grew 198671 →
213154 bytes; `index.css` grew 13483 → 15324 bytes
- new `app.js` contains: `activityRef`, `inactivityDetail`,
`MessageTracePanel`, `codeAgentSummaryRows`,
`classifyCodeAgentStatusSummary`, `formatBeijingTime`
- new `index.css` contains: `.message-trace-toolbar`,
`.message-trace-events`, `.message-trace-list`, `.message-trace-row`,
`.message-trace-body`, `.message-trace-empty`, `.message-trace-last`,
`.message-trace-time`, `.message-trace-tone`, `.message-trace-label`,
`.code-agent-summary-rows`, `.code-agent-summary-row`,
`.code-agent-summary-key`, `.code-agent-summary-value`,
`.code-agent-summary-raw`
- `web/hwlab-cloud-web/src/state/code-agent-status.ts` 398 lines, the
other new/edited files are also within the 400-line frontend guard.
Refs: pikasTech/HWLAB#775 (round 1 of 7)
Co-authored-by: HWLAB <ci@hwlab.local>
Fixes HWLAB #759 round-3 v0.2 WebUI issues introduced by the React migration:
1. device-pod right sidebar could not be re-expanded because the toggle button
was nested inside the right sidebar which is fully hidden when collapsed.
Move the toggle button to be a direct child of the right sidebar via a
new anchor button + content wrapper. Add --right-collapsed-width and a
vertical-rl text rotation so the toggle stays visible and accessible
when the right sidebar is collapsed.
2. The Session sidebar and right sidebar resize handles had no event
handlers after the React migration; dragging did nothing. Add a new
useSidebarResize hook with pointer/keyboard handlers, dynamic bounds
based on viewport and opposite sidebar width, localStorage
persistence, and CSS variable injection on the workbench shell.
3. document.querySelector("#command-form > div") (the input shell) was on
the same row as the timeout selects. Restore the original layout by
switching the command-bar to grid-template-areas with the input shell
on its own row and the three selects on a second row.
4. Code Agent was unusable from the React UI because the 202 response has
status=running and no reply text; the React UI marked the message as
completed with the fallback empty body. Add a polling loop in the
workbench store that follows resultUrl until status reaches a terminal
value, and surface assistantText / reply.content from the polled
AgentChatResultResponse. Add AgentChatResultResponse, AgentChatReply
and AgentRunProvenance types plus a getAgentChatResult API method.
Verified locally on G14:web/hwlab-cloud-web: bun run check (12 fresh
dist files), bun run scripts/tsc-check.ts (strict React TSX, 0 explicit
any), bun test (2 pass / 0 fail).
Co-authored-by: HWLAB <ci@hwlab.local>