Files
ycode/docs/视觉对齐实测.md

34 KiB
Raw Permalink Blame History

WorkBuddy 界面实测数据(YCode 视觉对齐依据)

历史实测参照,尚需通过 REA 复核。现行目标是视觉、交互与功能 1:1;本文旧版分级中的“不做/不可能”不能用于缩减范围。后续所有原版采集使用 REA,禁止直接运行 wb-* CDP 脚本绕过。接手记录见 接手状态-2026-10-15.md。

采集方式:CDP(WORKBUDDY_REMOTE_DEBUGGING_PORT=9223)+ scripts/wb-capture.mjs / scripts/wb-tree.mjs 采集环境:WorkBuddy 37.10.3-42,Windows,视口 1334 × 901,DPR 1,zoom 1.000,浅色主题 采集时间:2026-10-15 原始产物:%USERPROFILE%\.ycode\captures\(含真实对话,不入库)

说明:以下均为运行时 computed style 实测值,不是静态 CSS 推断。 换窗口尺寸或字号档位需重新采集。


0. 参照文档与对齐分级

同项目源头文档已复制到 docs/reference/,不必再跳到别的仓库:

文档 用途
workbuddy-cdp.md 采集 SOP(开启调试端口、采集流程、边界与常见问题)
workbuddy-chat-layout.md 对话区布局实测(字号 token、宽度约束、滚动策略)
workbuddy-composer-reference.md 输入区专项参考
ygent-ui-pixel-parity-feasibility-2026-10-14.md 像素级对齐可行性结论与分级目标
ygent-font-parity.md 字体与六档字号对齐
ygent-sidebar-parity.md / ygent-settings-parity.md / ygent-model-composer-parity.md 分区对齐记录
ygent-workbuddy-render-audit-2026-10-08.md 40 项逐项差异审计(含坐标/字库/间距)
ygent-workbuddy-ai-gap-2026-10-14.md 能力差距盘点
ygent-chat-parity.md 对话区对标路线图
ygent-chat-interaction-parity.md L3 动态交互对标与验收(必测序列、事件与渲染状态)
ygent-chat-stage-summary-2026-10-08.md 分阶段汇总
ygent-streaming-activity.md 流式活动播报
ygent-chat-edit.md / ygent-chat-approval-questions.md 消息编辑 / 审批提问
ygent-rich-content.md / ygent-attachments.md 富内容与附件
ygent-session-titles.md / ygent-shell-settings.md 会话标题 / 壳层设置
ygent-debug.md ygent 侧 CDP 调试
workbuddy-independent-conversations-2026-10-08.md / workbuddy-reference-import.md 独立会话与参照导入
ygent-岗位与项目团队方案.md 岗位/团队方案(后续扩展参考)

对齐分级(直接采用其结论,避免重复踩坑)

级别 目标 可行性
L1 几何对齐 同视口/同字号下关键锚点与尺寸 ≤1px 取整误差 ✅ 可达
L2 静态像素对齐 L1 + 图标路径/颜色/阴影/滚动条 ⚠️ 90%+,宿主原生控件除外
L3 动态交互一致 事件序列、折叠时机、滚动、取消/恢复 ⏳ 真正的目标,未完成
L4 全局 100% 像素一致 含宿主 chrome、平台入口、跨机器字形 ❌ 不可能,不做

明确不做(沿用其约定)

  • 不伪造消耗 / 模型元数据 / 产物计数以凑齐视觉
  • 不复制平台商业入口(邀请卡、账号区)与无效操作按钮
  • 不为对齐硬补高度
  • 不把静态像素通过宣称为动态交互通过
  • 不把任一端的绝对 y 差直接当作要修的 margin

已知的跨宿主差异(不可消除)

  • 渲染引擎版本不同 → 默认 UA 样式、原生滚动条伪元素、字体回退顺序可能不同
  • 系统字库为各机本地安装,不随项目分发 → 跨机器像素一致不成立
  • 顶栏 chrome 与侧栏数据层级属宿主结构差,不应为复制而破坏已对齐的内部坐标

1. 顶层布局

区域 实测
菜单栏 高 30px(.codebuddy-menubar)
左栏 .conversation-sidebar x=0 y=30 280 × 871
主内容区 宽 1054px(1334 − 280)
右栏(详情面板) .detail-panel-container 宽 1px —— 默认收起

2. 左栏(侧栏)

元素 实测值
容器 .conversation-list 280 × 871,背景 rgb(247,247,247) = #f7f7f7
头部 .conversation-list-header 279 × 288,padding: 0 12px 20px,gap: 2px,flex column
品牌行 .conversation-list-logo-row 255 × 64(min-height 40),gap: 4px,align center
品牌标题 .logo-*-title 14px / 700,行高 22px,色 rgba(0,0,0,.9),左边距 12px
版本行 高 18,padding-left: 12px,margin-top: -4px,gap: 6px
版本徽标 10px,行高 18,letter-spacing: .2px,色 rgba(0,0,0,.5)
次级按钮 .wb-button--secondary 98 × 28,padding: 4px 6px 4px 8px,gap: 2px,背景 #f2f2f2,色 rgba(0,0,0,.7),边框 1px #ebebeb,圆角 100px,字号 12px / 500
导航按钮 .conversation-list-tab-button 255 × 32,padding: 5px 12px,gap: 8px,圆角 8px,图标 16 × 16,标签 14px / 行高 22
Beta 徽标 10px,大写,padding: 0 5px,边框 1px #dedede,圆角 100px,色 rgba(0,0,0,.45),行高 16
分组标签 .conversation-section-label 255 × 30,padding: 5px 12px,圆角 8,背景 #f7f7f7,gap: 4px
分组文字 12px / 600,行高 20,色 rgba(0,0,0,.5);形如「任务 (1)」
分组折叠箭头 14 × 14,色 rgba(0,0,0,.3)
分组小按钮 20 × 20,圆角 4,色 rgba(0,0,0,.5)
会话项 .conversation-item 255 × 31;内层 .cb-agent-card padding: 5px 12px、圆角 8px
会话项标题 14px / 行高 21,字重 400,色 rgba(0,0,0,.9),左 24
会话项时间 11px / 行高 20,色 rgba(0,0,0,.5),右对齐(同一行,非第二行)

3. 对话区

元素 实测值
.cr-message-list x=280 y=94 1054 × 639,基础字号 13px
.cr-message-list__content 宽 832(max-width 832),padding: 0 40px → 正文列 752
.cr-agent 752 宽,flex column,色 rgba(0,0,0,.9),13px / 行高 19
.cr-agent__header 752 × 24.5,margin-bottom: 12px,gap: 10px,align center
.cr-markdown 17.143px / 行高 30.0002px
.cr-markdown p 15.0001px / 26.2502px,margin-bottom: 12px
.cr-self-message flex row,justify-content: flex-end,align-items flex-start,gap: 8px
.cr-self-bubble min-width: 40px,max-height: 310px,padding: 8px 12px,gap: 4px,背景 rgb(242,242,242),border-radius: 16px 16px 0,13px / 19px
.cr-collapse__header 高 26.25,gap: 8px,max-width: 100%,色 rgba(0,0,0,.5),15px / 26.25px

主文字色是 rgba(0,0,0,.9),不是 #000。


4. 输入区(最容易做错的地方)

元素 实测值
.cr-input-box x=415 y=733 784 × 134,z-index: 16
.cr-input-box__main border-radius: 24px,gap: 4px,flex column
.cr-input-container 背景 rgb(255,255,255)(白底,不是渐变);边框 1px rgb(230,230,230);圆角 24px;min-height: 96px;padding-top: 12px
阴影 双层:rgba(0,0,0,0.03) 0 16px 32px -8px, rgba(0,0,0,0.06) 0 2px 4px -4px
聚焦态 边框色变 rgba(0,0,0,.15)
.cr-input-editor-host 782 × 64(min-height 64),padding: 0 16px
输入文字 14px / 行高 21
.cr-input-toolbar 782 × 56,padding: 12px,gap: 8px,justify-content: space-between,min-height 32
.cr-input-toolbar__right 286 × 32,gap: 4px,背景 #fff
.cr-send-button 32 × 32,border-radius: 50%

几何关系:12 (padding-top) + 64 (编辑区) + 56 (工具栏) ≈ 134 ✓;输入框 784 = 832 − 48。

