From 171c18b9ca773505206f25336b3455405b80e56e Mon Sep 17 00:00:00 2001 From: creatixchu Date: Fri, 31 Jul 2026 16:23:36 +0800 Subject: [PATCH 1/2] cleanup(web): drop the unimplemented user-message edit control The user bubble's IconActions row carried an edit button with no click handler, no client mutation, and no host operation behind it, advertising an affordance the product cannot honor. The row now renders clock / copy / branch only for both user and assistant chrome, and MessageIconActions loses the `edit` prop with the button. The package README records the missing capability under Known Limitations, the web aria goldens pin the row without the control, and the Agent Note states what must exist before it comes back. --- ...7-31-drop-user-message-edit-stub.i18n.yaml | 6 +++++ .../2026-07-31-drop-user-message-edit-stub.md | 27 +++++++++++++++++++ ...26-07-31-drop-user-message-edit-stub.zh.md | 27 +++++++++++++++++++ apps/web/tests/message-actions.e2e.ts | 6 ++--- .../snapshots/code-mode-round/ui.expected.md | 2 -- .../cordis-tool-round/ui.expected.md | 2 -- .../snapshots/fresh-round-trip/ui.expected.md | 2 -- .../lifecycle-chrome/reloaded.expected.md | 2 -- .../live-interactions/cancel.expected.md | 2 -- .../live-interactions/error-auth.expected.md | 2 -- .../live-interactions/loading.expected.md | 2 -- .../live-interactions/retry.expected.md | 2 -- .../snapshots/message-actions/ui.expected.md | 2 -- .../plan-review/approved.expected.md | 2 -- .../question-composer/answered.expected.md | 2 -- .../queue-actions/collapsed.expected.md | 2 -- .../queue-actions/editing.expected.md | 2 -- .../snapshots/queue-actions/ui.expected.md | 2 -- .../seeded-history/command-row.expected.md | 2 -- .../snapshots/seeded-history/ui.expected.md | 2 -- .../snapshots/steering/mid-steer.expected.md | 2 -- .../snapshots/steering/settled.expected.md | 2 -- .../snapshots/web-search-round/ui.expected.md | 2 -- .../client/ui-conversation/README.i18n.yaml | 4 +-- packages/client/ui-conversation/README.md | 1 + packages/client/ui-conversation/README.zh.md | 1 + .../src/client/chat/MessageIconActions.tsx | 18 +++---------- .../src/client/chat/MessageItem.tsx | 1 - .../tests/chat-branch-tails.spec.tsx | 4 +-- 29 files changed, 73 insertions(+), 60 deletions(-) create mode 100644 .agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.i18n.yaml create mode 100644 .agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md create mode 100644 .agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.zh.md diff --git a/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.i18n.yaml b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.i18n.yaml new file mode 100644 index 0000000000..8cfbcd08c3 --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.i18n.yaml @@ -0,0 +1,6 @@ +# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each +# side as of the last confirmed-consistent state. Both languages carry equal authority; +# after editing either side, bring the other along and re-record with: +# pnpm run verify-translation-pairing --write .agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md +2026-07-31-drop-user-message-edit-stub.md: 5a34be1dd285f4aced9e6cfb2e324b20ec734bed +2026-07-31-drop-user-message-edit-stub.zh.md: 768cb4618b4a85f61e6348f8c6fb6a93d686e7d3 diff --git a/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md new file mode 100644 index 0000000000..5a34be1dd2 --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md @@ -0,0 +1,27 @@ +# Agent Note: Drop the user-message edit stub + +Status: implemented + +English | [中文](2026-07-31-drop-user-message-edit-stub.zh.md) + +## Problem + +The user bubble's IconActions row carried an edit button beside copy and branch. Nothing backed it: the control had no click handler, no client mutation, and no host operation for resending an edited message. A user who found it saw an affordance the product cannot honor. + +## Decision + +`MessageIconActions` renders clock / copy / branch only, and its `edit` prop is gone with the button; `MessageItem` no longer passes it. The user bubble and the assistant chrome now differ only by clock side. The package README records the missing capability under Known Limitations, and the web message-actions golden pins the row without the control. + +The common locale keeps its generic `edit` term, which is shared vocabulary rather than this component's copy. + +Reintroduce the control together with the capability: a client mutation that edits a settled user message and the host behavior that decides what the edited message does to the turn that already consumed it. + +## Alternatives considered + +**Disable the button with a tooltip.** A visible-but-dead control still advertises editing and costs the same explaining; removal is the honest state. + +**Wire it to the queue editor.** The queue edits a message that has not been sent. A settled user message is already in the transcript and in the model's context, so reusing that editor would silently mean something else. + +## Consequences + +Web offers no way to correct a sent message; branching from the message is the nearest available gesture. Reintroduction is a UI-only change once the mutation exists, since the row composes its actions from props. diff --git a/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.zh.md b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.zh.md new file mode 100644 index 0000000000..768cb4618b --- /dev/null +++ b/.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.zh.md @@ -0,0 +1,27 @@ +# Agent Note: 移除 user 消息的编辑存根 + +Status: implemented + +[English](2026-07-31-drop-user-message-edit-stub.md) | 中文 + +## 问题 + +user 气泡的 IconActions 行在复制和分支旁边还有一个编辑按钮,但其背后什么都没有:该控件没有点击处理、没有 client 侧变更,也没有 host 侧重新发送已编辑消息的操作。用户找到它时,看到的是一个产品无法兑现的可供性。 + +## 决策 + +`MessageIconActions` 只渲染时钟/复制/分支,其 `edit` prop 随按钮一并删除;`MessageItem` 不再传入该 prop。现在 user 气泡与 assistant chrome 只在时钟位置上不同。包 README 在 Known Limitations 中记录这项缺失的能力,web 的 message-actions 金样固定了不含该控件的动作行。 + +公共 locale 保留通用的 `edit` 词条:它是共享词汇,而非本组件的文案。 + +重新引入该控件时要与能力一起落地:既需要编辑已定稿 user 消息的 client 变更,也需要 host 侧决定这条编辑后的消息对已经消费过它的轮次意味着什么。 + +## 曾考虑的替代方案 + +**把按钮置灰并加提示。** 一个可见但无效的控件仍在宣告可以编辑,解释成本相同;直接移除才是诚实的状态。 + +**接到队列编辑器上。** 队列编辑的是尚未发送的消息。已定稿的 user 消息已经进入转录和模型上下文,复用该编辑器会让同一个动作悄悄变成另一件事。 + +## 后果 + +Web 没有任何途径修正已发送的消息;从该消息分支是最接近的现有手势。由于动作行的内容完全由 props 组合而来,能力就绪后重新引入只是一次纯 UI 改动。 diff --git a/apps/web/tests/message-actions.e2e.ts b/apps/web/tests/message-actions.e2e.ts index 4d798e11ed..bb58ccefc4 100644 --- a/apps/web/tests/message-actions.e2e.ts +++ b/apps/web/tests/message-actions.e2e.ts @@ -64,14 +64,14 @@ describe('web e2e: message IconActions and clocks on settled history', () => { await expect.poll(() => page.getByText('DONE', { exact: true }).count(), { timeout: 15_000 }).toBe(1) // Focus-reveal the footers (hover:hover keeps them opacity-hidden until - // hover/focus-within). User has three actions; each turn's last content - // assistant has copy + branch. + // hover/focus-within). User and each turn's last content assistant both + // have copy + branch. const copyButtons = page.getByRole('button', { name: 'Copy' }) await expect.poll(() => copyButtons.count(), { timeout: 10_000 }).toBeGreaterThanOrEqual(2) await copyButtons.first().focus() await expect.poll(() => page.getByRole('button', { name: 'Branch into a new conversation' }).count(), { timeout: 5_000 }) .toBeGreaterThanOrEqual(2) - await expect.poll(() => page.getByRole('button', { name: 'Edit' }).count(), { timeout: 5_000 }).toBe(1) + await expect.poll(() => page.getByRole('button', { name: 'Edit' }).count(), { timeout: 5_000 }).toBe(0) }, 60_000) it.skipIf(MODE === 'record')('matches the conversation aria golden with IconActions and clocks', async () => { diff --git a/apps/web/tests/snapshots/code-mode-round/ui.expected.md b/apps/web/tests/snapshots/code-mode-round/ui.expected.md index 5d1979eadf..8769cadd16 100644 --- a/apps/web/tests/snapshots/code-mode-round/ui.expected.md +++ b/apps/web/tests/snapshots/code-mode-round/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - 'button "Think The user wants me to write a single `run_code` program that:"': - img - img diff --git a/apps/web/tests/snapshots/cordis-tool-round/ui.expected.md b/apps/web/tests/snapshots/cordis-tool-round/ui.expected.md index 3ccbdfb332..9f8215568f 100644 --- a/apps/web/tests/snapshots/cordis-tool-round/ui.expected.md +++ b/apps/web/tests/snapshots/cordis-tool-round/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to:": - img - img diff --git a/apps/web/tests/snapshots/fresh-round-trip/ui.expected.md b/apps/web/tests/snapshots/fresh-round-trip/ui.expected.md index 039ecc99ea..d3d0aaaa8e 100644 --- a/apps/web/tests/snapshots/fresh-round-trip/ui.expected.md +++ b/apps/web/tests/snapshots/fresh-round-trip/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to run a simple bash command and reply with \"DONE\".": - img - img diff --git a/apps/web/tests/snapshots/lifecycle-chrome/reloaded.expected.md b/apps/web/tests/snapshots/lifecycle-chrome/reloaded.expected.md index 113f81f9eb..7fdbee0e74 100644 --- a/apps/web/tests/snapshots/lifecycle-chrome/reloaded.expected.md +++ b/apps/web/tests/snapshots/lifecycle-chrome/reloaded.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to reply with a single word. Let me comply.": - img - img diff --git a/apps/web/tests/snapshots/live-interactions/cancel.expected.md b/apps/web/tests/snapshots/live-interactions/cancel.expected.md index eb3742eb34..c5217a3443 100644 --- a/apps/web/tests/snapshots/live-interactions/cancel.expected.md +++ b/apps/web/tests/snapshots/live-interactions/cancel.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - paragraph: partial - text: Stopped - button "Copy": diff --git a/apps/web/tests/snapshots/live-interactions/error-auth.expected.md b/apps/web/tests/snapshots/live-interactions/error-auth.expected.md index 9dcca575de..682135166d 100644 --- a/apps/web/tests/snapshots/live-interactions/error-auth.expected.md +++ b/apps/web/tests/snapshots/live-interactions/error-auth.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - textbox "Message the agent" - button "Commands": - img diff --git a/apps/web/tests/snapshots/live-interactions/loading.expected.md b/apps/web/tests/snapshots/live-interactions/loading.expected.md index ae44167759..43fdd9650c 100644 --- a/apps/web/tests/snapshots/live-interactions/loading.expected.md +++ b/apps/web/tests/snapshots/live-interactions/loading.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - paragraph: partial - status: Deep diving... - textbox "Message the agent" diff --git a/apps/web/tests/snapshots/live-interactions/retry.expected.md b/apps/web/tests/snapshots/live-interactions/retry.expected.md index 4ed6a10c6f..f89148c032 100644 --- a/apps/web/tests/snapshots/live-interactions/retry.expected.md +++ b/apps/web/tests/snapshots/live-interactions/retry.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - group: - status: Retried model request (1/2) · {{duration}} - button "Think The user is asking for a one-sentence description of event sourcing. This is a straightforward knowledge question that doesn't require any skill loading or tool calls.": diff --git a/apps/web/tests/snapshots/message-actions/ui.expected.md b/apps/web/tests/snapshots/message-actions/ui.expected.md index 9aed20cfce..613e9a3605 100644 --- a/apps/web/tests/snapshots/message-actions/ui.expected.md +++ b/apps/web/tests/snapshots/message-actions/ui.expected.md @@ -10,8 +10,6 @@ - tooltip "Copy" - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to read a.txt and b.txt, then reply with \"DONE\". Let me do both reads in parallel.": - img - img diff --git a/apps/web/tests/snapshots/plan-review/approved.expected.md b/apps/web/tests/snapshots/plan-review/approved.expected.md index a81ed0ecd4..8dbc5c95a5 100644 --- a/apps/web/tests/snapshots/plan-review/approved.expected.md +++ b/apps/web/tests/snapshots/plan-review/approved.expected.md @@ -10,8 +10,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - 'button "Think The user wants me to plan a small change to add a `--greeting` flag to a CLI. They explicitly told me not to read or write any files, and to call exit_plan_mode with a short plan. Let me do that directly."': - img - img diff --git a/apps/web/tests/snapshots/question-composer/answered.expected.md b/apps/web/tests/snapshots/question-composer/answered.expected.md index 03c5d84005..6097e7c8e5 100644 --- a/apps/web/tests/snapshots/question-composer/answered.expected.md +++ b/apps/web/tests/snapshots/question-composer/answered.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to use the ask_user_question tool with specific parameters. Let me do exactly that.": - img - img diff --git a/apps/web/tests/snapshots/queue-actions/collapsed.expected.md b/apps/web/tests/snapshots/queue-actions/collapsed.expected.md index 1780e53e48..06aaf9495d 100644 --- a/apps/web/tests/snapshots/queue-actions/collapsed.expected.md +++ b/apps/web/tests/snapshots/queue-actions/collapsed.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - paragraph: partial - status: Deep diving... - button "2 queued messages" diff --git a/apps/web/tests/snapshots/queue-actions/editing.expected.md b/apps/web/tests/snapshots/queue-actions/editing.expected.md index 1811d4d213..bbd4361056 100644 --- a/apps/web/tests/snapshots/queue-actions/editing.expected.md +++ b/apps/web/tests/snapshots/queue-actions/editing.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - paragraph: partial - status: Deep diving... - button "2 queued messages" [disabled] [expanded] diff --git a/apps/web/tests/snapshots/queue-actions/ui.expected.md b/apps/web/tests/snapshots/queue-actions/ui.expected.md index 5786d9d88f..40545d3da7 100644 --- a/apps/web/tests/snapshots/queue-actions/ui.expected.md +++ b/apps/web/tests/snapshots/queue-actions/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - paragraph: partial - status: Deep diving... - list: diff --git a/apps/web/tests/snapshots/seeded-history/command-row.expected.md b/apps/web/tests/snapshots/seeded-history/command-row.expected.md index f722bb36ae..c7bc4699aa 100644 --- a/apps/web/tests/snapshots/seeded-history/command-row.expected.md +++ b/apps/web/tests/snapshots/seeded-history/command-row.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to read a.txt and b.txt, then reply with \"DONE\". Let me do both reads in parallel.": - img - img diff --git a/apps/web/tests/snapshots/seeded-history/ui.expected.md b/apps/web/tests/snapshots/seeded-history/ui.expected.md index 42455b1231..7473e62138 100644 --- a/apps/web/tests/snapshots/seeded-history/ui.expected.md +++ b/apps/web/tests/snapshots/seeded-history/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to read a.txt and b.txt, then reply with \"DONE\". Let me do both reads in parallel.": - img - img diff --git a/apps/web/tests/snapshots/steering/mid-steer.expected.md b/apps/web/tests/snapshots/steering/mid-steer.expected.md index a8816f93d7..5ed6bc55d1 100644 --- a/apps/web/tests/snapshots/steering/mid-steer.expected.md +++ b/apps/web/tests/snapshots/steering/mid-steer.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to use the ask_user_question tool to ask them a specific question with the given parameters. Let me do exactly that.": - img - img diff --git a/apps/web/tests/snapshots/steering/settled.expected.md b/apps/web/tests/snapshots/steering/settled.expected.md index ba2adad29f..7f69aa5078 100644 --- a/apps/web/tests/snapshots/steering/settled.expected.md +++ b/apps/web/tests/snapshots/steering/settled.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - button "Think The user wants me to use the ask_user_question tool to ask them a specific question with the given parameters. Let me do exactly that.": - img - img diff --git a/apps/web/tests/snapshots/web-search-round/ui.expected.md b/apps/web/tests/snapshots/web-search-round/ui.expected.md index 28a9d4fb47..b7ab44b07f 100644 --- a/apps/web/tests/snapshots/web-search-round/ui.expected.md +++ b/apps/web/tests/snapshots/web-search-round/ui.expected.md @@ -9,8 +9,6 @@ - img - button "Branch into a new conversation": - img -- button "Edit": - - img - img - text: Search DeepSeek Harness snapshot search - list: diff --git a/packages/client/ui-conversation/README.i18n.yaml b/packages/client/ui-conversation/README.i18n.yaml index cffb1cc453..f88189a320 100644 --- a/packages/client/ui-conversation/README.i18n.yaml +++ b/packages/client/ui-conversation/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/client/ui-conversation/README.md -README.md: b183aab56a10c3a22eeab31f8b1b0e6b5219beba -README.zh.md: af6427774a048de324d57bc9856f77547e9a03cc +README.md: 3ee0f5efa653ade99c4e5c94dcc94377244346ba +README.zh.md: d8740fb81b0b464c8002119a5080486432200b33 diff --git a/packages/client/ui-conversation/README.md b/packages/client/ui-conversation/README.md index b183aab56a..3ee0f5efa6 100644 --- a/packages/client/ui-conversation/README.md +++ b/packages/client/ui-conversation/README.md @@ -47,6 +47,7 @@ None; this package neither assembles nor sends a provider request. - **Stats-line durations cover the in-window flow only** — LLM and tool wall times fold the snapshot's assistant `timing` and tool call/result pairs, so nodes outside the loaded event window (older history) are not counted. - **Details panel is the minimal form and currently has no entry point** — selected call args/result raw display; the Input/Output/Metadata switch, Prev/Next stepping, and See-in-trajectory deep link are deferred. Tool rows stopped being details-panel click targets and nothing replaced that gesture, so `ChatViewInjected.openDetails` is implemented but uncalled and the panel (including its terminal card) is unreachable in the assembled application; its rendering stays covered by mounting it with a selection directly. - **Assistant per-message paging is a reserved slot** — drawn in the design, not implemented. The finalized content IconActions row (copy / branch / clock) ships under the last content-text assistant of each turn only; mid-turn narration and Think-only nodes stay chrome-free. Branch forks through the turn containing that message, increments the inherited title on the client, and then opens the child, while a fork or rename failure leaves the source selected. +- **Sent user messages cannot be edited** — the user bubble's IconActions row carries clock / copy / branch only. The design's edit control shipped as a stub that no click handler backed, and it was removed until resending an edited message exists end to end ([decision](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md)). - **The sparkle icon for the others tool row is a hand-drawn approximation** — the design glyph's vector geometry is not exportable locally; promotion into ui-primitives waits on an exact export. - **The approval panel's "Always allow this type" is deferred** — durable grants need a grant-storage design; only allow-once/reject answer today. - **TodoPanel truncates long item text to one ellipsized line** — the figma strip has no wrap or expand affordance; full text is not readable inline. diff --git a/packages/client/ui-conversation/README.zh.md b/packages/client/ui-conversation/README.zh.md index af6427774a..d8740fb81b 100644 --- a/packages/client/ui-conversation/README.zh.md +++ b/packages/client/ui-conversation/README.zh.md @@ -47,6 +47,7 @@ todo 两个面就是在该形状上的两个注册项,都是普通注册方插 - **统计行的耗时只覆盖窗口内消息流**:LLM(大语言模型)与工具墙钟时间由快照的 assistant `timing` 与工具 call/result 配对折算,落在已加载事件窗口之外的节点(更早的历史)不计入。 - **详情面板是最小形态,且当前没有入口**:以原始形式显示已选择调用的参数/结果;Input/Output/Metadata 切换、Prev/Next 步进与 See-in-trajectory 深链接暂缓实现。工具行已不再是详情面板的点击目标,且没有任何手势接替它,因此 `ChatViewInjected.openDetails` 虽已实现却无人调用,该面板(含其终端卡片)在组装后的应用中不可达;其渲染仍由直接以选中态挂载它来覆盖。 - **assistant 逐消息分页是预留 slot**:设计中已有图稿,尚未实现。已定稿的内容 IconActions 行(复制/分支/时钟)只挂在每个轮次中最后一条带 text 内容的 assistant 下;轮次中间的叙述与纯 Think 节点不带 chrome。分支会 fork 到包含该消息的轮次末尾,在 client 端递增继承标题后打开子会话,而 fork 或改名失败时源会话保持选中。 +- **已发送的 user 消息无法编辑**:user 气泡的 IconActions 行只有时钟/复制/分支。设计中的编辑控件曾以存根形式上线,没有任何点击处理挂在其上,现已移除,等到编辑后重新发送这条完整链路存在后再提供([决策](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md))。 - **others 工具行的闪光图标是手绘近似版本**:无法在本地导出设计字形的矢量几何;等到存在精确导出后再将其提升到 ui-primitives。 - **审批面板的「始终允许此类」暂缓**:持久授权需要授权存储设计;今天只能回答允许一次/拒绝。 - **TodoPanel 将过长条目截成单行省略号**:figma 条没有换行或展开入口,完整文本无法在行内读完。 diff --git a/packages/client/ui-conversation/src/client/chat/MessageIconActions.tsx b/packages/client/ui-conversation/src/client/chat/MessageIconActions.tsx index dbb8a8628e..cd6b0a36ce 100644 --- a/packages/client/ui-conversation/src/client/chat/MessageIconActions.tsx +++ b/packages/client/ui-conversation/src/client/chat/MessageIconActions.tsx @@ -1,10 +1,9 @@ // Shared IconActions chrome for user and assistant messages: copy live, -// branch wired through onBranch, date-aware clock, -// optional edit stub. +// branch wired through onBranch, date-aware clock. import { useCallback } from 'react' import { - IconBranchOutline16, IconCopyOutline16, IconEditOutline16, Tooltip, + IconBranchOutline16, IconCopyOutline16, Tooltip, } from '@deepseek-ai/dsh-client-ui-primitives' import type { ChatViewSlotProps } from '../contract/slots.ts' import { formatMessageClock, writeClipboard } from './message-chrome.ts' @@ -18,8 +17,6 @@ export interface MessageIconActionsProps { time: number /** Clock before icons (user) or after (assistant). */ clock: 'start' | 'end' - /** When true, append the stub edit control (user bubble). */ - edit?: boolean | undefined /** Fork the session at this message. */ onBranch?: (() => void) | undefined /** Parent layout class composed onto the actions row. */ @@ -30,11 +27,11 @@ export interface MessageIconActionsProps { /** * Copy / branch (/ clock) IconActions row shared by user and assistant chrome. - * @param props - Copy text, event time, clock side, optional edit, branch callback, className. + * @param props - Copy text, event time, clock side, branch callback, className. * @returns The actions row element. */ export function MessageIconActions({ - text, time, clock, edit, onBranch, className, t, + text, time, clock, onBranch, className, t, }: MessageIconActionsProps) { const day = useCalendarDay() const onCopy = useCallback(() => { @@ -58,13 +55,6 @@ export function MessageIconActions({ - {edit === true && ( - - - - )} {clock === 'end' ? clockEl : null} ) diff --git a/packages/client/ui-conversation/src/client/chat/MessageItem.tsx b/packages/client/ui-conversation/src/client/chat/MessageItem.tsx index d271db9989..db9f5d983c 100644 --- a/packages/client/ui-conversation/src/client/chat/MessageItem.tsx +++ b/packages/client/ui-conversation/src/client/chat/MessageItem.tsx @@ -156,7 +156,6 @@ export const MessageItem = memo(function MessageItem({ text={text} time={node.time} clock="start" - edit onBranch={onFork === undefined ? undefined : () => { onFork(node.seq) }} className={css.actions} t={t} diff --git a/packages/client/ui-conversation/tests/chat-branch-tails.spec.tsx b/packages/client/ui-conversation/tests/chat-branch-tails.spec.tsx index 779b925fd9..1d0fb3ebc5 100644 --- a/packages/client/ui-conversation/tests/chat-branch-tails.spec.tsx +++ b/packages/client/ui-conversation/tests/chat-branch-tails.spec.tsx @@ -27,7 +27,7 @@ afterEach(() => { const t: MessageItemProps['t'] = makeTranslate(zh, commonZh) describe('MessageItem arms', () => { - it('user bubbles expose clock / copy / branch / edit; copy writes the text', () => { + it('user bubbles expose clock / copy / branch and no edit; copy writes the text', () => { const writeText = vi.fn().mockResolvedValue(undefined) Object.defineProperty(navigator, 'clipboard', { configurable: true, @@ -47,7 +47,7 @@ describe('MessageItem arms', () => { expect(screen.getByText('14:24')).toBeTruthy() expect(screen.getByRole('button', { name: '复制' })).toBeTruthy() expect(screen.getByRole('button', { name: '在新对话中分支' })).toBeTruthy() - expect(screen.getByRole('button', { name: '编辑' })).toBeTruthy() + expect(screen.queryByRole('button', { name: '编辑' })).toBeNull() fireEvent.click(screen.getByRole('button', { name: '复制' })) expect(writeText).toHaveBeenCalledWith('hello bubble') }) From 2e163527778ee9313642d264400ae1e60ad8aaaa Mon Sep 17 00:00:00 2001 From: creatixchu Date: Fri, 31 Jul 2026 16:34:03 +0800 Subject: [PATCH 2/2] docs(ui-conversation): keep the module header and README at current state --- packages/client/ui-conversation/README.i18n.yaml | 4 ++-- packages/client/ui-conversation/README.md | 2 +- packages/client/ui-conversation/README.zh.md | 2 +- .../client/ui-conversation/src/client/chat/MessageItem.tsx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/client/ui-conversation/README.i18n.yaml b/packages/client/ui-conversation/README.i18n.yaml index f88189a320..4aae948a04 100644 --- a/packages/client/ui-conversation/README.i18n.yaml +++ b/packages/client/ui-conversation/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/client/ui-conversation/README.md -README.md: 3ee0f5efa653ade99c4e5c94dcc94377244346ba -README.zh.md: d8740fb81b0b464c8002119a5080486432200b33 +README.md: 7f428fd50411a8ee3b8e7e133d6465a77681900e +README.zh.md: e591072eb95ed461bb26b6636f00e24ab7ad2dfa diff --git a/packages/client/ui-conversation/README.md b/packages/client/ui-conversation/README.md index 3ee0f5efa6..7f428fd504 100644 --- a/packages/client/ui-conversation/README.md +++ b/packages/client/ui-conversation/README.md @@ -47,7 +47,7 @@ None; this package neither assembles nor sends a provider request. - **Stats-line durations cover the in-window flow only** — LLM and tool wall times fold the snapshot's assistant `timing` and tool call/result pairs, so nodes outside the loaded event window (older history) are not counted. - **Details panel is the minimal form and currently has no entry point** — selected call args/result raw display; the Input/Output/Metadata switch, Prev/Next stepping, and See-in-trajectory deep link are deferred. Tool rows stopped being details-panel click targets and nothing replaced that gesture, so `ChatViewInjected.openDetails` is implemented but uncalled and the panel (including its terminal card) is unreachable in the assembled application; its rendering stays covered by mounting it with a selection directly. - **Assistant per-message paging is a reserved slot** — drawn in the design, not implemented. The finalized content IconActions row (copy / branch / clock) ships under the last content-text assistant of each turn only; mid-turn narration and Think-only nodes stay chrome-free. Branch forks through the turn containing that message, increments the inherited title on the client, and then opens the child, while a fork or rename failure leaves the source selected. -- **Sent user messages cannot be edited** — the user bubble's IconActions row carries clock / copy / branch only. The design's edit control shipped as a stub that no click handler backed, and it was removed until resending an edited message exists end to end ([decision](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md)). +- **Sent user messages cannot be edited** — the user bubble's IconActions row carries clock / copy / branch only, and branching from the message is the nearest gesture. The control returns with the capability behind it: a client mutation over a settled user message, plus the host behavior for the turn that already consumed it ([decision](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md)). - **The sparkle icon for the others tool row is a hand-drawn approximation** — the design glyph's vector geometry is not exportable locally; promotion into ui-primitives waits on an exact export. - **The approval panel's "Always allow this type" is deferred** — durable grants need a grant-storage design; only allow-once/reject answer today. - **TodoPanel truncates long item text to one ellipsized line** — the figma strip has no wrap or expand affordance; full text is not readable inline. diff --git a/packages/client/ui-conversation/README.zh.md b/packages/client/ui-conversation/README.zh.md index d8740fb81b..e591072eb9 100644 --- a/packages/client/ui-conversation/README.zh.md +++ b/packages/client/ui-conversation/README.zh.md @@ -47,7 +47,7 @@ todo 两个面就是在该形状上的两个注册项,都是普通注册方插 - **统计行的耗时只覆盖窗口内消息流**:LLM(大语言模型)与工具墙钟时间由快照的 assistant `timing` 与工具 call/result 配对折算,落在已加载事件窗口之外的节点(更早的历史)不计入。 - **详情面板是最小形态,且当前没有入口**:以原始形式显示已选择调用的参数/结果;Input/Output/Metadata 切换、Prev/Next 步进与 See-in-trajectory 深链接暂缓实现。工具行已不再是详情面板的点击目标,且没有任何手势接替它,因此 `ChatViewInjected.openDetails` 虽已实现却无人调用,该面板(含其终端卡片)在组装后的应用中不可达;其渲染仍由直接以选中态挂载它来覆盖。 - **assistant 逐消息分页是预留 slot**:设计中已有图稿,尚未实现。已定稿的内容 IconActions 行(复制/分支/时钟)只挂在每个轮次中最后一条带 text 内容的 assistant 下;轮次中间的叙述与纯 Think 节点不带 chrome。分支会 fork 到包含该消息的轮次末尾,在 client 端递增继承标题后打开子会话,而 fork 或改名失败时源会话保持选中。 -- **已发送的 user 消息无法编辑**:user 气泡的 IconActions 行只有时钟/复制/分支。设计中的编辑控件曾以存根形式上线,没有任何点击处理挂在其上,现已移除,等到编辑后重新发送这条完整链路存在后再提供([决策](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md))。 +- **已发送的 user 消息无法编辑**:user 气泡的 IconActions 行只有时钟/复制/分支,从该消息分支是最接近的手势。该控件要与其背后的能力一起回归:既需要针对已定稿 user 消息的 client 变更,也需要 host 侧对已经消费过它的轮次给出行为([决策](../../../.agents/notes/implemented/simplification/2026-07-31-drop-user-message-edit-stub.md))。 - **others 工具行的闪光图标是手绘近似版本**:无法在本地导出设计字形的矢量几何;等到存在精确导出后再将其提升到 ui-primitives。 - **审批面板的「始终允许此类」暂缓**:持久授权需要授权存储设计;今天只能回答允许一次/拒绝。 - **TodoPanel 将过长条目截成单行省略号**:figma 条没有换行或展开入口,完整文本无法在行内读完。 diff --git a/packages/client/ui-conversation/src/client/chat/MessageItem.tsx b/packages/client/ui-conversation/src/client/chat/MessageItem.tsx index db9f5d983c..64f47b2f7b 100644 --- a/packages/client/ui-conversation/src/client/chat/MessageItem.tsx +++ b/packages/client/ui-conversation/src/client/chat/MessageItem.tsx @@ -1,5 +1,5 @@ // MessageItem: simple chat nodes — user bubble (right-aligned, with -// clock + copy / branch / edit IconActions), steering (badged bubble), context +// clock + copy / branch IconActions), steering (badged bubble), context // injection, retry disclosure, and unknown-surface JSON rows. import { memo, useEffect, useMemo, useState } from 'react'