From e2a5f83666fc180018b6382ab74e53acea385e32 Mon Sep 17 00:00:00 2001 From: mesalogo Date: Thu, 8 Oct 2026 16:34:25 +0800 Subject: [PATCH] docs: publish chat history navigation workflow --- .github/workflows/pages.yml | 9 ++++ .gitignore | 1 + .../chat-history-navigation/README.md | 17 ++++++ docs/features/chat-history-navigation/prd.md | 34 ++++++++++++ .../chat-history-navigation/progress.md | 17 ++++++ .../technical-design.md | 52 +++++++++++++++++++ .../2026-09-26-unreleased/article.md | 29 ++++++++--- .../2026-09-26-unreleased/review.md | 16 ++++++ docs/pr-articles/README.md | 2 +- src/renderer/src/App.tsx | 30 +---------- src/renderer/src/ConversationHistorySlot.tsx | 13 ++++- 11 files changed, 180 insertions(+), 40 deletions(-) create mode 100644 docs/features/chat-history-navigation/README.md create mode 100644 docs/features/chat-history-navigation/prd.md create mode 100644 docs/features/chat-history-navigation/progress.md create mode 100644 docs/features/chat-history-navigation/technical-design.md diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b7310802..f97764cc 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -7,6 +7,8 @@ on: - main paths: - 'sites/**' + - 'package.json' + - 'package-lock.json' - '.github/workflows/pages.yml' permissions: @@ -29,8 +31,15 @@ jobs: steps: - uses: actions/checkout@v7 + - uses: actions/setup-node@v4 + with: + node-version: '24' + cache: npm + - name: Validate website run: | + npm ci --ignore-scripts + npm run docs:build node sites/scripts/validate.mjs node --check sites/app.js diff --git a/.gitignore b/.gitignore index db21b812..f6c1a0d4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ shareserver/build-server/ coverage/ /temp/ .vite/ +sites/docs-dist/ .runtime-resources/ .remote-runtime-resources/ .agent-resources/ diff --git a/docs/features/chat-history-navigation/README.md b/docs/features/chat-history-navigation/README.md new file mode 100644 index 00000000..17f644de --- /dev/null +++ b/docs/features/chat-history-navigation/README.md @@ -0,0 +1,17 @@ +# 聊天历史导航 + +聊天历史导航负责长会话的连续滚动、窗口化渲染,以及后续的对话 minimap。第一阶段先取消向上滚动时每次增加 80 条消息的产品限制,保留已有的消息窗口化机制;第二阶段再评估 minimap。 + +## 文档导航 + +| 文档 | 权威职责 | +| --- | --- | +| [产品需求](./prd.md) | 用户问题、范围、验收和非目标 | +| [技术设计与测试计划](./technical-design.md) | 当前实现边界、实验分组、性能指标和执行步骤 | +| [实施进度](./progress.md) | 已验证事实、命令、结果和遗留问题 | + +## 术语 + +- **历史窗口**:允许滚动访问的消息范围。第一阶段扩大为当前已加载会话的全部消息。 +- **DOM 窗口**:实际挂载消息组件的范围。继续由消息高度估算和最多约 60 条挂载消息控制。 +- **minimap**:对话右侧的轻量纵向全局导航概览,不等于完整渲染所有消息。 diff --git a/docs/features/chat-history-navigation/prd.md b/docs/features/chat-history-navigation/prd.md new file mode 100644 index 00000000..7b9e6e32 --- /dev/null +++ b/docs/features/chat-history-navigation/prd.md @@ -0,0 +1,34 @@ +# 聊天历史连续滚动 + +## 用户问题 + +长会话向上阅读时,当前界面每次只增加 80 条消息,并在顶部显示“加载更早的消息”控件。这个控件把连续滚动切成多个操作,用户无法像 VSCode 一样直接拖动滚动条或连续滚到会话顶部。 + +## 目标 + +- 已加载的当前会话可以从底部连续滚动到顶部。 +- 消息仍按可见范围挂载,长会话不会因为取消 80 条限制而一次性创建全部消息组件。 +- 滚动位置、锚点、消息展开状态和流式输出行为保持稳定。 +- 为后续 minimap 提供完整的消息索引和可定位滚动范围。 + +## 范围 + +- 取消真实聊天会话的 80 条历史窗口增量。 +- 保留现有消息窗口化、占位高度、滚动锚定和按需挂载。 +- 对 100、500、2,000、10,000 条消息进行功能和性能对比。 +- 记录 minimap 的下一阶段性能测试入口,但本阶段不实现 minimap。 + +## 非目标 + +- 不改变未打开会话的摘要加载策略。 +- 不要求一次从数据库加载所有未加载的会话历史。 +- 不取消最多约 60 条消息组件的 DOM 窗口化限制。 +- 不在本阶段加入 minimap、消息摘要接口或新的 IPC。 + +## 产品验收 + +- 打开一个已加载历史的会话后,顶部不再出现“加载更早的消息”按钮。 +- 用户可以连续滚动到第一条消息,滚动位置不会因消息挂载或高度测量而跳动。 +- 2,000 条消息会话仍保持窗口化渲染,实际挂载消息数量维持现有上限附近。 +- 流式输出、输入、消息展开、附件和工具输出行为没有回归。 +- 若会话只有摘要,仍按现有逻辑按需加载完整历史。 diff --git a/docs/features/chat-history-navigation/progress.md b/docs/features/chat-history-navigation/progress.md new file mode 100644 index 00000000..833cedc1 --- /dev/null +++ b/docs/features/chat-history-navigation/progress.md @@ -0,0 +1,17 @@ +# 实施进度 + +## 2026-10-08 + +- 已确认 80 条限制由 `ChatHistoryPane` 的 `messageRenderBatchSize` 和 `revealEarlierMessages` 驱动。 +- 已确认消息窗口化仍以高度占位和最多约 60 条挂载消息为上限。 +- 已建立基线、本阶段和 minimap 阶段的对比测试计划。 +- 已将生产会话接线改为直接使用当前已加载消息总数,保留 DOM 窗口化。 +- `ChatHistoryPane` 与 `ChatTimeline` 定向测试通过:58/58。 +- 改动文件定向 web 类型检查和 lint 通过。 +- `npm run build:bundle` 通过。 +- `npm run perf:app` 通过。本次 B 组测量中,长会话打开交互延迟为 86.9 ms,长会话滚动帧间隔 p95 为 16.9 ms、无长任务;流式输入场景帧间隔 p95 为 16.9 ms,输入延迟 p95 为 17.1 ms。 +- B 组第二次运行仍通过:长会话打开交互延迟为 46.9 ms,长会话滚动帧间隔 p95 为 16.8 ms、无长任务;流式输入场景输入延迟 p95 为 19.1 ms。 +- App 测试通过 341/349;剩余 8 个失败集中在既有图片附件异步场景,未出现聊天历史窗口相关失败。 +- 全局 `npm run typecheck` 仍被既有 `src/main/desktop-storage-electron-fixture.ts:215-217` 类型错误阻断;全局 lint 仍包含生成的 VitePress cache 错误。 +- A 组临时恢复后连续两次在 composer 初始化阶段超时,未进入性能场景,因此没有有效 A 组数据,不能据此推导 A/B 数值差异。B 组代码已恢复并重新完成 bundle、定向类型检查、定向 lint 和 58/58 聊天窗口测试。 +- 下一步实现 minimap 前仍需先修复性能驱动在 A 组接线下的 composer 初始化问题,或建立不依赖 composer 的长会话专用 benchmark,再进行严格 A/B 测量。 diff --git a/docs/features/chat-history-navigation/technical-design.md b/docs/features/chat-history-navigation/technical-design.md new file mode 100644 index 00000000..5a0a304c --- /dev/null +++ b/docs/features/chat-history-navigation/technical-design.md @@ -0,0 +1,52 @@ +# 技术设计与测试计划 + +## 当前边界 + +`ChatHistoryPane` 当前有两层机制:`messageRenderBatchSize = 80` 控制向上滚动时可访问的历史窗口;`maxRenderedMessageCount = 60` 控制实际挂载的消息组件。第一阶段只移除前者在生产接线中的作用,保留后者以及消息高度占位和锚点恢复。 + +已加载历史的消息数组仍由会话 store 提供。带 `messageSummary` 的会话继续先显示加载状态,由现有 `loadHistory` 路径取得完整历史。这样本实验测量的是滚动历史窗口的变化,不混入存储或 IPC 改造。 + +## 实验分组 + +| 组别 | 历史窗口 | DOM 窗口 | minimap | +| --- | --- | --- | --- | +| A 基线 | 每次增加 80 条 | 保留 | 无 | +| B 本阶段 | 当前已加载消息全部可访问 | 保留 | 无 | +| C 下一阶段 | 当前已加载消息全部可访问 | 保留 | 有 | + +A 组保留在组件级回归测试中;B 组是当前生产实验;C 组待 B 组稳定后实现。 + +## 功能测试计划 + +- 100 条消息:打开会话后直接滚到第一条,不出现加载按钮。 +- 500 条消息:从底部连续滚到顶部,检查消息顺序、首尾消息和滚动位置。 +- 2,000 条消息:在中部、顶部和底部来回滚动,确认高度占位和锚点不跳动。 +- 消息交互:展开 reasoning/tool details、输入答案、选择文本、打开附件后滚出再滚回,确认状态保留。 +- 流式消息:生成过程中滚动、暂停跟随底部,再回到底部,确认自动跟随行为不变。 +- 摘要会话:打开只有 `messageSummary` 的会话,确认仍然先加载历史,不把摘要误当作完整消息。 + +## 性能测试计划 + +每个规模至少运行 5 次,分别记录冷打开和已经打开后的滚动表现。低端机模拟沿用已有性能测试配置,结果记录中注明运行环境。 + +记录指标: + +- 会话打开到首屏可交互的耗时; +- 首次滚到顶部的耗时; +- 连续滚动期间长任务和掉帧; +- Renderer 内存峰值和测试结束后的回收情况; +- 实际挂载消息数量; +- 流式输出时输入延迟。 + +通过条件:B 组功能测试全部通过,实际挂载消息数量仍受窗口上限控制;相对 A 组没有明显的输入、流式输出或滚动回归。若 B 组稳定,再以同一批数据实现 C 组并做增量对比。 + +## 验证命令 + +```text +npm exec vitest run src/renderer/src/ChatHistoryPane.test.tsx src/renderer/src/ChatTimeline.test.tsx +npm run typecheck +npm run lint +npm run perf:app +``` + +`perf:app` 的具体参数和输出以仓库脚本当前实现为准;无法在自动化环境观察的内存和掉帧指标,需要补充 Electron 手工记录。 diff --git a/docs/pr-articles/2026-09-26-unreleased/article.md b/docs/pr-articles/2026-09-26-unreleased/article.md index ae7bc075..08ebaf88 100644 --- a/docs/pr-articles/2026-09-26-unreleased/article.md +++ b/docs/pr-articles/2026-09-26-unreleased/article.md @@ -1,14 +1,14 @@ # GoodBuddy 更新:故事图谱、Obsidian接入、Runtime原生终端 -> **编辑标注说明(对外发布前删除):** 本稿汇总桌面版 0.13.8 至 0.15.11,以及其后截至 `e50ca6d1` 的已提交变化,更新于 2026-10-05。所述功能与修复均已开发完成并提交,验证及发布归属另行标注;原故事线概念图仅作示意,待换为生产界面截图。“待补图”表示缺少可发布素材,“待替换”表示发布信息未核验,“待核对”表示发布前需要确认的行为。本文是宣传草稿,尚未对外发布。 +> **编辑标注说明(对外发布前删除):** 本稿汇总桌面版 0.13.8 至 0.15.13,以及其后截至 `384683e8` 的已提交变化,更新于 2026-10-08。所述功能与修复均已开发完成并提交,验证及发布归属另行标注;原故事线概念图仅作示意,待换为生产界面截图。“待补图”表示缺少可发布素材,“待替换”表示发布信息未核验,“待核对”表示发布前需要确认的行为。本文是宣传草稿,尚未对外发布。 GoodBuddy 这一轮更新围绕工作记录的整理与使用展开:监督者把分散的事件归入持续发展的故事,从中整理带有来源和适用条件的经验,供人和助手在后续工作中查阅。笔记连接支持保存聊天正文、返回原会话,以及在聊天中读写本机 Obsidian 笔记。本地项目还可以从输入区打开 Continue、OpenCode 原生终端或 DS Web 客户端,沿用当前项目与模型配置。 -本文接续上一份画布笔记与文档处理更新稿,覆盖 0.13.8 起的实际增量。这次还加入了智能心跳、笔记标签、会话图片保存、Telegram 私聊和工作区文件导入。项目与会话集中到同一个菜单,提问和执行任务也无需再切换工作模式。远程统一执行与文件导入建议配套 Desktop 0.15.11 和 Agent 0.15.4,请先升级桌面端,再更新 Host 环境;最新远程启动修复还需包含后续提交的 Agent。 +本文接续上一份画布笔记与文档处理更新稿,覆盖 0.13.8 起的实际增量。这次还加入了智能心跳、笔记标签、会话图片保存、Telegram 私聊和工作区文件导入。项目与会话集中到同一个菜单,提问和执行任务也无需再切换工作模式。远程统一执行、文件导入和后续 Runtime 修复建议配套 Desktop 0.15.13 和 Agent 0.15.6,请先升级桌面端,再更新 Host 环境。 -> **【待替换 R01|版本与体验入口】** 最新已核查桌面 tag `v0.15.11` 与 Agent tag `agent-v0.15.4` 均指向 `78afec77`。本轮检查 `9527402..e50ca6d1`,共 60 个提交;Telegram 私聊、历史耗时缺失提示、自定义回顾日期及最新运行修复位于这些 tag 之后,发布版本待确认。对外发布前核验公开安装包、发布日期、下载地址和完整更新日志链接,并在此补入。桌面 0.13.14 的发布失败后由 0.13.15 承接。 +> **【待替换 R01|版本与体验入口】** 当前版本资料为 Desktop `0.15.13`、Agent `0.15.6`;本轮检查 `e50ca6d1..384683e8`,共 22 个提交。`0.15.12`、`0.15.13` 的发布说明已覆盖其中的主要功能,后续测试和发布维护提交不单独作为新功能。对外发布前仍需核验公开安装包、发布日期、下载地址和完整更新日志链接,并在此补入。桌面 0.13.14 的发布失败后由 0.13.15 承接。 -**升级前,请先关闭应用并备份完整用户数据。** 数据库、设置和相邻的 `notes/` 目录需要成套保留;如有 WAL 文件,也应一并备份。当前核查提交的助理数据库格式为 61,0.15.11 标签对应格式为 60;升级后旧客户端不能直接打开新版数据库,回退需要升级前的备份。大库首次转换可能需要等待。高频本地保存调整了磁盘同步策略,断电时可能丢失最近尚未同步的写入。 +**升级前,请先关闭应用并备份完整用户数据。** 数据库、设置和相邻的 `notes/` 目录需要成套保留;如有 WAL 文件,也应一并备份。当前核查提交的助理数据库格式为 62,0.15.13 之前的客户端不能直接打开新版数据库,回退需要升级前的备份。大库首次转换可能需要等待。高频本地保存调整了磁盘同步策略,断电时可能丢失最近尚未同步的写入。 ## 新增功能 @@ -104,7 +104,7 @@ GoodBuddy 这一轮更新围绕工作记录的整理与使用展开:监督者 ### 笔记支持标签筛选,列表与正文并排浏览 -给笔记加上“项目资料”“待整理”等标签后,可以按标签查找,也可以同时选择多个标签,筛出同时带有这些标签的笔记。每篇最多添加 10 个标签;标签支持改名、同名合并和删除,删除标签会保留笔记正文。 +给笔记加上“项目资料”“待整理”等标签后,可以按标签查找,也可以同时选择多个标签,筛出同时带有这些标签的笔记。标签管理器可以直接新建标签,也支持改名、同名合并和删除;每篇最多添加 10 个标签,删除标签会保留笔记正文。 宽窗口打开笔记时,左侧保留列表,右侧阅读和编辑正文,两栏宽度可以拖动调整。切换笔记时保留当前工作区内的筛选与阅读位置,有未保存内容时会提示。窄窗口可从正文工具栏打开笔记列表抽屉,选完笔记后继续阅读;记录索引默认收起,“新建笔记”固定在页头。 @@ -178,7 +178,7 @@ GoodBuddy 这一轮更新围绕工作记录的整理与使用展开:监督者 ### 将本机文件导入本地或远程工作区 -工作区文件面板的“新建文件”旁新增导入入口。选定目标目录后,可以批量选择本机文件,复制到本地项目或上传到远程 Host,随后在文件列表中查看。远程导入需要配套 Agent 0.15.4 或包含该功能的更新版本。 +工作区文件面板的“新建文件”旁新增导入入口。选定目标目录后,可以批量选择本机文件,复制到本地项目或上传到远程 Host,随后在文件列表中查看。远程导入需要配套 Agent 0.15.6 或包含该功能的更新版本。 导入遇到同名文件时保留原文件,单个文件失败后继续处理其余文件。列表可以按名称、修改时间或可用的创建时间排序;排序针对当前目录已读取的条目,每目录最多 500 条。 @@ -286,10 +286,18 @@ GoodBuddy 这一轮更新围绕工作记录的整理与使用展开:监督者 文档解析、分块与摘要哈希计算也转到后台线程;笔记网格、工作区文件树和知识库文档表主要绘制可见区域,终端连续输出合并刷新。启动时按需加载部分组件,并在后台准备工具环境,需要这些工具时再等待准备完成。 +### 存储与请求路径合并,减少主进程等待 + +桌面端的 Assistant、Knowledge、附件、运行绑定和用量记录现在由同一个存储工具进程负责,主进程通过类型化的异步调用访问。查询、文件操作和回顾来源读取共用这条路径,启动升级、取消、关闭排空和存储进程异常都有明确状态;原有事务顺序、提交确认和数据路径保持不变。 + +这次同时移除了没有实测依据的产品侧请求队列和部分并发上限,工作负载交给实际的存储和 Runtime 主机处理。文档解析不再额外设置不受支持的 worker 队列限制。存储进程故障时,已确认提交的数据可以继续读取,未确认写入会明确报告,应用不会把不确定结果静默当成成功。 + ### 设置页减少来回查找 长设置表单的分类标题与相关页签固定在顶部,请求 Header、Body 等低频选项收进高级设置。默认工作目录移到“平台功能 → 通用设置”,Skills 和 MCP 页面移除重复标题,保留导入与添加操作。 +从外部路径直接打开设置页时,目标页会在进入前完成必要的预加载,减少先显示空白内容再补齐设置的情况。 + 设置导航按用途分组,开关统一放在右侧。通用设置集中放置会话与通知、工作目录等选项;本地语音和嵌入模型页面提供“模型下载源”快捷入口,可打开统一弹窗,在 ModelScope 与 Hugging Face 之间切换。选择影响后续托管模型下载,已安装模型、ZIP 导入、Ollama 和应用更新不受影响。 外观设置新增透明磨砂效果,当前默认开启;标题栏和相关卡片使用半透明背景,可以看到其后的应用内容。可以关闭恢复实色显示,已有的外观选择继续保留。 @@ -308,6 +316,10 @@ HTTP OCR 高级设置可以直接选择是否保留页眉、页脚、页码等 会话运行或正在压缩时需等待完成;没有可压缩的较早历史时会提示。这项修复适用于本地直连文本会话,不包含图像生成连接、远程通道会话或 SSH 项目。 +### 工具失败后仍可继续直连模型对话 + +直连模型执行工具失败时,失败信息会保留在当前轮次,后续消息仍可以继续发送,不会因为一次工具错误把会话留在无法继续的状态。工具输出分页仍保留必要内容并服从现有大小边界;这项修复不改变工具权限、取消和超时规则。 + ### 长请求持续保留已授权的工具访问 修复桌面 Agent 请求持续超过十分钟后,工具授权提前失效的问题。请求仍在执行时,已启用并分配的知识库、笔记、浏览器等工具可继续使用;完成、取消或失败清理时仍会撤销该次授权。工具自身的调用超时、读写权限和开关设置保持不变。 @@ -326,9 +338,9 @@ HTTP OCR 高级设置可以直接选择是否保留页眉、页脚、页码等 最后一个活动任务结束后,远程空闲 Runtime 会被释放,下一轮对话再恢复历史。仍有任务或待答问题的共享进程会保留;更新后被替换的旧 Agent 会等待已有工作结束再退出,当前 Agent 保持常驻。 -Host 更新还会清理已确认停用的旧 Agent 程序和归属明确的孤儿进程,保留会话历史、活动安装和状态不明的安装。这些完成状态与进程清理修复自 Agent 0.13.4 起提供;本轮基础配套为 Agent 0.15.4,仅升级桌面不会直接替换 Host 上已经运行的旧进程。 +Host 更新还会清理已确认停用的旧 Agent 程序和归属明确的孤儿进程,保留会话历史、活动安装和状态不明的安装。这些完成状态与进程清理修复自 Agent 0.13.4 起提供;本轮配套为 Agent 0.15.6,仅升级桌面不会直接替换 Host 上已经运行的旧进程。 -最新修复使远程 Runtime 在等待启动时仍可取消,并避免阻塞其他会话;本地 OpenCode 提交失败后也能及时结束等待并显示原因。远程部分需要包含 `bbf24c28` 改动的 Agent,不属于已核查的 Agent 0.15.4 标签。 +最新修复使远程 Runtime 在等待启动时仍可取消,并避免阻塞其他会话;本地 OpenCode 提交失败后也能及时结束等待并显示原因。远程部分随 Agent 0.15.6 提供,升级 Host 后新启动的 Runtime 才会使用更新后的代码。 ### 通道交付与统计结果 @@ -344,6 +356,7 @@ Host 更新还会清理已确认停用的旧 Agent 程序和归属明确的孤 - 修复本机直连模型文件搜索参数受限和大结果截断的问题。模型可使用 ripgrep 原生参数,保留原生结果与退出码,并分页续读长输出;工具使用当前执行账户权限。这项变更不属于远程 Agent 或其他 Runtime 的新增工具。 - 修复早期监督回顾只取部分会话、消息和正文的问题,改为对入选来源分页、分批处理。事实与来源独立保存,只有必要阶段完成并成功保存结果后才标记完成。 - 修复监督回顾中的旧实体引用、摘要合并校验及长摘要报错。遇到无效 JSON、结构或引用时,会尝试缩小当前批次后重试,剩余正文留待后续处理;成功保存的批次保留。 +- 修复回顾来源使用短引用或已知历史键时被错误拒绝的问题;删除会话后,相关回顾仍可继续查看和处理,暂停、继续、重试及项目范围校验保持有效。 - 监督模型遇到可识别的临时网络中断、限流或部分服务端错误时,清理失败请求后自动再试一次,等待期间可以取消。认证、配置、费用额度、超时、取消及容量错误不会触发这次重试;失败尝试已报告的用量仍会记录,重试可能增加模型费用。 - 故事或经验整理失败时,已保存的回顾结果继续可用,可以单独重试整理。故事归类减少把各功能的提交与测试统归到“发布”的情况;经验应用记录也增加时间顺序与共同实体核对,归纳内容仍需结合来源判断。 - 时间螺旋退出时释放图形资源;3D 初始化失败或图形上下文丢失时,在视图内提示并提供重试,也可切回平铺,避免整个监督页面无法使用。 diff --git a/docs/pr-articles/2026-09-26-unreleased/review.md b/docs/pr-articles/2026-09-26-unreleased/review.md index 82ca4dc0..ced40de9 100644 --- a/docs/pr-articles/2026-09-26-unreleased/review.md +++ b/docs/pr-articles/2026-09-26-unreleased/review.md @@ -1,5 +1,21 @@ # 0.13.8 起综合宣传稿核查记录 +## 2026-10-08 截至 384683e8 的增量核查 + +本轮固定范围 `e50ca6d1..384683e8`,共 22 个提交;全文范围为 `v0.13.7..384683e8`。版本资料已推进到 Desktop 0.15.13、Agent 0.15.6;HEAD 位于版本准备提交之后,最后一组提交主要是存储故障验收夹具和测试稳定化,不另列为产品功能。正文仍按新增功能、功能改进、问题修复组织,并将连续的架构与性能改动合并为一节。 + +| 提交 | 入文内容 | 核查依据与边界 | +| --- | --- | --- | +| `d80d42b0`、`8473189f`、`904bb691`、`1f85d0c0` | 合并为“存储与请求路径合并,减少主进程等待” | Desktop SQLite 的 Assistant、Knowledge、附件、Runtime 绑定和用量记录改由同一 storage utility process 负责;查询、文件操作和回顾来源读取共用类型化异步调用。同步保留事务、提交确认、取消、关闭排空和故障报告边界。移除无依据的产品侧 admission、子任务和解析 worker 队列上限,不宣传为全量并发或跨平台性能验收;存储进程故障后未确认写入仍需按域核对。 | +| `13c29bad`、`c1e4bbf6`、`3e3a0216` | 更新魔法笔记标签节 | 标签管理器新增直接创建标签;保留空标签集合,重复标签错误保留原始原因。正文不扩大为自动打标签或取消每篇最多 10 个标签的限制。 | +| `e0607a15`、`2be57492` | 合入回顾结果修复 | 支持短引用和已知历史键映射;删除会话后回顾可继续查看或处理,暂停、继续、重试及项目范围规则仍有效。 | +| `56b8b10d` | 新增直连模型工具失败后的继续对话说明 | 工具执行失败不会阻塞后续直连模型消息,分页输出边界、工具权限、取消和超时规则保留。 | +| `425accf4`、`4bb7573b`、`edf019aa` | 合入日常界面改进 | 直接进入设置页时预加载目标路由;工作区文件列表元数据和聊天输入区过渡更简洁。均不单列为新能力。 | +| `b90ff50f`、`36e671a0`、`fbfafa15` | 更新版本与监督稳定性依据 | 监督任务交付和停顿修复并入既有监督修复范围;版本准备资料为 Desktop 0.15.12/0.15.13、Agent 0.15.5/0.15.6。 | +| `42ad8a98`、`4c25e85b`、`7eb51bd5`、`9212fd43`、`384683e8` | 仅留内部验证依据 | 存储故障验收、权限夹具、容量断言和测试竞态稳定化,不写入宣传正文,也不据此宣称完整 C01–C07 或跨平台性能验收完成。 | + +本轮未修改产品代码,仅更新宣传正文、核查记录和索引。未运行产品测试、构建、真实模型请求或拍摄新截图;本轮提交中的测试记录只作为静态核查依据。生产配图、Telegram 真实联调和公开下载信息继续待核验。deai-writing 扫描结果为阻断项 0、复核项 18、读取错误 0;复核项均为版本、素材、能力边界或模型结果限定,未机械删除。`git diff --check -- docs/pr-articles` 通过,仅提示既有 LF/CRLF 行尾策略。 + ## 2026-10-05 截至 e50ca6d1 的增量核查 本轮最终范围 `9527402..e50ca6d1`,共 60 个提交;全文范围为 `v0.13.7..e50ca6d1`。初次固定至 `bbf24c28` 的 58 个提交,收尾补查新产生的两项提交。本地桌面 `v0.15.11` 与 Agent `agent-v0.15.4` 同指向 `78afec77`,上一桌面 `v0.15.10` 指向 `ff61da28`。Telegram、自定义回顾日期、历史耗时缺失提示及最后一组运行修复在 0.15.11 标签之后,均已提交,不将其混入该标签,也不使用开发状态标签。以下取代旧节的当前状态描述,旧节仅作历史依据。 diff --git a/docs/pr-articles/README.md b/docs/pr-articles/README.md index c441c0a6..cb33c16d 100644 --- a/docs/pr-articles/README.md +++ b/docs/pr-articles/README.md @@ -386,4 +386,4 @@ Agent 专题使用对应的 `agent-v…` tag。 | 日期 | 目标 tag | 标题 | 状态 | 正文 | 发布链接 | | --- | --- | --- | --- | --- | --- | | 2026-09-19 | 未确定(unreleased) | GoodBuddy 更新预览:画布笔记、文档处理与应用管理 | 草稿,截图待补 | [综合更新稿](./2026-09-19-unreleased/article.md) | 未发布 | -| 2026-09-26(10-05 更新) | v0.15.11(78afec77)及之后截至 e50ca6d1;汇总 v0.13.8 起的变化 | GoodBuddy 更新:故事图谱、Obsidian接入、Runtime原生终端 | 草稿,已补 Telegram 私聊、统一执行、项目会话菜单、文件导入、自定义回顾日期、监督模型与会话图谱开关、临时失败重试、3D 和性能改进;Telegram 实际联调、生产配图及公开发布信息待核验 | [综合更新稿](./2026-09-26-unreleased/article.md) | 未发布 | +| 2026-09-26(10-08 更新) | Desktop 0.15.13/Agent 0.15.6 及之后截至 384683e8;汇总 v0.13.8 起的变化 | GoodBuddy 更新:故事图谱、Obsidian接入、Runtime原生终端 | 草稿,新增存储架构与请求路径合并、标签创建、回顾来源兼容和直连模型失败后继续对话;Telegram 实际联调、生产配图及公开发布信息待核验 | [综合更新稿](./2026-09-26-unreleased/article.md) | 未发布 | diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index f53e6e94..d95326f3 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -131,10 +131,7 @@ import type { ImageViewerItem, Message, } from "./ChatTimeline"; -import { - messageRenderBatchSize, - type ChatScrollSnapshot, -} from "./ChatHistoryPane"; +import type { ChatScrollSnapshot } from "./ChatHistoryPane"; import { usePaneOrder } from "./pane-order"; import { getConversationDisplayTitle, isUnusedConversation, type Conversation } from "./chat-conversation"; import { @@ -1806,9 +1803,6 @@ function App(): React.JSX.Element { ), [], ); - const [visibleMessageCounts, setVisibleMessageCounts] = useState< - Record - >({}); const sidebarRef = useRef(null); const sidebarToggleRef = useRef(null); const livePrimarySidebarWidthRef = useRef(primarySidebarWidth); @@ -1863,15 +1857,6 @@ function App(): React.JSX.Element { }, [], ); - const handleVisibleMessageCountChange = useCallback( - (conversationId: string, count: number): void => { - setVisibleMessageCounts((current) => ({ - ...current, - [conversationId]: count, - })); - }, - [], - ); const closeNarrowSidebar = useCallback((): void => { setSidebarOpen(false); requestAnimationFrame(() => sidebarToggleRef.current?.focus()); @@ -4580,11 +4565,6 @@ function App(): React.JSX.Element { delete next[conversationId]; return next; }); - setVisibleMessageCounts((current) => { - const next = { ...current }; - delete next[conversationId]; - return next; - }); setConversationActivity(conversationId, false); const remaining = conversationStore.getState().filter( (conversation) => conversation.id !== conversationId, @@ -5941,7 +5921,6 @@ function App(): React.JSX.Element { const index = conversation.messages.findIndex(item => item.id === targetId); if (index < 0 || !snapshot.messages.some(message => message.id === targetId)) notify({ tone: 'info', message: t('magicNotes:capture.missingMessage') }); else { - setVisibleMessageCounts(current => ({ ...current, [source.conversationId]: Math.max(current[source.conversationId] ?? messageRenderBatchSize, conversation.messages.length - index) })); setNoteMessageNavigation({ conversationId: source.conversationId, messageId: targetId, requestId: Date.now() }); } } @@ -7081,19 +7060,12 @@ function App(): React.JSX.Element { onSelectTask={setSelectedAssistantTaskId} onSetInput={setQuickActionInput} onSetScheduleEnabled={setAssistantScheduleEnabled} - onVisibleMessageCountChange={ - handleVisibleMessageCountChange - } quickActions={quickActions} schedules={assistantSchedules} scrollSnapshot={chatScrollSnapshots[conversationId]} selectedAssistantTaskId={selectedAssistantTaskId} store={conversationStore} tasks={tasksByConversation.get(conversationId) ?? emptyConversationTasks} - visibleMessageCount={ - visibleMessageCounts[conversationId] ?? - messageRenderBatchSize - } /> ))} {activeProject?.kind === "channel" && diff --git a/src/renderer/src/ConversationHistorySlot.tsx b/src/renderer/src/ConversationHistorySlot.tsx index fd0ec5ca..38ab2d97 100644 --- a/src/renderer/src/ConversationHistorySlot.tsx +++ b/src/renderer/src/ConversationHistorySlot.tsx @@ -37,7 +37,9 @@ function ConversationHistoryLoader({ conversationId, active, load }: { ; } -type PaneProps = Omit, "conversation" | "taskStrip" | "artifactById">; +type PaneProps = Omit, "conversation" | "taskStrip" | "artifactById" | "onVisibleMessageCountChange" | "visibleMessageCount">; + +const ignoreVisibleMessageCountChange = (): void => undefined; export type ConversationHistorySlotProps = PaneProps & { conversationId: string; @@ -110,5 +112,12 @@ export const ConversationHistorySlot = memo(function ConversationHistorySlot({ /> ); } - return ; + return ; });