Skip to content

feat(desktop): 会话已加载窗口显式建模,孤岛接回主段后零成本跳转 - #3693

Open
Michael-Yu2978 wants to merge 1 commit into
makecindy:mainfrom
Michael-Yu2978:codex/featb
Open

feat(desktop): 会话已加载窗口显式建模,孤岛接回主段后零成本跳转#3693
Michael-Yu2978 wants to merge 1 commit into
makecindy:mainfrom
Michael-Yu2978:codex/featb

Conversation

@Michael-Yu2978

@Michael-Yu2978 Michael-Yu2978 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

feat B「会话已加载窗口显式建模」:把 makerChatStore 里「窗口是否掺过孤岛」的布尔
historyWindowHasIsland)升级为显式孤岛区间模型
historyWindowIslands: readonly LoadedWindowIsland[](每座孤岛 {oldestClientId, newestClientId}
按时间升序)。

背景(#676 review 之后与 MessageStream 锚定窗口双向有界 TODO 同一条后续改动):单个布尔
无法回答「目标落在窗口哪一段」,于是「孤岛 + 已翻到历史起点」的会话每次窗口内搜索都被迫
多发一轮 around + list 探测,窗口其实早已补成连续。显式模型下:孤岛被向上翻页真的跨过
(接回主段)时自动从模型消失;目标落在主连续段(最新尾段,最后一个孤岛最新边界行之后的
全部行)内时,搜索 / 跳转直接 focus、零网络。生产入口(CCAgentSessionView 的 searchJump
effect)与 store 侧补齐快速通道共用同一把结构尺子 isInsideMainContiguousRun,不会再出现
「生产判定与自愈判定漂移」的 #676 类问题。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护
  • 其他:

范围

  • 关联 Issue / 需求:5-PR 提案 feat B;来源线程分析见 searchJumpTargeting.ts 的「孤岛 + 已翻
    到历史起点」注释与 fix(desktop): 跳转历史消息不再留窗口空洞,工作组不跨空洞合并 #676 review(bce583965)
  • 本 PR 包含:
    • apps/desktop/src/renderer/lib/searchJumpTargeting.ts:新 API(LoadedWindowIsland
      mainContiguousRunStartIndexisInsideMainContiguousRuncanFocusWithoutJumpLoad
    • apps/desktop/src/renderer/lib/makerChatStore.tsSessionChatState.historyWindowIslands
      (必填)替换旧布尔;SessionChatLightState 保留派生布尔 historyWindowHasIsland;接入
      trim / demote / reload / clear / removeMessagesByClientIds / dropMessagesFromClientId
      (edit-last)/ loadOlderMessages / 初始加载两次 setState / 权威重建(reconcile)/
      around 提交(busy / covered / fallback);新增收口助手
      absorbIslandsCrossedByPagingupdateIslandsAfterAroundMerge
      pruneIslandsForTrimmedWindowconservativeIslandsForconservativeIfIslandRowRemoved
      pruneIslandsAfterNewestTruncation
    • apps/desktop/src/renderer/hooks/useCCAgentChat.ts:sessionless light 快照改用
      EMPTY_LIGHT_STATE
    • 测试:searchJumpTargeting.test.ts(重写)、makerChatStoreJumpBackfill.test.ts(T 三阶段 +
      新增 T2 / T3 / Y 语义更新)、makerChatStoreActiveView / makerQueueState /
      reconcileRemoteMessages(断言迁移)
  • 明确不包含:MessageStream 锚定窗口双向有界 TODO 本身、其它 5-PR 提案项
  • 用户可见变化:窗口内搜索 / 引用跳转在「孤岛已补齐」后不再白打探测,行为更顺;无视觉变化
  • 是否存在 breaking change:无(historyWindowIslands 是 store 内部模型字段,未跨仓消费;
    对外 light 布尔保留)

UI 变化

  • 引用的设计规范:不涉及:无组件 / 布局 / 样式 / 文案 / 动效改动,命中的是 store 状态模型
    与搜索跳转判定逻辑;UI 消费方(CCAgentSessionView / MessageStream)仍读派生布尔
    historyWindowHasIsland,接口不变。

怎么验证的

自动验证

corepack pnpm --filter desktop run typecheck
结果:PASS

corepack pnpm test:unit:related
结果:PASS(test:runner 445 项 0 失败 + apps/desktop related 全绿)

corepack pnpm test:unit(全量 unit tier)
结果:除 8 项 Windows 上既有的 POSIX 平台用例失败外全部 PASS。失败项全部在
src/main/__tests__/codexAuthLink.test.ts(6 项)与
src/main/maker-host/__tests__/codexAuthInvalidation.test.ts(2 项)——模拟
'darwin'/'linux' 平台的 symlink / hardlink 行为,Windows 文件系统返回 link-unsupported。
已对照验证:把本次改动全部 stash 后在干净树重跑同一批文件,失败数与名单完全一致
(8 failed | 68 passed),确认是既有环境问题、与 feat B 无关;其余 workspace(含
apps/desktop renderer 全部单测、maker-core 等)全绿。本地因全局 pnpm 版本与仓库
engines 不匹配,等价执行方式为 corepack 解析的 pnpm 10.33.2 逐段运行
(test:runner + test-workspaces.mjs --tier unit);最终以 CI 为准。

相关单测覆盖(全部通过):

  • searchJumpTargeting:主段内直跳 / 孤岛上交回 store / 多孤岛间洞 / 边界行缺失保守全 false
  • jumpBackfill T:孤岛重跳仍补齐;T2:两孤岛序列只收口被跨过的那座;T3:翻页填洞后同目标
    零分页请求;Y:整座被裁掉的孤岛随洞消失、保留尾段恢复主段
  • reconcile / activeView / queueState:断言迁移到区间模型后全绿

手工验证

未执行实机 GUI / device-link 验证:搜索跳转链路需真实双端联调,本机只覆盖到 store 与纯函数
单测;canFocusWithoutJumpLoad 的判定与 store 快速通道共用同一把尺子,单测已直接覆盖生产入口
(CCAgentSessionView 的 searchJump effect 调用的就是该纯函数)。

未执行的验证

  • 实机 / 真机 GUI 目检(搜索跳转、翻页、device-link 隧道下的窗口收口)
  • absorbIslandsCrossedByPaging 的「row id 游标」分支:测试里 id === clientId,未直接命中
    生产形态的分叉(代码为同一匹配函数,审查级确认)

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:孤岛判定的保守性权衡(见下)

影响与回滚

  • 影响范围:desktop renderer 的窗口状态模型与搜索跳转判定;UI 消费接口(light 布尔)不变。
  • 回滚 / 降级方式:revert 本 PR 即可恢复 boolean 模型;无数据 / 兼容 / 协议风险。
    不涉及 SQLite / system prompt / 协议 / 原生层 / 存量插件 / 冷更。

行为变更与边界(如实记录)

  1. 孤岛逐座收口:covered 只证明「尾部 → 本次目标」连续,不证明更早孤岛被跨过;只有翻页
    真的跨过(行落进本批拉取范围)才从模型移除(T2 两孤岛序列守这条)。
  2. around 块连主段判定改在合并前窗口:修复「无孤岛窗口 + 首座失败跳转孤岛」被合并后主段
    起点塌缩吸收、孤岛永远记不上的 bug(T / Y3 回归);判据是「块里至少有一行本来就躺在
    合并前主段里」。
  3. 裁剪精确收口slice(-TRIM_TARGET) 后,整座被裁掉的孤岛随洞消失(Y 用例语义更新),
    仍夹在保留窗口里的孤岛保留(Y3 覆盖)——比旧 boolean「一律保留」更精确且不丢不变量。
  4. busy 路径:around 带回新行且落在主段更老一侧时记孤岛(旧代码会被主段起点塌缩
    跳过);一行都没加进来时不记(Z「零新增」语义不变)。
  5. 保守兜底:孤岛边界行不在窗口里(模型被破坏)时,主段置空、任何目标都走补齐尝试;
    hasMore=false 不再作为短路依据(fix(desktop): 跳转历史消息不再留窗口空洞,工作组不跨空洞合并 #676 codex P1 的「孤岛 + 已翻到历史起点」仍可被 around
    捞回缺的邻居)。
  6. 游标匹配absorbIslandsCrossedByPaging 的边界按 clientId || id 匹配——生产分页
    游标是 DB row id,只按 clientId 会让边界永远落空、孤岛不收口。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s,见 DCO)——重提后为 1 个 commit 并已签名(已重基到当前 main,剔除了误带入 fix(desktop): 诊断页与会话视图硬编码颜色改用语义 token #3686 的两个语义 token commit),pnpm check:dcoorigin/main..HEAD 全部通过
  • UI 改动已在「UI 变化」注明引用的设计规范章节(不涉及 UI,已注明理由)
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档(本 PR 说明 + 代码内行为注释)
  • 已确认测试结果或说明未执行原因

@Michael-Yu2978
Michael-Yu2978 requested a review from a team as a code owner August 31, 2026 12:55
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown

Greptile Summary

本 PR 将桌面会话历史窗口从单一孤岛布尔值升级为显式孤岛区间模型,使分页补齐后的孤岛能够逐段收口,并让主连续段内的搜索或引用跳转直接聚焦。

  • 新增主连续段判定,并在生产跳转入口与 store 快速通道间复用
  • 在分页、around 合并、裁剪、删除、截断、重载和远程对账路径中维护孤岛区间
  • 保留轻量状态的派生布尔接口,并补充窗口收口与主题 token 契约测试
  • 将相关桌面视图中的裸色值替换为双模式语义 token

Confidence Score: 5/5

未发现需要阻止合并的具体问题,本 PR 看起来可以安全合并。

显式孤岛模型在分页、合并和窗口形变路径中采用保守维护策略,远程裁剪与隐藏消息过滤也未形成提前清除孤岛或漏补齐的可达故障。

Important Files Changed

Filename Overview
apps/desktop/src/renderer/lib/makerChatStore.ts 用显式孤岛区间替代内部布尔状态,并在所有主要窗口形变和补齐路径中维护该模型;未发现可发布缺陷。
apps/desktop/src/renderer/lib/searchJumpTargeting.ts 新增主连续段计算与共享跳转判定,使 UI 和 store 对零成本跳转采用一致规则。
apps/desktop/src/renderer/features/cc-agent/CCAgentSessionView.tsx 将 handoff 与容量环颜色迁移到语义主题 token,未改变交互逻辑。
apps/desktop/src/renderer/features/maker-experimental/MakerExperimentalView.tsx 将诊断视图的硬编码颜色系统性替换为已注册的双模式主题 token。
apps/desktop/src/renderer/hooks/useCCAgentChat.ts sessionless 轻量订阅改用形状匹配且稳定的 EMPTY_LIGHT_STATE。
apps/desktop/src/renderer/tests/makerChatStoreJumpBackfill.test.ts 增加多孤岛逐座收口、填洞后零网络跳转及裁剪语义回归覆盖。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[搜索或引用目标] --> B{目标位于主连续段?}
  B -- 是 --> C[直接 focus]
  B -- 否 --> D[around 与向上分页补齐]
  D --> E[合并返回消息]
  E --> F[收口被分页跨过的孤岛]
  F --> B
Loading

Reviews (1): Last reviewed commit: "feat(desktop): 会话已加载窗口显式建模,孤岛接回主段后零成本跳转" | Re-trigger Greptile

@MagicLizi MagicLizi added awaiting-discussion 等待维护者讨论(review-pr) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) labels Sep 1, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

这个 PR 会改变会话跳转 / 已加载窗口的用户体验,已进入维护者确认,球不在作者手里。

请维护者直接在 PR 上 Approve;需要修改就 Request Changes。讨论 issue:#3716

@MagicLizi

Copy link
Copy Markdown
Contributor

命中 UI 路径(会话跳转 / CCAgentSessionView)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面,便于确认界面符合 DESIGN.md 设计规范。

@MagicLizi MagicLizi removed the touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) label Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-discussion 等待维护者讨论(review-pr) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants