Files
hermes-ui/docs/chat-development-todo.md
T
toor 5e1003ceb7
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s
replace the monochrome theme with the CYBER neon-cyan skin
The project shipped a black-and-white theme that was only half converted:
the login page looked right, the message page was halfway, and the
settings page had not been started. This finishes the move to the CYBER
reference in prototype_reference/.

Colors now come from a single token source (styles/variables.scss), where
every semantic color is declared twice: once as OKLCH for the CSS, and
once as an RGB triple so translucent variants can be built as
rgba(var(--*-rgb), alpha). Cyan is the system itself, amber means the user
has to intervene, green means the machine is working, and red only ever
means something broke. The RGB triples are derived from the OKLCH values
so the two declarations cannot drift apart.

Pages adopt the .cy-* shell classes from the reference (view, panel,
kpis, tabs, grid, table, field) instead of ad-hoc markup, which is what
makes 19 of 26 views consistent. The remaining seven are deliberately
bespoke: chat streams, the kanban board, the workflow canvas, the
terminal, and the missing-agent screen.

The chart palette and the kanban column colors move into single-source
modules so they cannot drift either. A new guard test rejects raw hex
colors, named colors, and literal RGB triples anywhere in the client
source, with an explicit exemption list for the places that genuinely
cannot read a CSS variable. The existing chat semantics spec keeps the
chat chain honest.

No behavior changes: no logic, no i18n keys, no data structures, and the
/chat-run event contract is untouched.
2026-10-20 11:17:46 +08:00

9.8 KiB
Raw Blame History

对话页面待开发事项

对话台(ChatView)是全项目离 CYBER 原型最远的一页。设置页那套骨架已经落地, 但对话台没有套上 —— 全仓库只有 SettingsView.vue 在用 cy-* 骨架类。

本文记录已核实的差距和推进顺序。所有条目均已对照 prototype_reference/hermes-ui-cyber-chat.html 与真实组件确认,不是推测。

进度:P0 / P1 / P2 已全部完成(2026-10-19)。变更片段见 chat-chain-changes/2026-10-19-chat-cyber-skeleton-pass.md 与 chat-chain-changes/2026-10-19-three-colour-semantics.md。 下方各条目已标注实测结果;与真实代码不符的旧记录就地更正并说明原因。

为什么对话台排在最前面

对话台是结构最复杂的一页:一个页面里有会话列表、气泡流、审批卡、输入区、 右侧两个面板,六种结构各自的视觉规则都不同。骨架层没套上来,意味着这六块 各自沿用迁移前的样子,霓虹暗色的辨识度出不来。

令牌层和控件层已经达标 —— styles/global.scss 里的 neon-sheen、 neon-pulse、各处 text-shadow 都在。缺的是页面骨架层和组件级语义配色, 也就是原型第 3、7、9 三节。

现状:骨架类使用情况

注意:本节记录的是 P0/P1 动工之前的基线。对话台最终没有套用 cy-view / cy-panel 这类通用骨架类 —— CYBER 语义是按「每种颜色只承担 一种含义」逐组件落的(见下文 P1),直接套骨架类反而会把语义抹平。 真正补上的是 global.scss 里的 .cy-led 与 @keyframes live-ring。

cy-view / cy-panel / cy-tabs / cy-sec-t 的全仓库使用点:

文件 位置
views/hermes/SettingsView.vue cy-tabs、cy-panel、cy-panel-b
styles/global.scss 定义处

对话台相关组件 —— ChatPanel.vue、MessageList.vue、MessageItem.vue、 ChatInput.vue、SessionListItem.vue —— 一个都没用。

任务清单

P0 · 修 rainbow-glow(违反三色语义规则)✅ 已完成

一次动画里四种语义色同时在闪,直接违反「同屏内每种颜色只承担一种含义」。 硬编码值,未走令牌。

三处重复定义,需要收敛成一处:

文件 行
components/hermes/chat/MessageItem.vue 1523(定义)、1451(调用)
components/hermes/chat/SessionListItem.vue 409(定义)、395(调用)
components/hermes/group-chat/GroupMessageItem.vue 1051(定义)、1114(调用)

原色值循环:#ff6b6b → #feca57 → #48dbfb → #ff9ff3 → 回环。

处理结果:三处本地 @keyframes rainbow-glow 全部删除(约 130 行重复), 改用 global.scss 里单一定义的 @keyframes live-ring —— 荧光绿 (--success,语义为「机器在动」)单色呼吸,不再循环。.speech-playing 与 .streaming 两类「机器正在动」的指示形态从此共用这一个动画。

P1 · 组件级语义配色 ✅ 已完成

项 原型 真实实现(更新于 2026-10-19)
发送键扫光 原型 133-140:28×26,青管壁 + sheen 每 3.4s 扫过 已完成。移除 border: 0 !important + box-shadow: none !important(原本把 neon-tube 整个抹平),恢复全站霓虹管 + 扫光;禁用态不再硬编码 #9f9f9f 灰块,走全局熄灭态;新增 .send-button--stop 琥珀橙中断态
气泡 role 配色 原型 216-227:用户=青、助手=绿,助手气泡左缘一道 lime-line 此前记录有误,实为已完成。MessageItem.vue:1310 用户气泡 border-right: 2px solid rgba(var(--accent-primary-rgb), 0.45);助手气泡 border-left: 2px solid var(--success-line);.message-bubble.system 琥珀橙边 + 橙底;.agent-error 用 $error。由 2026-10-19-three-colour-semantics.md 完成
LED 指示灯 原型 151-156:7px 圆点 + 发光 + 呼吸动画 已完成。global.scss 新增 .cy-led(7px 圆点),绑定真实 appStore.connected:连通=绿 + led-breathe 呼吸,断开=红且静止(死连接不该看起来还在动)。挂在 ChatPanel.vue 顶栏标题后
会话列表当前项 原型 190-192:青软底 + 左侧 2px 发光条 已完成。SessionListItem.vue 的 .session-item.active 从 box-shadow: 0 0 0 3px 描边改为青软底 + inset 2px 0 0 左侧发光条(用 inset 而非 border-left,避免挤动整行内容宽度)
顶栏青色微光 原型 200-201:radial-gradient 压顶 已完成。ChatPanel.vue 的 .chat-header 压一层 radial-gradient(120% 160% at 50% 0%, rgba(var(--accent-primary-rgb), 0.07), transparent 70%)。用 radial 而非 linear —— linear 会让整条边均匀发亮,反而没有「压顶」的层次
审批卡橙区 原型 264-267:橙边 + 内发光 此前记录有误,实为已完成。MessageList.vue 的 .approval-float-panel 已用 var(--warning-line) 边框 + --warning-soft 底 + inset 0 0 22px rgba(var(--warning-rgb), 0.06) 内发光 + @keyframes approval-pulse。由 2026-10-19-three-colour-semantics.md 完成
上下文余量条 原型 273-278:绿→橙→红三段 此前记录为「待确认」,实为已完成。ChatInput.vue:1061-1064 按 usagePercent 分三段:默认绿、>60%~80% 转 context-bar-warn(橙)、>80% 转 context-bar-danger(红)

P2 · 响应式 ✅ 已完成

原型 166-177 定义了两档断点:

  • ≤1180px:Outline 从挤压主区改为浮层覆盖(position: absolute) —— 已完成。OutlinePanel.vue 在 ≤1180px 下改 position: absolute + z-index: 20 + 左侧投影;≤768px 进一步收窄为 min(280px, 86vw)。 右上角的 Outline 按钮本身就是开关,不需要额外关闭控件。
  • ≤900px:顶栏 .ws-tag / 工作区徽标隐藏 —— 已完成。 ChatPanel.vue 在 ≤900px 下 .workspace-badge { display: none }。

