867f8dd751
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>