Files
pikasTech-HWLAB/web
Lyon 0740712a57 fix(web): v0.2 round-6 workbench: message actions panel (cancel/retry/replay) (HWLAB #775 round 3) (#784)
Continues HWLAB #775 round 3 by adding the message-actions panel
that the React migration dropped from `app-conv.ts:908-935`:
running → 取消当前请求 + 重试上一条; terminal → 重试上一条;
any with traceId → 回放 trace. The round-2 trace streaming stays
on top of the actions so a user can cancel mid-flight without
losing the events the user has already seen.

## 修复对照

| 类别 | 迁移前 (`893f46bc`) | 迁移后 (round 3) | 状态 |
|---|---|---|---|
| **消息动作面板** | `app-conv.ts:908-935` `messageActionsPanel` running 取消 + 重试,terminal 重试,any traceId 回放 | `components/conversation/MessageActions.tsx`:同结构按钮 + `traceReplayStatus` 行内展示 |  对齐 |
| **取消当前请求** | `app-conv.ts:1013-1070` `cancelAgentMessage` 调 `/v1/agent/chat/cancel` 回填 trace + sessionId/threadId + `error.code = "codex_stdio_canceled"` | `state/runner-actions.ts:cancelAgentMessageAction` 同路径,dispatch `message:replace` |  对齐 |
| **重试上一条** | `app-conv.ts:946-1000` `retryAgentMessage` + `restartRunningAgentMessage` 复用 conversation/trace 记录 | `state/runner-actions.ts:retryAgentMessageAction` 走 `submitMessage(retryInput)` |  对齐 |
| **回放 trace** | `app-conv.ts:1073-1125` `replayAgentTrace` / `replayFullTrace` 调 `/v1/agent/chat/trace/<id>` | `state/runner-actions.ts:replayAgentTraceAction` 走 `state/runner-trace.ts:replayFullTrace`,dispatch `message:trace` + `message:trace-status` |  对齐 |
| **retryInput 保留** | `app-conv.ts:1019` 在 `cancelAgentMessage` 末尾 `el.commandInput.value = message.retryInput` | `state/workbench.ts:submitMessage` 把 `value` 注入 `pending.retryInput`,round-trip 通过 reducer 保留 |  对齐 |

## 改动

- 新增 `web/hwlab-cloud-web/src/components/conversation/MessageActions.tsx`(44 行)
- 新增 `web/hwlab-cloud-web/src/state/runner-actions.ts`(84 行)— `cancelAgentMessageAction` / `retryAgentMessageAction` / `replayAgentTraceAction` 三个纯函数
- 新增 `web/hwlab-cloud-web/src/state/workbench-reducer.ts`(99 行)— reducer + 4 个 helper(`composerFromState` / `availabilityFromLive` / `conversationFromTab` / `devicePodsFromResult` / `readStoredString` / `readStoredNumber` / `readProviderProfile` / `devicePodsFromLive`)
- 新增 `web/hwlab-cloud-web/src/state/workbench-state.ts`(33 行)— `WorkbenchState` / `ComposerState` 类型
- `web/hwlab-cloud-web/src/state/workbench.ts`(319 行,< 400 前端 guard)— 删除冗余 reducer / helpers,import 上面 3 个文件,导出 `devicePodsFromLive` re-export,新增 `cancelAgentMessage` / `retryAgentMessage` / `replayAgentTrace` 三个 hook callback
- `web/hwlab-cloud-web/src/components/conversation/ConversationPanel.tsx` — `MessageCard` 接 `onCancel` / `onRetry` / `onReplayTrace` props
- `web/hwlab-cloud-web/src/App.tsx` — `<ConversationPanel>` 接 `onCancelMessage` / `onRetryMessage` / `onReplayTrace` 三个事件
- `web/hwlab-cloud-web/src/types/domain.ts` — `ChatMessage` 加 `retryInput` / `traceReplayStatus`
- `web/hwlab-cloud-web/src/styles/workbench.css` — `.message-actions` / `.message-action` / `.message-action-status`

## 验收

- `bun run check` 通过(Vite build + 2/2 dist freshness test pass + 12 fresh dist files)
- `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` 218185 → 221256 bytes;`index.css` 15324 → 16041 bytes
- dist `app.js` 含 `cancelAgentMessage` / `retryAgentMessage` / `replayAgentTrace` / `message-actions` / `message-action-cancel` / `message-action-retry` / `message-action-trace` / `message-action-status` 等关键字
- 所有改动文件 < 400 行前端 guard

Refs: pikasTech/HWLAB#775 (round 3 of 7)

Co-authored-by: HWLAB <ci@hwlab.local>
2026-06-03 23:00:28 +08:00
..