# dsh-token-quota 侧边栏与设置界面迭代方案 日期:2026-10-03。状态:UI01–UI06 已完成,最终候选包已通过必要验证;未提交、推送或发布。 本方案面向当前仓库 `dsh-token-quota`,借鉴 `dsh-usage` 的侧栏速览、折叠交互和集中展示方式,优化日常查看额度与配置供应商的操作。主要交付为一个可以折叠的侧栏卡片,以及一个共用内容的用量监控面板。实施分为六批,验收集中为五组。 本文是实施规范,原始代码位置对应下述固定基线。实施进度见[简短执行记录](sidebar-settings-execution.md),最终验收结果记录在本文末尾。 ## 基线与取舍 | 对象 | 已核对的基线 | 本方案用途 | | --- | --- | --- | | 当前插件 | `v1.4.0`,提交 `a0ec978e14b258842256f14a168c262c5cd8975e` | 确认现有组件、接口、测试和桌面适配边界。 | | 参考插件 | `zhu1090093659/dsh-web` 的 `dev`,提交 `007e49c7af5565e80c82a384d0f61f7675a42446` | 参考侧栏卡片与设置页的信息组织。 | | 宿主接口 | DeepSeek Harness 提交 `639ed015397290b3745d163aafe02ffee4aa3f84`;仓库桌面适配基线为 `0.2.0-rc.2` | 确认槽位和设置导航的能力边界。实施时记录实际运行版本。 | 参考插件在侧栏提供可折叠速览,将详细数据集中到设置分区。采用这两点,但按当前插件的“周期限额、余额、报告费用”能力组织内容。参考插件的成本估算、Token 银行和趋势台账不属于本轮范围,不能仅凭界面改动承诺这些能力。 参考插件的 `foot-card-mount.tsx` 使用宿主 DOM 选择器插入卡片,并通过模拟点击进入设置分区。当前插件已经使用 `sidebar.footer.action` 和 `settings.section`,应继续保留这两个官方槽位。 已查阅的宿主契约中,普通 `settings.section` 只接收 `close`;`openSection` 属于 onboarding 的专属接口。因此,本轮默认采用以下可执行路径:侧栏直接打开插件自己的监控对话框,原生设置分区嵌入同一个面板内容。二者共用数据、组件与配置逻辑,不依赖未公开的跳转接口,也不复制参考插件的 DOM 点击逻辑。 ### 当前需要解决的问题 以下是当前源码和仓库已有截图支持的判断;交互风险来自静态代码检查,并非本轮新做的运行验收。 | 当前情况 | 代码位置 | 本轮处理 | | --- | --- | --- | | 侧栏同时显示连接文案、今日用量、候选数量、供应商、模型和重置信息;额度信息容易在窄宽度下消失。 | `lib/client.js` 的 `FooterWidget`,约第 536 行 | 确立主次,增加完整与紧凑两种状态,额度优先于模型名称。 | | 查看路径包含侧栏弹出菜单、详情弹窗、设置弹窗和原生设置页。 | `Popover`、`DetailModal`、`SettingsModal`、`SettingsSection` | 删除中间弹出菜单,详情与配置收进同一面板。 | | 原生设置页首屏先显示全局轮询参数,供应商操作靠后。 | `SettingsPanel.renderMain` | 概览作为默认页;供应商管理与全局设置分别设为页签。 | | 余额没有 `pct` 时,`EntryCard` 将 `unknown` 映射为错误色,并显示“无限额概念(余额)”。 | `EntryCard`,约第 779 行 | 按指标类型渲染;正常余额使用中性色,错误色只表达失败。 | | 页面形态也调用 `useDialog`;未取得状态时直接生成遮罩和对话框。 | `SettingsPanel`,约第 851 行;`useDialog`,约第 1297 行 | 区分嵌入页面与对话框的加载、焦点和关闭行为。 | | 侧栏与设置页分别读取状态;直接复用现有 Hook 的多个实例,会涉及调度登记和取消的相互影响。 | `requestScheduler`、`useQuotaState`、`SettingsPanel.reload` | 由一个共享控制器管理请求,视图只订阅。 | ## 目标界面 ### 侧栏卡片 完整状态保留四行信息。以下数值仅为布局示例。 ```text 用量监控 收起 OpenCode · 模型名称 5 小时已用 63% 2h13m 后重置 今日用量 1.24M tokens ``` 主操作区域点击后直接进入监控面板的“概览”。收起按钮与主操作按钮为同级元素,避免嵌套按钮和误触。完整状态目标高度约为 88–104 CSS px,根据宿主字体实际调整。 紧凑状态为一行,优先保留供应商和主指标: ```text OpenCode · 5 小时已用 63% 展开 ``` 显示规则如下。 1. 供应商来自当前显示会话最近一次真实调用。没有调用时显示“暂无调用”,不借用其他会话的供应商。 2. 周期限额使用现有“已用百分比”口径,选取已用比例最高的有效窗口;同一行必须显示该窗口名称与对应的重置时间。缺少重置时刻时不生成倒计时。 3. 余额直接显示币种和金额。多币种保持独立,侧栏显示一个余额条目及“另有 N 项”,完整内容放在概览中,不相加、不换算。 4. 报告费用与报告用量保留原有统计周期。不能将组织账单的最近完整 UTC 日写成“今日”,也不能将报告费用写成余额。 5. 今日用量沿用现有 `suppliers.filter(s => s.current)` 后汇总 `todayTokens` 的口径,不变更记账和筛选算法。卡片的可访问说明及概览说明明确写出“当前供应商的今日 Token 用量,按宿主本地日统计”。它不是当前会话用量,也不是全部历史路由的当日总量。 6. 连接状态缩为状态标记,正常时不占主指标位置;失败时显示短文案。沿用现有事件观测口径,不将“已见事件”解释成实时网络在线。 7. 取数失败但有旧数据时,显示“更新失败 · 上次数据”,旧值使用中性色;没有旧数据时显示“暂时无法获取”。未知值用 `—`,真实零值仍显示 `0`。 8. 侧栏可用宽度不足 200 CSS px 时自动使用紧凑布局,恢复宽度后回到用户选择。Web `wide=false` 保留现有图标入口;Windows 桌面零宽折叠时随宿主隐藏,展开后恢复。 9. 用户选择的完整或紧凑状态写入浏览器本地偏好;只保存这一显示选择。自动窄栏降级不覆盖用户选择,存储不可用时使用内存状态。 布局继续位于官方 footer 槽位。维持该槽位内的整行显示,不移动宿主“设置”按钮,不增加常驻悬浮层,不承诺与参考插件完全相同的像素位置。 ### 用量监控面板 原生设置导航名称统一为“用量监控”。面板包含三个页签。 ```text 用量监控 刷新 概览 供应商 设置 概览:今日用量、当前供应商、额度与余额卡片 供应商:已添加列表、重新扫描、添加与配置 设置:轮询间隔、保留期、侧栏显示 ``` | 页签 | 默认内容 | 交互规则 | | --- | --- | --- | | 概览 | 今日用量、已添加数量、异常数量;已添加供应商的额度与余额卡片。 | 当前会话供应商优先,其余按稳定名称顺序。筛选只保留“全部”“需关注”;“需关注”包含取数失败和达到用户告警阈值的项目。卡片可以进入对应供应商配置。刷新历史默认收起。 | | 供应商 | 已添加目录;每行显示名称、地域或凭据类别、状态、主指标、启用开关和“配置”。 | “重新扫描”仅发现配置,“刷新”仅查询额度。把“测试连接”移入供应商编辑页,减少行内按钮。可添加列表默认收起,扫描结果仍在当前页显示。 | | 设置 | 轮询间隔、数据保留期、侧栏完整或紧凑选择。 | 轮询维持 10–3600 秒,保留期维持 1–90 天;保持现有默认值。宿主配置显式保存,本地显示偏好立即生效并标注“仅当前浏览器”。 | 概览卡片以供应商为单元,卡片内按周期限额、余额、报告费用或用量分组。沿用供应商 ID 作为身份:普通 Key 与 Management Key、组织 Admin Key、国内与国际条目不能因为显示名称相似而合并。同一个供应商可以同时拥有多个能力组。 内容区宽度达到 720 CSS px 时使用两列卡片;不足时一列。取消按供应商不断向右延伸的多栏布局,主页面不产生横向滚动。对话框宽度建议为 `min(960px, calc(100vw - 32px))`;原生设置页直接使用宿主内容列宽度。 颜色和背景继续使用宿主 `--dsw-*` 变量。金额和比例使用等宽数字;告警同时提供文字,不能只靠颜色区分。错误原因放在具体卡片或字段附近,详细响应按需展开,不把原始配置、调试字段或内部实现说明写入页面正文。 ### 供应商编辑页 编辑页作为“供应商”页签内的子页。返回时恢复目录位置;从概览进入时,返回到原来的概览。结构固定为: 1. 标题区:供应商名称、地域、凭据类别、启用开关。 2. 当前数据预览:复用概览指标组件;说明这是已保存配置的最近查询结果。修改草稿不会把预览伪装成新配置的结果。 3. 凭据区:按现有 `meta.needs` 生成字段;已保存的密钥显示设置状态,输入留空保留旧值。 4. 高级选项:Base URL、警告阈值和临界阈值默认折叠;有关字段出错时自动展开并定位。 5. 操作区:测试连接、取消、保存。保存中禁用重复提交;失败保留输入并显示原因。 供应商草稿在当前面板内保留,切页不因背景刷新被覆盖。返回或关闭遇到未保存修改时,使用“继续编辑/放弃修改”的简短确认;保存中关闭仍沿用操作身份作废规则,重新打开后读取服务器实际状态,不自动重放保存。秘密字段只保留在编辑草稿生命周期内,不进入共享展示缓存或本地偏好。 ## 实施批次 下表保留实施前的依赖和工期估算。实际执行按用户授权连续完成六批,不包含新增供应商、发布和远端部署。 | 批次 | 依赖 | 主要成果 | 估算 | | --- | --- | --- | --- | | UI01 | 无 | 统一指标与错误状态的展示规则 | 0.5 日 | | UI02 | UI01 | 共用面板、导航和请求控制器 | 1 日 | | UI03 | UI02 | 完整与紧凑侧栏卡片 | 1 日 | | UI04 | UI02、UI03 | 概览和供应商目录 | 1 日 | | UI05 | UI04 | 编辑页和设置页整理 | 1 日 | | UI06 | UI01–UI05 | 必要验证、文档同步和清理 | 0.5 日 | 本次实施遵照 2026-10-03 用户授权:每批完成后自行检查依赖并连续进入下一批,无需逐批确认;本次授权覆盖原方案的逐批停止规则。不在界面批次中附带发版。 ### UI01 统一展示规则 改动位置:`lib/client.js` 的 `headlineOf`、`tightestOf`、`resetTextOf`、`EntryCard`;`lib/index.js` 的 `buildStatePayload`;`test/client.mjs` 和必要的状态响应测试。 - **UI01.1 指标选择。** 增加纯展示函数,例如 `selectPrimaryMetric(supplier)` 与 `buildEntryView(entry, supplier)`,返回类型、标签、值、单位、窗口、重置文案和告警色。只使用现有结构化字段,不从金额字符串反推额度。侧栏、概览、编辑预览共用它们。 - **UI01.2 状态显示。** 将“正常余额但无百分比”“尚未查询”“未启用”“查询失败”分开。`pct` 缺失不再自动使用错误色;余额不再显示“无限额概念(余额)”。保留 `0` 与缺失值的区别。 - **UI01.3 数据时间。** 在供应商状态响应中增加可选的 `lastSuccessAt`,直接来自现有 `scheduler.getState(id)`。失败尝试的时间不充当成功数据时间;旧响应没有该字段时省略时间,仍显示失败标记。`state.now` 只代表状态响应生成时间。 交付:旧界面先使用新的展示函数;后续布局批次无需再决定余额、百分比和错误态的语义。无需修改 `providers.js` 的查询与费用计算。 ### UI02 共用面板和数据请求 改动位置:`lib/client.js` 的 `requestScheduler`、`useQuotaState`、`SettingsPanel.reload`、`DetailModal`、`SettingsSection`、`useDialog` 与 `apply`;`test/client-lifecycle.mjs`、`test/browser/shell.html`。 - **UI02.1 面板外壳。** 增加 `MonitorPanel`,统一“概览/供应商/设置”页签及供应商子页。原生槽位使用 `variant="page"`;侧栏使用 `variant="dialog"`。先接入现有详情和配置内容,保持本批可运行。 - **UI02.2 共享状态。** 将现有请求调度包装为一个随插件 `apply` 创建和销毁的展示控制器。控制器统一订阅当前会话和页面可见性;组件通过 `useSyncExternalStore` 订阅稳定快照。仅保留一套自动刷新循环,不在每个视图重新挂载现有 `useQuotaState`。 - **UI02.3 生命周期。** 第一个可见视图订阅时开始工作,最后一个视图离开或插件卸载时释放资源;隐藏文档暂停,恢复后立即获取一次。切会话作废旧请求。沿用现有 10 秒后台状态刷新、失败退避和手动刷新合并,不同时修改宿主供应商轮询周期。 - **UI02.4 编辑隔离。** 保存、重扫完成后通过控制器重新加载展示状态,不重新初始化已有编辑草稿。保留现有 `editorId`、操作序号和草稿修订检查,旧回调不能影响另一个编辑页。 - **UI02.5 页面与对话框。** `useDialog` 增加明确的启用条件。嵌入页面不创建遮罩、不声明第二个模态框、不截获宿主 Tab 与 Esc;对话框保留焦点限制、Esc 关闭和返回入口焦点。加载和失败状态同样遵循这一规则。 原生分区已经挂载时,侧栏入口通过插件自身控制器切换该分区的内部页签并聚焦标题;分区未挂载时,打开插件对话框。只根据自身组件的挂载状态协调,不能查找宿主菜单文本。若原生分区在插件对话框打开期间挂载,关闭插件对话框并接管当前内部页面和未提交草稿,避免出现两套可编辑界面。 交付:详情和配置拥有同一内容树与数据入口。函数可以先保留在现有 `lib/client.js` 闭包中,继续使用 `__ModuleLoader__` 的无构建加载方式,不引入打包器或新运行时依赖。 ### UI03 改造侧栏 改动位置:`lib/client.js` 的 `FooterWidget`、`FooterSlotWithSession`、`useStripVariant`、相关 CSS 和中英文词条;`test/client.mjs`、`test/browser/interactions.spec.mjs`。 - **UI03.1 卡片结构。** 按目标界面实现主点击区域和独立收起按钮;移除点击后先经过 `Popover` 的路径。图标栏入口也直接进入同一概览。 - **UI03.2 宽度与偏好。** 复用 `ResizeObserver` 判断可用宽度;增加带版本的本地偏好键 `dsh-token-quota.ui.v1`,仅包含 `sidebarDensity: "expanded" | "compact"`。读取失败回退完整状态,写入失败保留当次选择。设置页通过同一偏好存储订阅变更。 - **UI03.3 文案与优先级。** 采用 UI01 指标;模型名称首先省略,完整名称进入可访问说明。错误必须有可见短标签;正常连接状态不挤占额度。新会话显示“暂无调用”,其今日汇总仍可展示,但不能误写成该会话用量。 - **UI03.4 删除旧分支。** 移除运行代码中的 `?qm-strip=A|B|C` 及未选 CSS,保留最终一套完整和紧凑布局。相应更新测试定位和词条。 交付:一点击可查看详情,折叠选择可以跨刷新保留,Web 图标栏与 Windows 零宽折叠分别遵循宿主行为。 ### UI04 重排概览和供应商目录 改动位置:`lib/client.js` 中原 `DetailModal` 内容、`EntryCard`、供应商目录、扫描结果和 CSS;`test/browser/interactions.spec.mjs`、`test/browser/server.mjs`。 - **UI04.1 概览。** 将原横向供应商分栏改为一列或两列卡片;使用 UI01 的分类型指标。保留完整多窗口和多币种数据,错误原因紧邻所属供应商。 - **UI04.2 筛选与定位。** 加入“全部/需关注”,空筛选结果给出明确文案。当前会话供应商可优先展示,用户编辑期间目录不因轮询自动换序。概览的“配置”直接进入指定供应商子页,返回位置由面板控制器保存。 - **UI04.3 供应商行。** 主列表继续由服务端 `added` 决定;已停用但有密钥的供应商仍保留。行内保留启用开关与配置按钮,测试连接移入编辑页。重新扫描与添加入口放在目录标题区,未添加列表默认折叠。 - **UI04.4 异常与历史。** 扫描失败保留上次成功目录并标注失败;不使用客户端显示排序重新推导接入状态。刷新历史继续默认收起,详细错误按需展开。 交付:概览负责看数据,供应商页负责接入与管理;页面在窄窗口下纵向排列,未丢失现有供应商能力。 ### UI05 整理编辑页和设置页 改动位置:`lib/client.js` 的 `SettingsPanel`、`renderSupplierPage`、`supplierDraft`、`supplierPatch`、保存和连接测试逻辑、CSS 与词条;`test/browser/edit-identity.spec.mjs`、`test/draft-config.mjs`。 - **UI05.1 表单分组。** 按标题、预览、凭据、高级选项、操作区重排。高级选项默认折叠;校验失败自动展开对应组,并保留全部草稿。 - **UI05.2 草稿处理。** 增加 dirty 比较与未保存修改提示;切换页签保留本面板草稿,明确放弃或销毁面板时清理。已有的留空保留密钥、非秘密字段清空和并发操作身份规则继续生效。 - **UI05.3 查询结果。** 测试连接只针对发起时的草稿;草稿变化后旧结果失效。成功保存后更新共享状态,显示一次保存结果;失去回写资格的旧请求不得显示到新编辑器。 - **UI05.4 设置页。** 将全局参数从目录首屏移到设置页签,保留原范围和默认值。侧栏完整或紧凑偏好与卡片箭头互通;偏好不写入 DSH 行配置,不新增第二套保存机制。 交付:首屏可直接处理凭据和查看额度,高级字段按需展开;配置仍沿用现有 volatile 行配置与服务端校验。 ### UI06 验证与文档收尾 改动位置:现有相关测试、`scripts/verify-desktop.mjs`、`README.md`、`CONTEXT.md`、`docs/windows-desktop-adaptation.md`;本方案状态。 - **UI06.1 更新既有断言。** 将旧弹出菜单路径改为直接打开概览;保留会话隔离、异步编辑和保存失败的有效行为断言。增加下表所列必要覆盖,不按全部供应商、主题和窗口尺寸做笛卡尔组合。 - **UI06.2 运行必要验证。** 执行一次完整现有自动回归和包检查;使用最终候选包做一次真实 Windows 安装版检查,并在一个真实 DSH Web 页面做入口与布局冒烟。前面失败且已修复的检查可针对性重跑。 - **UI06.3 同步说明。** 更新实际入口、三个页签、今日用量范围与侧栏偏好;清理过时的四处展示、Popover 和 A/B/C 描述。`ui-prototype.html` 若保留,明确其历史参考地位,不作为本轮验收依据。 - **UI06.4 记录结果。** 在本方案附一张结果表,列出检查项、通过或失败或未运行、证据位置即可;可沿用现有测试报告,不新增多份账本和交接体系。 交付:可以评审和安装的候选改动及必要结果记录。版本、提交、推送和正式发布另按用户指定范围执行。 ## 必要验收 只保留以下五组。针对展示分支使用可控数据;供应商真实账户查询不因本轮布局修改全部重测。模拟数据结果与真实宿主结果分开记录。 | 编号 | 必须确认的行为 | 最小验证方式 | | --- | --- | --- | | A1 指标与状态 | 百分比、余额和报告费用标签正确;多币种不相加;未知不等于零;旧数据失败可辨认;重置时间对应所展示窗口。 | 展示函数用一个表驱动测试覆盖上述分支,再人工查看一次正常和失败卡片。不新增真实供应商矩阵。 | | A2 侧栏与入口 | 完整、紧凑和宽度降级可用;刷新后保留偏好;长名称不挤掉主指标;点击直接进入共用面板;关闭返回焦点。 | 一条参数化浏览器流程检查 240 px、180 px 侧栏和现有 Web 图标栏;真实 Windows 检查折叠隐藏和恢复。 | | A3 面板与配置 | 概览与预览一致;嵌入页无额外模态限制;供应商与高级字段可操作;空密钥保留旧值;保存失败保留草稿;旧回调不覆盖新编辑器。 | 改造现有浏览器保存和编辑身份测试,合并检查页面与对话框的焦点行为;查看一次窄窗口及明暗主题。 | | A4 会话与请求 | A/B 会话不串数据;无调用不借其他会话;侧栏与面板同时显示时不重复轮询;隐藏暂停、恢复一次、卸载释放;手动刷新可正常完成。 | 复用 `test/client-lifecycle.mjs` 与会话相关测试,仅补共享订阅场景。 | | A5 实际宿主可用 | 最终候选包加载正常;真实桌面和真实 Web 均能进入概览、配置并保存一个非秘密字段;已有设置可读取;展示不遮挡宿主设置入口。 | 包检查后,候选包只做一轮桌面安装验证,加一次 Web 冒烟。使用隔离 profile;只验证 UI 与保存,不要求付费调用。 | 执行命令沿用现有工具: ```powershell npm test npm run test:browser npm run test:pack ``` 真实桌面验证继续使用 `npm run test:desktop -- --app <安装版路径> --package <候选tgz路径> --output <本轮输出目录>`。脚本的操作路径必须先随 UI 更新;参数使用实际路径,不直接沿用旧输出目录。Web 浏览器测试壳不能代替 A5 的真实 Web 宿主冒烟。 不新增性能压测、长时间稳定性测试、所有供应商真实余额测试、发布资产校验或重复安装矩阵。只有本轮出现相关异常,或实际改动超出上述范围时,才增加对应验证。未能运行的真实宿主检查明确记为 `notRun`,不以模拟页面通过替代。 ## 兼容与回退 本轮继续使用现有 API 路径、供应商注册表、小时桶格式、凭据类别隔离和配置写入方式。唯一计划中的宿主响应增量是可选的 `lastSuccessAt`,无数据文件迁移,也不提高包声明的宿主最低版本;旧版入口如未做实机复验,需要在结果中说明这一范围。 每批形成可独立检查的改动。布局回退只需恢复对应客户端改动;未识别的本地显示偏好可以忽略。若正式替换已安装插件后需要回退,恢复先前插件包即可,保留 DSH 配置与用量文件。共享请求控制器与面板入口应作为同一批回退,避免新旧视图混用生命周期。 ## 源码依据 - [参考插件中文说明](https://github.com/zhu1090093659/dsh-web/blob/007e49c7af5565e80c82a384d0f61f7675a42446/packages/dsh-usage/README.zh.md)。 - [参考侧栏组件 UsageFootCard](https://github.com/zhu1090093659/dsh-web/blob/007e49c7af5565e80c82a384d0f61f7675a42446/packages/dsh-usage/src/client/UsageFootCard.tsx)。 - [参考挂载与设置跳转实现](https://github.com/zhu1090093659/dsh-web/blob/007e49c7af5565e80c82a384d0f61f7675a42446/packages/dsh-usage/src/client/foot-card-mount.tsx)。 - [参考设置分区 UsageSectionCard](https://github.com/zhu1090093659/dsh-web/blob/007e49c7af5565e80c82a384d0f61f7675a42446/packages/dsh-usage/src/client/UsageSectionCard.tsx)。 - [宿主设置槽位契约](https://github.com/deepseek-ai/deepseek-harness/blob/639ed015397290b3745d163aafe02ffee4aa3f84/packages/client/ui-settings/src/client/contract/slots.ts)。 - [宿主侧栏 footer 布局](https://github.com/deepseek-ai/deepseek-harness/blob/639ed015397290b3745d163aafe02ffee4aa3f84/packages/client/ui-sidebar/src/client/SidebarRoot.tsx)。 - 当前仓库:[`lib/client.js`](../lib/client.js)、[`lib/index.js`](../lib/index.js)、[`lib/scheduler.js`](../lib/scheduler.js)、[`Windows 桌面适配记录`](windows-desktop-adaptation.md)。 ## 实施结果(2026-10-03) 六批均已完成。UI01 增加共用指标展示函数与 `lastSuccessAt`;UI02 将展示请求统一到随插件生命周期管理的控制器,原生页与对话框共享内容和面板会话;UI03 实现完整/紧凑、本地偏好和直接概览入口;UI04 完成分组概览、关注筛选及供应商目录;UI05 完成高级选项、草稿和保存身份保护;UI06 完成测试迁移、必要回归、真实宿主检查与文档同步。 | 检查项 | 结果 | 证据位置 | | --- | --- | --- | | A1 指标与状态 | 通过。表驱动覆盖百分比、余额、报告费用/用量、未知与零、多币种、旧数据与对应窗口重置;已查看正常和失败卡片。 | `test/client.mjs`;`.scratch/sidebar-ui-visual/overview-normal-and-stale.png` | | A2 侧栏与入口 | 通过。240/180 px 与 Web 图标栏、偏好重载、窄宽度不覆盖偏好、主指标及关闭焦点;真实桌面零宽折叠与恢复通过。 | `.scratch/sidebar-ui-browser-final.log`;`.scratch/sidebar-settings-desktop-package-final/report.json` | | A3 面板与配置 | 通过。页面/对话框焦点、明暗窄窗口、留空密钥、失败草稿、测试迟到回调、保存锁接管及关闭重开。最后补充原生宿主滚动位置恢复回归,旧实现 `344→0`,修复后严格恢复 `344`。 | `test/browser/edit-identity.spec.mjs`;`test/browser/interactions.spec.mjs`;`.scratch/sidebar-ui-visual/narrow-dark.png`、`narrow-light.png` | | A4 会话与请求 | 通过。单共享订阅、A/B 隔离、忽略 abort 的迟到回调、隐藏/恢复、卸载释放、手动刷新合并。 | `test/client-lifecycle.mjs`;`.scratch/sidebar-ui-client-final.log`(25/25,含客户端展示测试) | | 完整既有自动回归 | 通过。`npm test` 72/72,无跳过;后续客户端改动针对性复验 25/25。浏览器完整回归 21/21,最后新增滚动回归 1/1,共 22 项通过。 | `.scratch/sidebar-ui-unit.log`;`.scratch/sidebar-ui-browser-final.log`;上述客户端日志与滚动回归测试 | | 包检查与语法 | 通过。46 个文件;包内 46/46 文件与最终工作区逐字节一致;`lib/*.js` 语法检查及 `git diff --check` 通过。 | `.scratch/sidebar-ui-pack.log`;`.scratch/sidebar-ui-package.json` | | A5 真实 Windows 安装版 | 通过,9/9。宿主 `0.2.0-rc.2`、Electron `44.0.0`、Node `24.18.1`;最终 tgz 安装于隔离 `desktop` profile。 | `.scratch/sidebar-settings-desktop-package-final/report.json`,同目录截图;`.scratch/sidebar-settings-desktop-package-final.log` | | A5 真实 DSH Web | 通过,5/5。安装版自带 CLI `0.2.0-rc.2` 启动真实 HTTP 宿主,最终 tgz 安装于隔离 `web` profile,使用 Chromium 访问。 | `.scratch/sidebar-settings-web-package-final/report.json`,同目录截图;`.scratch/sidebar-settings-web-package-final.log` | | 真实供应商查询 | `notRun`。隔离 profile 未设置真实供应商凭据,未发送聊天或付费查询;本轮不新增真实账户矩阵。 | 两份真实宿主报告的 `supplierQueries` 字段 | | 旧版实际宿主 | `notRun`。本轮真实宿主检查限定于现有 `0.2.0-rc.2`;旧会话接口仅有自动回归,不将其记作旧版实机验收。 | `test/client-lifecycle.mjs`;两份宿主报告的运行版本 | 候选包:`.scratch/sidebar-settings-candidate-20261003/dsh-token-quota-1.4.0.tgz`。SHA-256:`D0288E4A2FDF53B176CBC321C6B15EA0D0A6339E46BB6DBF9EB1AFCF6C2252E4`。两份最终宿主报告记录的哈希与该文件一致。候选包版本仍为 `1.4.0`,未替换日常使用环境中的插件。 ### 实施调整与边界 - 保留官方两个槽位和无构建加载;没有新增依赖、供应商查询方法、计费功能或用量数据迁移。 - 原生设置的滚动由宿主容器承载,因此返回位置通过组件自身最近的可滚动祖先保存,不依赖宿主菜单选择器。 - 在途保存锁跟随面板会话迁移;旧保存成功仍刷新共享状态,但旧编辑器没有回写资格。关闭后重新进入时,等待未结算写入及最新读取,避免用旧缓存创建草稿;不自动重放保存。 - 宿主 `settings.section` 没有可取消的外部导航接口。插件内返回、取消和关闭均提供未保存确认;宿主直接卸载原生分区时无法拦截,只能销毁草稿。该边界已同步 README 和桌面说明。 - 真实供应商查询与旧版实机检查不属于本轮必须执行的 A5 路径,无需人工操作即可完成本轮交付。若另行验收这两项,最少需要在隔离 profile 配置目标供应商凭据,或提供目标旧版宿主;结果须单独记录。 ### 保留的失败记录 真实 Web 源码探索保留 `.scratch/sidebar-settings-web-source-01`、`02`、`03` 的失败报告,原因分别为初次预览说明、密钥接入提示及刷新后再次出现的接入提示阻挡操作。脚本改用宿主正常“继续/稍后配置”交互后,`source-04` 通过;最终包检查也通过。未删除宿主遮罩或绕过交互。 实现期间发现并修复保存后 busy 未释放、旧全局保存影响新编辑器、原生接管丢失保存锁、关闭重开初始化旧配置以及原生滚动位置丢失,均保留对应行为断言。浏览器旧定位、密钥状态测试字段与浅色主题测试变量按实际新交互修正,未删除关键行为断言或将失败改为跳过。