⚠️ 注意区分两个 composer: --wb-bg-input-slot-gradient(linear-gradient(180deg,#ebebeb,#f5f5f5))属于 .wb-home-composer__input-slot(首页新建对话); 会话内输入框 .conversation-input__box 明确定义 background: 0 0(透明)+ 白底容器 + 描边。两者不可混用。


5. 右栏:详情面板(展开态实测)

采集时视口变为 1638 × 901(用户展开面板后窗口更宽)。CSS 中 .detail-panel-container 为 width: 100%, 实际宽度由外层布局决定,面板可拖拽调宽;本次实测宽 647px。

元素 实测值
.detail-panel-container 647 × 871,border-left: 1px solid #ebebeb
.sidebar-next 646 × 871,背景 #fff,border-radius: 12px 12px 0 0
.detail-layout flex column,白底
.detail-layout__top 646 × 64(min-height 64)
.sidebar-next-main-header 646 × 64,padding: 0 16px,justify-content: space-between,gap: 4px,白底
.artifact-tabs 高 32,gap: 4px
.artifact-tab(当前项) 240 × 32(min-width 80 / max-width 240),padding: 0 8px,gap: 4px,背景 #f2f2f2,圆角 8px,14px / 600,行高 22
.artifact-tab__icon 16 × 16,色 rgba(0,0,0,.7)
.artifact-tab__close 14 × 14,色 rgb(119,119,119),border-radius: 999px
.artifact-tabs__add 32 × 32,圆角 8,图标 16 × 16
顶栏右侧操作 两个 32 × 32 按钮(gap: 4px),圆角 6px,图标 16 × 16,色 rgba(0,0,0,.7)
.detail-layout__content 646 × 807
.detail-main__body 背景 #fff

6. 图标采集与替换

真实界面的图标都是内联 SVG(<svg><path fill="currentColor">),不是字体图标(codicon 类名只在少量 VS Code 继承处出现)。

采集链路:scripts/wb-icons.mjs(CDP 取指定节点的 SVG outerHTML → icons.json)→ scripts/gen-icons.mjs(生成 src/renderer/src/components/icons.tsx)。

YCode 组件 来源 尺寸
IconNewTask 侧栏「新建任务」 16
IconChevronDown 「发现应用」下拉箭头 14
IconFilter 侧栏顶栏筛选 16
IconCompact / IconSectionAdd 分组操作 16
IconPlus 输入区「+」 16
IconShield 「允许完全访问」盾牌 16
IconChevronSmall 模型选择器箭头 12
IconMic 语音输入 16
IconStop 停止(圆底 + 圆角方块) 32
IconTab 详情面板页签 13
IconClose 页签关闭 14
IconChevronRight 「查看所有产物」 8
IconPanelCollapse / IconPanelRight 面板收起 / 右侧栏 16

⚠️ 来源与替换要求:icons.tsx 中的矢量路径取自 WorkBuddy 运行时界面, 属于第三方产品界面资产,仅作为当前阶段 1:1 还原的临时占位(用户明确要求"先用 workbuddy 的,先 1:1 还原,然后再改造")。 正式发布前必须整体替换为自有图标或开源图标集。 对比:VS Code codicon 为 MIT 许可,可长期使用;本项目的 icons-extra.tsx 是自有矢量,可保留。


7. 标题栏与菜单栏(实测)

元素 实测值
顶部条带 高 30px,通栏
左侧操作区 x=0 宽 92px(侧栏顶部操作)
.codebuddy-menubar x=92 宽 227,padding-left: 4px,flex row,align center
菜单按钮 .menubar-menu-button 高 30px
菜单标题 .menubar-menu-title 高 24,padding: 2px 8px,圆角 4px,12px / 行高 20,色 rgb(139,148,158) = #8b949e
菜单项 编辑(E) / 窗口(W) / 帮助(H) / 关于(A)
右侧窗口控制区 x=2422 宽 138px(约 46px × 3:最小化 / 最大化 / 关闭)

这是自绘菜单(VS Code 风格),不是系统原生菜单。YCode 已改为 frame: false 无边框窗口 + 渲染进程自绘标题栏(components/TitleBar.tsx), 菜单项均接真实行为(编辑用原生 role、窗口用 IPC、帮助/关于打开对应对话框)。

无边框窗口注意:条带设 -webkit-app-region: drag 负责拖动窗口, 按钮与菜单设 no-drag;主进程需 Menu.setApplicationMenu(null) 去掉原生菜单。


8. 空态与免责声明(实测自 CSS)

说明:采集时 WorkBuddy 处于会话中,页面无空态元素,以下取自安装包 CSS 规则(非冒烟实测), 待用户切到新建对话页后可做一次 wb-tree 复核。

空态 .claw-agent-chat-pane .colleague-chat-empty--profile

元素 实测值
容器 flex column,居中,gap: 24px(spacing-7),padding: 0 16px(spacing-5),text-align center
头像 64px(spacing-12),border: 1px solid 边框色 --wb-color-border-secondary = #ebebeb,border-radius: 18px(radius-lg 8 + md 6 + sm 4),margin-bottom: 16px
标题 24px / 34 / 500,色 text-primary
说明 max-width: 324px,12px / 18,色 text-tertiary
快捷提问容器 flex column,align-items: flex-start,gap: 16px(spacing-5)

快捷提问胶囊 .conversation-embed-empty__quick-prompt

min-height: var(--wb-size-control-md)、padding: 10px 16px、border-radius: 9999px、 背景 --wb-color-bg-primary-default = gray-3 #f2f2f2、文字 color-mix(text-primary 90%, transparent)、 14px、行高 21、white-space: nowrap、border: 0。

免责声明 .claw-local-empty__disclaimer / .conversation-embed-empty__disclaimer

padding: 8px 0、text-align center、色 --wb-color-text-disabled = rgba(0,0,0,.3)、 12px、line-height: 20px、user-select: none、pointer-events: none。 文案:「内容由 AI 生成,请核实重要信息」。

输入区(空态变体)

.claw-local-empty__input-area:width: 100%、max-width: 832px、padding: 0 16px、margin: 0 auto。 .conversation-embed-empty__input-area:--cb-input-content-radius: 22px、--cb-input-main-area-radius: 22px、 --cb-content-background: transparent。


9. 间距阶(编号已与对标对齐)

编号 值 编号 值
spacing-1 2px spacing-7 24px
spacing-2 4px spacing-8 32px
spacing-3 8px spacing-9 40px
spacing-4 12px spacing-10 48px
spacing-5 16px spacing-12 64px
spacing-6 20px

YCode 的 --yc-space-N 编号与之一一对应,翻译对方 CSS 时无需换算。


10. 与 YCode 的差距(本轮已修 / 待修)

已修正

  • 空态:改为「64px 圆角头像(18px 圆角 + 1px #ebebeb 边框) + 标题 24px/500 + 说明 12px/18 max-width 324px + 胶囊快捷提问(padding: 10px 16px、圆角 9999、底色 #f2f2f2)」
  • 输入区下方免责声明:新增「内容由 AI 生成,请核实重要信息」(12px、居中、色 rgba(0,0,0,.3)、padding: 8px 0)
  • 间距阶:--yc-space-N 编号对齐对标 spacing 阶(原实现整体错位一档)
  • 标题栏 + 菜单栏:Electron 原生菜单 → 无边框窗口(frame: false)+ 自绘 30px 条带;菜单 编辑(E)/窗口(W)/帮助(H)/关于(A),12px / #8b949e / 标题 padding: 2px 8px / 圆角 4;右侧 46px×3 窗口控制
  • 主文字 #000 → rgba(0,0,0,.9)
  • 侧栏背景 #f2f2f2 → #f7f7f7
  • 输入框:错误地改成渐变 → 改回白底 + 1px #e6e6e6 + 圆角 24 + 双层阴影,宽度 832 → 784,min-height 96
  • 侧栏列表项:padding 8px 20px + 13px + 两行堆叠 → 31px 单行,padding 5px 12px,圆角 8,标题 14px 左 + 时间 11px 右
  • 侧栏结构:改为「品牌行(64px) + 版本行 + 导航项 + 分组标签(30px) + 列表项」
  • 右侧详情面板:默认显示 → 默认收起(对齐真实默认态);展开态已按实测改为「顶栏 64px + 页签 32px/圆角8/底色 #f2f2f2/14px600 + 右侧 32×32 操作按钮(圆角6)」,面板白底 + 上圆角 12 + border-left 1px #ebebeb
  • 详情面板拖拽调宽:新增 .app-shell__resizer 手柄(0 宽网格列 + 6px 命中区伪元素,hover/拖拽显示品牌色指示线);宽度状态在 App.tsx,以 --yc-layout-right 注入网格;范围 320–900px,默认 647px(对齐实测值)。面板收起时手柄一并卸载。已实测:左拖 150px → 797px、右拖收窄、越界夹在 320 / 900

待补(需要真实界面数据)

  • 侧栏顶部完整导航项(助理 Beta / 专家·技能·连接器 / 定时任务 / 资料库 / 更多)—— YCode 目前只实现「新建对话」与「任务」分组,不伪造未实现入口
  • 权限选择器、麦克风等输入区工具项
  • 图标集:真实界面用 SVG 图标(16×16),YCode 已接入采集图标(见第 6 节,正式发布前需替换)

10.1 对话区顶栏(补充实测)

元素 实测值
.workbuddy-topbar 高 64px,padding: 0 16px,align-items center,justify-content: space-between
.workbuddy-topbar-options 高 32px,位于顶栏内部左右两端
顶栏下方首行 .cr-collapse--summary(「已完成 3m2s」行),字号 13px

据此 YCode 的 .chat-head 由自拟的 padding: 12px 20px 10px 改为 高 64px / padding: 0 16px / 两端对齐,与实测一致。


11. 完整 design token 表(对标体系镜像)

来源:安装包 tokens-Df-i-zsO.css / contexts-BkjwYSZT.css。 YCode 的 --yc-* 编号与对标 --wb-* 一一对应,翻译对方 CSS 时是机械映射。

11.1 间距阶 --wb-spacing-N

N 值 N 值
1 2px 7 24px
2 4px 8 32px
3 8px 9 40px
4 12px 10 48px
5 16px 12 64px
6 20px

11.2 字号阶 --wb-font-size-N

N 值 N 值
1 8px 7 18px
2 10px 8 20px
3 12px 9 24px
4 13px 10 28px
5 14px 11 32px
6 16px

行高:4:16 4-2:18 5:20 5-2:22 6:24 7:28 8:32 10:40 字重:400 500 600 700

11.3 控件尺寸阶 --wb-size-N

N 值 N 值
3 12px 9 36px
3-2 14px 10 40px
4 16px 11 44px
5 20px 12 48px
6 24px 13 52px
7 28px 14 56px
8 32px 17 68px

语义别名:control-sm 24 control-ms 28 control-md 32 control-lg 40 control-xl 48 control-2xl 56

11.4 圆角阶 --wb-radius-*

none 0 xs 2 sm 4 md 6 lg 8 xl 12 2xl 16 3xl 20 4xl 24 full 9999

11.5 语义字号(体例)

角色 字号 行高 字重
body 14 22 400
body-strong 14 22 600
caption 12 18 400
code 13 20 400
h1 24 32 600
h2 20 28 600
h3 16 24 600
display 32 40 700

11.6 语义字号(对话流 chatflow,对标独立一套)

角色 字号 行高
h1 21 37
h2 19 33
h3 17 30
h4 15 26
p1 15 26
p2 13 23
p3 11 19

11.7 全局字号档位(六档)

机制:级别存 localStorage,同时更新「Markdown 根字号」与「全局字号偏移」; 偏移经 clamp(-1, global, 2) 夹取后作用于各语义 token。

档位 --cb-md-root 全局偏移
1 16px −1
2(默认) 17.143px 0
3 18.286px +1
4 20.571px +2
5 22.857px +2
6 26.286px +2

快捷键:Ctrl+- 降档、Ctrl++ 升档、Ctrl+0 恢复默认。

YCode 的实现差异:因组件样式已全部 token 化,不需要像对标那样扫描样式表注入覆盖规则; 只改 --yc-font-offset-global 与 --yc-md-root 两个根变量即可全局生效。 未实现对标的 .cb-font-size-fixed 例外类——目前没有固定字号的控件需要豁免。

11.8 字体族

  • 正文:'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif
  • 等宽:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace

11.9 实测常量(不在标准阶内,对标自身也硬写)

scrollbar 6px、菜单最小宽 200px、窗口控制图标 10px、侧栏项高 31px、侧栏项纵向 padding 5px、 行高 19 / 21 / 24.5 / 26.25、列表缩进 21.45px、气泡 max-height 310px、工具卡正文 max-height 320px、 空态头像圆角 18px、空态说明 max-width 324px、输入 min-height 96px、选项卡 80–240px、 对话框 560 / 420px


12. REA 拆解证据与工具边界

12.1 归档级拆解(已执行)

open_binary  app.asar                    → format=asar, kind=archive
             sha256 035254bc…729de918
inspect_artifact (record-and-continue)   → 12253 节点 / 17356 occurrence / 14476 文件 / 2880 目录
                                            45 处完整性矛盾(观察值标记为 untrusted)

完整性矛盾:首条为 cli/bin/native/win32-x64/job-object.node——声明的 sha256 与伴随文件不符。 REA 指出这是常见现象(打包工具会在写入归档后对未打包的原生二进制签名或裁剪), 但该模块正是绑定子进程树的 Windows Job Object 原生实现,与 GPU 沙箱受限环境的观察一致, 值得单独留意。

12.2 工具边界(重要)

REA 的 CDP 浏览器 provider 只枚举 HTTP(S) 页面目标。 WorkBuddy 的渲染器是 file:// URL,因此:

list_browser_targets http://127.0.0.1:9223
→ targets: []            excluded: { unsupported_url: 1 }
→ limitations: "All page targets with supported HTTP(S) URLs are listed."

结论:REA 的浏览器类工具(inspect_web_page / capture_web_screenshot / compare_web_captures)目前无法观察 WorkBuddy 主窗口。 对 file:// 渲染器的 Electron 应用,实测采集需要直接用 CDP(本项目的 scripts/wb-capture.mjs / wb-tree.mjs / wb-icons.mjs)。 YCode 开发态走 http://localhost,REA 浏览器工具对其可用。

同理,REA 的二进制 provider(Ghidra / IDA / Hopper)在本机均未配置, 且不接归档目标("Ghidra v1 imports executable targets, not archive targets"), 因此无字符串检索能力;token 表据以从归档内 CSS 文件直接提取。


13. 外围壳层完整结构(第二轮实测)

采集脚本:scripts/wb-shell.mjs(输出侧栏完整子树 + 外围元素清单)

重要发现:侧栏宽度不是常量。两次采集分别为 280px(@1334 窗口) 与 240px(@1276 窗口),说明该宽度本身可变(可拖拽或随窗口变化)。 YCode 取 280px 作为展开默认值,并支持收起为 44px 窄轨。

13.1 品牌区

元素 实测值
.conversation-list-logo-row 215×64(min-height 40),gap: 4px,align center
.conversation-list-brand-block flex column,align flex-start,padding-top: 4px
.conversation-list-brand-line 90×22,padding-left: 12px,gap: 8px
品牌标题 14px / 700 / 行高 22,色 rgba(0,0,0,.9)
.conversation-list-version-row 40×18,padding-left: 12px,margin-top: -4px,gap: 6px
版本徽标 10px / 行高 18,letter-spacing: .2px,色 rgba(0,0,0,.5)
「发现应用」按钮 98×28,padding: 4px 6px 4px 8px,gap: 2px,背景 #f2f2f2,色 rgba(0,0,0,.7),边框 1px #ebebeb,圆角 100px,12px / 500 / 行高 20
└ 左侧图标 / 右侧箭头 各 14×14;箭头色 rgba(0,0,0,.3);文字 12px/400

13.2 导航项(实测 .conversation-list-tab-button)

项 备注
新建任务 主入口
助理 带 Beta 徽标
专家·技能·连接器
定时任务
资料库
更多 右侧附 「灵感」 副文案

尺寸:215×32,padding: 5px 12px,gap: 8px,圆角 8px,图标 16×16,标签 14px / 行高 22。

  • Beta 徽标:10px / 500 / 行高 16,padding: 0 5px,边框 1px #dedede,圆角 100px,色 rgba(0,0,0,.45)
  • 「灵感」副文案:11px / 行高 20,色 rgba(0,0,0,.5)

13.3 分组

元素 实测值
分组标签 .conversation-section-label 215×30,padding: 5px 12px,gap: 4px,背景 #f7f7f7,圆角 8px,position: sticky
分组文字 12px / 600 / 行高 20,色 rgba(0,0,0,.5),形如「任务 (1)」「空间 (2)」
折叠箭头 14×14,色 rgba(0,0,0,.3),默认 opacity 0(hover 显现)
分组操作按钮 20×20,圆角 4px,色 rgba(0,0,0,.5),默认 opacity 0
空间分组头 .collapsible-section header 215×34,padding: 5px 12px,gap: 4px,背景 #f7f7f7,圆角 8px
└ 图标 / 名称 16×16 / 14px 行高 22

13.4 底部账号区(实测)

元素 实测值
.conversation-list-footer 239×57,padding: 8px 12px 8px 8px,border-top: 1px solid #e6e6e6
.user-menu 219×40,gap: 4px
.user-menu-trigger 147×40(min-height 40),padding: 6px 8px,圆角 8px;内部 gap: 10px
头像 28×28,border-radius: 50%,背景 #ebebeb,12px / 500
用户名 12px / 600(.user-menu-trigger-name 高 12)
通知按钮 32×32,圆角 6px,色 rgba(0,0,0,.7),图标 16×16
未读角标 .msg-center-badge 14×14,背景 #f64041,白字,border-radius: 7px,9px / 500 / 行高 14,padding: 0 3px
小程序按钮 32×32,圆角 6px,图标 16×16

13.5 输入区补充

.cr-permission-setting(「允许完全访问」):132×32 —— 权限选择器实为 32px 高控件。


14. Mock 数据约定

用户明确要求「登录账号先用 mock 写死数据」。约定:

文件 内容 替换时机
src/renderer/src/mock.ts 账号、通知、空间、导航项清单 接入真实数据源时整体替换

约束(已落实):

  1. 所有导出一律 MOCK_ 前缀,便于全局检索替换
  2. 使用处必须在 UI 上显式标注为示例数据:
    • 通知面板底部:「示例数据 · 尚未接入消息中心」
    • 设置 → 账号:「账号信息为 mock 写死数据,尚未接入登录」
    • 账号按钮 title:「账号为 mock 数据」
  3. 未实现的入口不做假交互:点击给出 2 秒临时提示(如「『专家·技能·连接器』尚未实现」), 不伪造可用状态。这是对外围壳层「配齐」与「不虚构能力」两条要求的折中。

15. 首页 / 新建任务页(空态)—— 冒烟实测

采集方式:用户批准「方案 B」后,由 CDP 直接点击侧栏「新建任务」切换页面后采集。 脚本:scripts/wb-probe.mjs(按文案定位,应对 CSS Module 哈希类名)、scripts/wb-home.mjs、scripts/click-shot.mjs 参考截图:docs/screenshots/wb-home-reference.png

15.1 页面构成(自上而下)

  1. 大标题:「WorkBuddy, 我帮你」
  2. 分段控件 .wb-segmented:[办公][开发][设计]…(场景切换)
  3. 分类胶囊行 .quick-actions__list
  4. 输入框(比会话内更高)
  5. 工作目录 + 权限行(📁 YCode ⌄ / 🔒 允许完全访问 ⌄)
  6. 建议条目列表(整行胶囊 + 右上箭头)
  7. 底部免责声明:内容由 AI 生成,请核实重要信息

15.2 实测尺寸

元素 实测值
分类行 .quick-actions__list 宽 680,flex row,gap: 8px,align center
分类胶囊 .quick-actions__item 高 32,padding: 0 12px,gap: 4px,背景 #f7f7f7,色 rgba(0,0,0,.9),边框 1px #dedede,border-radius: 100px,14px / 400
分段控件 .wb-segmented 高 32,border-radius: 9999px,gap: 2px
分段项 .wb-segmented__item 72×32,padding: 5px 12px,gap: 4px,圆角 9999px,14px / 600,阴影 rgba(0,0,0,.05) 0 1px 4px 0
首页输入编辑区 .cr-input-editor-host 798 × 74,min-height: 74px,padding: 0 16px
输入占位符 15px / 26.25px,色 rgba(0,0,0,.9);文案「今天帮你做些什么?@ 添加上下文,/调用技能与指令」

注意:首页编辑区 74px,会话内是 64px —— 两者不同,不能共用。

15.3 分类清单(实测)

办公 开发 设计 创作文档 金融服务 分析数据 制作PPT 深度研究 策划方案 定时任务

YCode 已按此实现分类行(--yc-* token 化),点击分类把对应提示词填入输入框(真实可用, 提示词为自拟,非对标文案)。

15.4 与旧实现的差异(已修正)

旧空态是「56px 头像 + 大标题 + 竖排胶囊」——那是从 CSS 规则推断的 .colleague-chat-empty--profile, 与真实首页不符。真实首页没有头像,改为「大标题 + 横排分类 + 建议列表」。已按实测重写。

15.5 垂直结构精测(第三轮,scripts/wb-home-layout.mjs + wb-home-parts.mjs)

本轮发现第一轮实现整体结构错误:我把输入框放页面底部、10 个分类挤一行。 真实首页是居中内容列,输入框在页面中部、建议列表在其下方。

区块 实测 rect(视口 1276×901)
标题 h1.wb-home-header__title [614, 159, 278, 42] —— 30px / 600 / 行高 42,色 rgb(0,0,0),gap: 10px
分段控件 .wb-segmented [643, 219, 220, 32] —— 居中于内容列(中心 753)
分类行 .quick-actions [353, 317, 680, 32] —— 左对齐于内容列
输入框外层 .wb-home-route__input-box [353, 365, 800, 184],flex column gap: 12px
└ 白框 .cr-input-container [353, 365, 800, 144],圆角 24,padding-top: 12,白底 + 双层阴影
└ 编辑区 .cr-input-editor-host [354, 378, 798, 74],padding: 0 16px
└ 工具栏 .cr-input-toolbar [354, 452, 798, 56],padding: 12px,space-between
权限项 .cr-permission-setting [461, 513, 132, 32],圆角 999px,13.33px,色 rgb(180,44,63)
建议项 .wb-home-prompt-list__row [353, 601, 238, 38] 起 —— 高 38 / 圆角 9999 / 白底 / 边框 1px #e6e6e6 / 14px,行距 50(38 + 12),左对齐

垂直间距:标题底 201 → 分段 219 = 18;分段底 251 → 分类 317 = 66; 分类底 349 → 输入 365 = 16;输入底 549 → 建议 601 = 52。

结构结论:

  1. 内容列 x=353、宽 800,整体居中(中心 753 ≈ 内容区中心 758)
  2. 输入框不是底部停靠,在页面中部;建议列表在其下方
  3. 分类分两处:分段控件 3 个(办公/开发/设计) + 胶囊行 7 个,不是 10 个一行
  4. 输入框下方有「工作目录 + 权限」行,在输入框外层容器内部(184 = 144 + 40)
  5. 白框 144 = 12 + 74 + 56 + 2,纵向无 gap(YCode 早期实现误加 4px gap → 148,已修)
  6. 会话内输入框 134 = 12 + 64 + 56 + 2,同为无 gap

已实现:ChatPane 拆为 composer(两种变体共用,data-variant 区分编辑区高度)+ composerFooter(工作目录/权限行);首页走 .home 布局,会话走原底部停靠布局。 分段控件用前 3 个分类,胶囊行用后 7 个,与对标结构一致。


16. OMP 内核接入(底层循环替换)

架构决策(用户拍板):YCode 从「自建网关 + 自写 agent 循环」转为 OMP 前端壳。

16.1 事实

项 值
OMP 可执行文件 C:\Users\Administrator\AppData\Local\Ygent\omp.exe(随 Ygent 安装)
版本 omp/18.6.3
协议 --mode rpc:stdio 上的 newline-delimited JSONL,启动先发 ready 帧,单帧上限 1 MiB
Profile ~/.omp/profiles/ycode/agent/models.yml(独立 profile,不动用户 ygent 配置)
上游 https://api.iiiii.run/v1,api: openai-responses,模型 gpt-6-luna/astra/6.1-sol

16.2 实现

文件 职责
src/main/omp.ts sidecar 管理:spawn + JSONL 解析 + 命令关联(id)+ ready 等待 + 退出清理;detectOmpPath() 探测可执行文件
src/main/agent/omp-turn.ts OMP 事件 → YCode ChatEvent 映射(渲染进程零改动)
src/main/ipc.ts 会话 → 内核进程 池;会话删除时释放进程;OMP 不可用时回退自建循环

事件映射:

OMP 事件 YCode ChatEvent
message_update.assistantMessageEvent.type = "text_delta" text
tool_execution_start / _update / _end tool_call / tool_result
agent_end(yielded !== false) done
prompt_result.status = "error" / notice(level=error) error
abort cancelled

踩过的坑:

  1. spawn 报 ENOENT 但可执行文件明明存在 —— 是 cwd 不存在(工作目录为空字符串)。 spawn 的 cwd 与可执行路径无关,必须单独兜底(现回退到用户主目录)。
  2. OMP 工具事件载荷文档未给全 → readToolInfo() 做多形状兼容解析 (toolCall/call/tool/data 逐层找 id/name/arguments)。

16.3 端到端验证

发送「只回复两个字:收到」          → 回复「收到」(omp.exe 被拉起)
发送「用 list_dir 列出工作目录文件」 → 3 张工具卡:glob / read / bash(OMP 原生工具)
                                     全部 ok;回复「工作目录根目录下有 12 个文件。」

注意工具名是 OMP 自己的工具集(glob/read/bash),不再是 YCode 的 list_dir/read_file —— 内核真正接管。YCode 自带的 agent/tools.ts 在 OMP 可用时不再使用(保留代码作回退)。

16.4 遗留

  • 取消链路已接(abort),但未做端到端验证
  • 工具事件载荷的解析是容错的,若 OMP 未来改字段名可能拿不到 name/args(UI 会显示 tool)
  • OMP 进程按会话存活:长会话会常驻一个 omp.exe;会话删除时释放
  • ~/.omp/profiles/ycode 里的 key 有额度限制,过期后回合会失败(届时换 key 即可)