与原建议的一处偏离:原型在 ≤900px 还要求「会话侧栏整体隐藏」,未采纳。 真实实现的会话侧栏由顶栏 toggle 按钮控制显隐,隐藏整列后用户将无法再打开 —— 比挤一点更糟。窄屏下改为只隐藏次要信息(工作区徽标),侧栏交给 toggle。

核实记录:真实实现原本只有 $breakpoint-mobile(768px)一档断点, 不存在 ≤1180px 的等价实现。

已知原型侧问题(不是待开发项)

以下原型自身与真实实现不符,接入时以真实实现为准,不要照抄原型:

  • 会话来源标签:原型列了 8 种,真实只有 4 种 (api_server / cli / global_agent / workflow,见 stores/hermes/chat.ts)。原型里的 cron / channel / group_chat / terminal / file / kanban 不存在。
  • moa 作为气泡 role:原型写进「role 全集」,但真实 Message.role 是 5 元联合类型(stores/hermes/chat.ts:47)。moa 是 display_role, 渲染时被映射成 system(同文件 :483)。原型的 .bubble-row.moa 和 AV.moa = '◇' 都应删。
  • Outline 的「附件」区块:原型 578-580 有,真实 OutlinePanel.vue:82-111 只产出「用户提问 + h1/h2/h3 标题」两类条目,没有附件概念。
  • 会话列表 ⌕ 搜索按钮:原型 498 有,全项目无会话搜索功能。
  • 顶栏副标题 01JQ8F2K · default profile:原型 618 有,真实 header 只有 单个 headerTitle 字符串(ChatPanel.vue:307-311),无第二行。
  • m.reasoning 作为消息字段:原型当作字段,实际是 utils/thinking-parser.ts:51 从 content 里正则摘 <think> 标签得到。 折叠交互是真的,数据结构是假的。
  • ⇤ 语义错位:原型 615 画成「返回」,真实同位置是切换会话侧栏显隐。
  • ~/work/hermes-ui 完整路径:真实 workspace-badge 只显示 basename (ChatPanel.vue:1599)。
  • 顶栏常驻 streaming tag:真实 streaming 标记在会话列表项上 (ChatPanel.vue:1209),不在 header。

执行顺序建议(已执行)

  1. P0 rainbow-glow ✅ —— 三处收敛成一处,删约 130 行重复。
  2. P1 组件级语义配色 ✅ —— 逐块推进,每块单独验证。
  3. P2 响应式 ✅ —— 在 P1 布局稳定后落地。

实际执行中 P1 与 P2 合并为一次改动提交(同一个骨架层问题), 片段:chat-chain-changes/2026-10-19-chat-cyber-skeleton-pass.md。

验证基线

改动前后都应跑:

npm run harness:check
npm run test          # 当前 277 文件 / 2047 通过
npm run test:e2e      # 当前 46 通过
npm run build

chat/ 属聊天链,改动需要 docs/chat-chain-changes/<date>-<slug>.md 片段, harness:check 会强制校验。

2026-10-19 实测结果

检查 结果
harness:check 通过(含 chat-chain 片段校验)
test(tests/client + tests/shared) 通过 —— 108 文件 / 659 测试
test:e2e 通过 —— 35 项
build 通过
浏览器实测 通过 —— LED 两态、发送键三态(启用 / 中断 / 禁用)、当前会话项光条、≤1180px Outline 浮层、≤900px 徽标隐藏,均已逐项核对计算样式

上面这份「2026-10-19 实测结果」是对话台改动的原始记录,写于本轮修复之前。 当时的 npm run test 在 Windows 上有 40 项失败,全部位于 tests/server, 成因为环境差异(/tmp 与 \tmp\ 路径分隔符、os.homedir() 在 Windows 读 USERPROFILE 而非 HOME、测试端点写死了 POSIX IPC 形态)。 这些失败已在 2026-10-19 全部修掉:改成平台无关的等价断言,而不是跳过用例, 因此 Linux / macOS 的行为不受影响。当前 npm run test 在 Windows 上 0 失败。