From 527c5b0dd5b17a39591b5a7ee698e26f3e37b44e Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Wed, 3 Jun 2026 23:26:09 +0800 Subject: [PATCH] fix(web): v0.2 round-7 workbench: message pending/session-continuity/runtime-path context panels (HWLAB #775 round 4) (#785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Continues HWLAB #775 round 4 by restoring the three message-level context panels that the React migration dropped: - `messagePendingContextPanel` (`app-conv.ts:1228`) - `messageSessionContinuityPanel` (`app-conv.ts:1183`) - `messageRuntimePathPanel` (`app-conv.ts:1268`) ## 修复对照 | 类别 | 迁移前 (`893f46bc`) | 迁移后 (round 4) | 状态 | |---|---|---|---| | **Pending context 面板** | `app-conv.ts:1228` `messagePendingContextPanel`(traceId/conversation/session/thread/activityTimeout) | `components/conversation/MessagePendingContext.tsx`:grid 2 列 + activity timeout 用 `formatDuration` | ✅ 对齐 | | **Session continuity 面板** | `app-conv.ts:1183` `messageSessionContinuityPanel`(conversation/session/thread/lifecycle/retryOf/missing/changed) | `components/conversation/MessageSessionContinuity.tsx`:grid 2 列 + lifecycleHint/lastEvent | ✅ 对齐 | | **Runtime path 面板** | `app-conv.ts:1268` `messageRuntimePathPanel`(rows + missingFields + compact details) | `components/conversation/MessageRuntimePath.tsx`:复用 round-1 `codeAgentRuntimePathFromMessage`,加 missingFields 行 | ✅ 对齐 | ## 改动 - 新增 `web/hwlab-cloud-web/src/components/conversation/MessagePendingContext.tsx`(43 行) - 新增 `web/hwlab-cloud-web/src/components/conversation/MessageRuntimePath.tsx`(37 行) - 新增 `web/hwlab-cloud-web/src/components/conversation/MessageSessionContinuity.tsx`(58 行) - `web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx` — `MessageCard` 顺序:title → body → pending/continuity/runtime → footer → trace → actions - `web/hwlab-cloud-web/src/App.tsx` — `` 接 `codeAgentTimeoutMs` - `web/hwlab-cloud-web/src/styles/workbench.css` — `.message-pending-context` / `.message-session-context` / `.message-runtime-path` 共享 grid 样式 ## 验收 - `bun run check` 通过(Vite build + 2/2 dist freshness test pass) - `bun run scripts/tsc-check.ts` 通过(strict React TSX, 0 explicit any) - `bun test` 2 pass / 0 fail - `bun run build` 9 dist files verified fresh;`app.js` 221256 → 226176 bytes;`index.css` 16041 → 17152 bytes - dist `app.js` 含 `message-pending-context` / `message-session-context` / `message-runtime-path` / `message-pending-grid` / `message-session-grid` / `message-runtime-grid` - 所有改动文件 < 400 行前端 guard Refs: pikasTech/HWLAB#775 (round 4 of 7) Co-authored-by: HWLAB --- web/hwlab-cloud-web/src/App.tsx | 2 +- .../conversation/ConversationPanel.tsx | 12 +++- .../conversation/MessagePendingContext.tsx | 43 ++++++++++++++ .../conversation/MessageRuntimePath.tsx | 37 ++++++++++++ .../conversation/MessageSessionContinuity.tsx | 59 +++++++++++++++++++ web/hwlab-cloud-web/src/styles/workbench.css | 12 ++++ 6 files changed, 161 insertions(+), 4 deletions(-) create mode 100644 web/hwlab-cloud-web/src/components/conversation/MessagePendingContext.tsx create mode 100644 web/hwlab-cloud-web/src/components/conversation/MessageRuntimePath.tsx create mode 100644 web/hwlab-cloud-web/src/components/conversation/MessageSessionContinuity.tsx diff --git a/web/hwlab-cloud-web/src/App.tsx b/web/hwlab-cloud-web/src/App.tsx index f0e1c3e3..3a7583a2 100644 --- a/web/hwlab-cloud-web/src/App.tsx +++ b/web/hwlab-cloud-web/src/App.tsx @@ -107,7 +107,7 @@ export function App(): ReactElement { onKeyDown={sessionResize.onKeyDown} />
- {route === "workspace" ? void navigator.clipboard?.writeText(store.activeConversationId ?? "")} onCancelMessage={(id) => void store.cancelAgentMessage(id)} onRetryMessage={(id) => void store.retryAgentMessage(id)} onReplayTrace={(id) => void store.replayAgentTrace(id)} /> : null} + {route === "workspace" ? void navigator.clipboard?.writeText(store.activeConversationId ?? "")} onCancelMessage={(id) => void store.cancelAgentMessage(id)} onRetryMessage={(id) => void store.retryAgentMessage(id)} onReplayTrace={(id) => void store.replayAgentTrace(id)} /> : null} {route === "skills" ? : null} {route === "gate" ? : null} {route === "help" ? : null} diff --git a/web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx b/web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx index 3231241e..22d433e3 100644 --- a/web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx +++ b/web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx @@ -8,6 +8,9 @@ import { codeAgentSummaryRows, classifyCodeAgentStatusSummary } from "../../stat import { StateTag } from "../shared/StateTag"; import { MessageTracePanel } from "./MessageTracePanel"; import { MessageActions } from "./MessageActions"; +import { MessagePendingContext } from "./MessagePendingContext"; +import { MessageRuntimePath } from "./MessageRuntimePath"; +import { MessageSessionContinuity } from "./MessageSessionContinuity"; interface ConversationPanelProps { messages: ChatMessage[]; @@ -20,7 +23,7 @@ interface ConversationPanelProps { onReplayTrace(messageId: string): void; } -export function ConversationPanel({ messages, availability, live, chatPending, onCopySession, onCancelMessage, onRetryMessage, onReplayTrace }: ConversationPanelProps): ReactElement { +export function ConversationPanel({ messages, availability, live, chatPending, codeAgentTimeoutMs, onCopySession, onCancelMessage, onRetryMessage, onReplayTrace }: ConversationPanelProps & { codeAgentTimeoutMs: number }): ReactElement { const intro = useMemo(() => [ { id: "intro-mode", @@ -56,7 +59,7 @@ export function ConversationPanel({ messages, availability, live, chatPending, o
- {[...intro, ...messages].map((message) => onCancelMessage(message.id)} onRetry={() => onRetryMessage(message.id)} onReplayTrace={() => onReplayTrace(message.id)} />)} + {[...intro, ...messages].map((message) => onCancelMessage(message.id)} onRetry={() => onRetryMessage(message.id)} onReplayTrace={() => onReplayTrace(message.id)} />)}
@@ -98,7 +101,7 @@ function CodeAgentSummary({ availability, live, latestMessage }: { availability: ); } -function MessageCard({ message, onCancel, onRetry, onReplayTrace }: { message: ChatMessage; onCancel(): void; onRetry(): void; onReplayTrace(): void }): ReactElement { +function MessageCard({ message, codeAgentTimeoutMs, onCancel, onRetry, onReplayTrace }: { message: ChatMessage; codeAgentTimeoutMs: number; onCancel(): void; onRetry(): void; onReplayTrace(): void }): ReactElement { const html = renderMessageMarkdown(message.text); const traceKey = `hwlab.workbench.trace-open.${message.traceId ?? message.id}`; return ( @@ -111,6 +114,9 @@ function MessageCard({ message, onCancel, onRetry, onReplayTrace }: { message: C {statusLabel(message.status)}
+ {message.role === "agent" && message.status === "running" ? : null} + {message.role === "agent" && message.status !== "running" ? : null} + {message.role === "agent" ? : null}