Expand description
TCF: fold sources for the *ai:opencode* conversation buffer.
Two [lattice_core::FoldSource]s, both reading the same single-pass
layout (project_conversation) so a fold’s line range can never drift
from the rendered text:
ToolCallFoldSource— one fold per tool call that has capturedinput/outputdetail, spanning its▸ summary [status]head line through the last detail row.ReasoningFoldSource— one fold per multi-line reasoning block.
Both fold closed: true by default (a fresh tool call / reasoning block
opens collapsed; za on the head line expands it). Lattice fold semantics
keep the head line visible (start_line < line <= end_line, see
lattice_host::folds::FoldIndex::line_inside_closed_fold), so a closed
fold shows only the summary and elides the detail rows at the cell layer —
a collapsed transcript costs the renderer nothing per hidden line
(paramount #1).
Mode-owned, exactly the shape diff-mode uses for [HunkFoldSource]:
AiConversationMode::on_activate constructs one of each (holding a
ConversationStore clone) and registers them via the
FoldOverlayService; the mode’s Drop guard removes them. Each holds the
store, so compute_folds reads the currently-published conversation on
every recompute — no FoldContext, no buffer round-trip.
[HunkFoldSource]: crate — see lattice_diff::fold::HunkFoldSource for the
precedent this mirrors.
§Identity — the streaming-coherence fix
A closed fold’s expansion state is carried across recomputes by
[lattice_core::Fold::identity], not by its line range. The transcript
grows above a tool call on every streamed token, shifting its line range;
keying identity on the tool-call id (not the range) is what keeps an
expanded call expanded as content lands above it. Reasoning blocks carry no
wire id, so their identity is keyed on the block’s ordinal in document
order — stable because earlier turns are never rewritten, so a given
reasoning block stays the nth one as it streams.
Structs§
- Conversation
Fold - TCF: one foldable region in the projected transcript, produced by
project_conversation.start_lineis the fold head (stays visible when closed);start_line + 1 ..= end_lineare the rows that hide.identitycarries closed-state across streaming recomputes. - Reasoning
Fold Source - TCF: folds each multi-line reasoning block (closed by default).
- Tool
Call Fold Source - TCF: folds each tool call’s captured detail rows (closed by default).
Enums§
- Conversation
Fold Kind - TCF: which kind of block a
ConversationFoldcovers, so each [FoldSource] can filterproject_conversation’s span list to its own.
Constants§
- REASONING_
FOLD_ NAMESPACE - Namespace for the per-buffer reasoning fold provider id. See
TOOL_FOLD_NAMESPACE. - TOOL_
FOLD_ NAMESPACE - Namespace for the per-buffer tool-call fold provider id. OR’d with the
buffer’s id (low 32 bits) so the source is distinct in the registry —
FoldOverlayService::add_sourcekeys removal on the id. Distinct high bits fromREASONING_FOLD_NAMESPACEso a buffer’s two AI fold sources register under different ids (they coexist over disjoint line regions). Distinct from diff’s0xD1FF_*and multibuffer’s0xBBBB_*namespaces.
Functions§
- reasoning_
fold_ identity - Stable identity for a reasoning fold, keyed on the block’s ordinal in
document order (reasoning blocks carry no wire id). Namespaced with
"ai:reasoning". - tool_
fold_ identity - Stable identity for a tool-call fold, keyed on the wire
tool_call_id(not the line range) so the fold’s expansion state survives a transcript that grows above it. Namespaced with"ai:tool"so it never collides with a primary provider’s hash for the same span.