Skip to content

feat(desktop): unify sparse transcript paging with turn virtualization #4123

Description

@Astro-Han

Problem

Desktop keeps transcript memory and IPC bounded by loading durable messages in byte-limited ranges. The renderer also keeps the DOM bounded through turn virtualization.

These two mechanisms currently stop at different boundaries:

  • DesktopTranscriptReplica owns only the currently resident durable range. Loading around a target replaces that range.
  • The renderer turn virtualizer derives its logical turns only from resident messages.
  • The prompt rail uses a separate sampled landmark index that can span the complete conversation.

As a result, navigating to an unloaded prompt replaces the visible transcript range. Durable messages outside that range remain stored, but their logical positions disappear from the renderer until another range is loaded. #3880 makes this state understandable, but the product should ideally present one continuous conversation without exposing resident versus non-resident history.

The 512 KiB range limit is a transport and memory budget, not a conversation limit. Increasing it would only move the threshold.

Desired outcome

Users can navigate one continuous logical transcript, including unloaded history, while message bodies, renderer state, IPC, and mounted DOM remain bounded.

Loading or evicting a content page must not remove its logical place from the conversation or make other durable turns appear deleted.

Suggested architecture boundary

  • Runtime Host and storage remain the only durable transcript authority.
  • Preserve the existing bounded transcript page protocol and Main/Renderer cache budgets.
  • Expose a lightweight, pageable logical turn-position index across the conversation. It should carry only the identity and ordering needed for layout and navigation, not duplicate message bodies.
  • Let the renderer virtualizer operate on those logical positions and represent unloaded ranges as gaps or spacers.
  • Load message bodies around the viewport, overscan window, and explicit navigation target.
  • Evict content pages without removing their logical positions.
  • Preserve the scroll anchor while estimated gaps are replaced by measured content.
  • Keep sampled prompt landmarks as a navigation projection, not a second transcript or layout authority.

The exact protocol shape should follow the closest existing paging and virtualization seams. This issue does not require introducing another transcript store or retaining the complete transcript in Renderer memory.

Acceptance criteria

  • Jumping from the live tail to an unloaded old or intermediate prompt loads the target without presenting the conversation as a different standalone range.
  • Returning to the tail preserves the same logical transcript and live-tail behavior.
  • Page loading and eviction preserve scroll position and scrollbar continuity.
  • Mounted transcript DOM remains bounded by the existing turn-window budget.
  • Main and Renderer content caches remain within their existing byte budgets.
  • Active-overlay to durable-message handoff remains correct at the live tail.
  • Keyboard and screen-reader navigation work across loaded and unloaded ranges.
  • Copy/export reads from the complete data model rather than only the mounted or resident window.
  • Regression coverage includes a transcript larger than twice the range budget and navigation between tail, intermediate, and old ranges.

Alternatives considered

  • Increase the 512 KiB range budget: postpones the same discontinuity to a larger transcript.
  • Retain several disconnected resident ranges: adds another cache representation without providing one stable logical layout.
  • Explain resident ranges only in the UI: fix(desktop): clarify partial transcript ranges #3880 correctly improves the current behavior, but the user still has to understand an internal paging state.

Related work

@Sun-GLiang, if you are interested, this would be a natural architectural follow-up to #3880. The current PR does not need to expand to include it.

This issue was prepared with Codex under maintainer direction after reviewing the current transcript paging and virtualization boundaries. The maintainer owns the problem definition and proposed direction.

简体中文

问题

Desktop 通过按字节限制的范围加载来控制 transcript 的内存和 IPC 使用,同时通过 turn virtualization 控制挂载的 DOM 数量。

目前这两套机制停在了不同的边界:

  • DesktopTranscriptReplica 只拥有当前驻留的持久化范围,围绕新目标加载时会替换这个范围。
  • Renderer turn virtualizer 只能根据当前驻留的消息建立逻辑 turns。
  • Prompt rail 使用另一份可以覆盖整段对话的抽样 landmark index。

因此,导航到未加载的 prompt 时,当前可见的 transcript 范围会被替换。范围外的持久化消息仍保存在 storage 中,但它们的逻辑位置会暂时从 Renderer 中消失。#3880 正确解释了这个状态,但理想的产品体验应该是一条连续的对话,不需要向用户暴露驻留和未驻留历史的区别。

512 KiB 是传输和内存预算,不是对话历史上限。提高这个数值只会把问题推迟到更大的 transcript。

目标结果

用户可以在一条连续的逻辑 transcript 中导航,包括尚未加载的历史;与此同时,消息正文、Renderer state、IPC 和已挂载 DOM 仍保持有界。

内容页面的加载或淘汰不能移除它在对话中的逻辑位置,也不能让其他持久化 turns 看起来像被删除。

建议的架构边界

  • Runtime Host 和 storage 继续作为 transcript 唯一的持久化权威。
  • 保留现有的有界 transcript page protocol 和 Main/Renderer 缓存预算。
  • 提供覆盖整段对话、可分页的轻量逻辑 turn position index。它只携带布局和导航所需的身份与顺序,不复制消息正文。
  • Renderer virtualizer 基于这些逻辑位置工作,把未加载范围表示成 gap 或 spacer。
  • 围绕 viewport、overscan window 和明确的导航目标加载消息正文。
  • 淘汰内容页面时不移除其逻辑位置。
  • 用实际内容替换估算 gap 时保持滚动锚点稳定。
  • 抽样 prompt landmarks 继续只负责导航,不成为第二份 transcript 或布局权威。

具体协议形态应该扩展现有的 paging 和 virtualization seam。这个 issue 不要求增加另一份 transcript store,也不要求在 Renderer 内存中保留完整 transcript。

验收标准

  • 从 live tail 跳到未加载的较早或中间 prompt 时,可以加载目标,但不会把对话表现成另一段独立范围。
  • 返回 tail 时仍处于同一条逻辑 transcript 中,并保持正常 live-tail 行为。
  • 页面加载和淘汰期间保持滚动位置与 scrollbar 连续。
  • 已挂载 transcript DOM 继续受现有 turn-window 预算限制。
  • Main 和 Renderer 内容缓存继续遵守现有字节预算。
  • Live tail 的 active-overlay 到 durable-message handoff 保持正确。
  • 键盘和 screen reader 可以跨已加载与未加载范围导航。
  • Copy/export 从完整数据模型读取,而不是只读取已挂载或驻留窗口。
  • 回归测试包含大于两倍 range budget 的 transcript,以及 tail、中间和较早范围之间的导航。

考虑过的替代方案

  • 提高 512 KiB range budget: 只会把同样的断层推迟到更大的 transcript。
  • 同时保留多个不连续的驻留范围: 增加另一种缓存表示,但没有提供稳定、统一的逻辑布局。
  • 只在 UI 中解释驻留范围: fix(desktop): clarify partial transcript ranges #3880 正确改善了当前行为,但用户仍然需要理解内部的分页状态。

相关工作

@Sun-GLiang,如果你有兴趣,这会是 #3880 很自然的架构后续。当前 PR 不需要扩大范围来包含这项工作。

本 issue 由 Codex 在维护者指示下,根据当前 transcript paging 与 virtualization 边界的审查结果整理。问题定义和建议方向由维护者负责。

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions