const std = @import("std");const debug_trace = @import("../core/shared/debug_trace.zig");const display_width = @import("../core/shared/display_width.zig");const io_mod = @import("../core/shared/io.zig");const text_utils = @import("../core/shared/text_utils.zig");const tool_result_display = @import("../core/tooling/tool_result_display.zig");const command_output_content = @import("../core/tooling/command_output_content.zig");const command_replay_store = @import("../core/session/command_replay_store.zig");const result_store = @import("../core/session/result_store.zig");const session_child_store = @import("../core/session/session_child_store.zig");const diff_mod = @import("../core/output/diff.zig");const transcript_presentation = @import("../core/output/transcript_presentation.zig");const assistant_wrap = @import("render_engine/assistant_wrap.zig");const build_checkpoint = @import("render_engine/build_checkpoint.zig");const transcript_blocks = @import("render_engine/transcript_blocks.zig");const command_output_runtime = @import("transcript/command_output_runtime.zig");const tool_group_projection = @import("transcript/tool_group_projection.zig");const user_message_card = @import("assistant/user_message_card.zig");const ui_render = @import("render.zig");const types = @import("../core/shared/types.zig"); const Allocator = std.mem.Allocator; const ToolDetailRecord = transcript_blocks.ToolDetailRecord;const BuildCheckpoint = build_checkpoint.BuildCheckpoint; pub const DetailDepth = enum { review, full };const review_detail_line_limit: usize = 3; const PendingInputProbe = struct { polls: usize = 0, fn pending(context: *anyopaque) bool { const self: *PendingInputProbe = @ptrCast(@alignCast(context)); self.polls += 1; return true; }}; test "projection source index resolves direct tool and command associations" { const alloc = std.testing.allocator; const block_call_id = try alloc.dupe(u8, "command-7"); defer alloc.free(block_call_id); const lookup_call_id = try alloc.dupe(u8, "command-7"); defer alloc.free(lookup_call_id); var block = command_output_runtime.CommandOutputBlock{ .entry_id = 20, .lifecycle_id = .{ .turn_id = 7, .call_id = block_call_id }, .retention_overflow = true, }; try block.source_entry_ids.append(alloc, 21); defer block.source_entry_ids.deinit(alloc); const blocks = [_]command_output_runtime.CommandOutputBlock{block}; const details = [_]ToolDetailRecord{.{ .entry_id = 10, .tool_name = @constCast("run_command"), .lifecycle_id = .{ .turn_id = 7, .call_id = lookup_call_id }, .command_output_entry_id = 20, }}; var index = try ProjectionSourceIndex.build(alloc, &details, &blocks, null); defer index.deinit(alloc); try std.testing.expect(index.detailForEntry(10) == &details[0]); try std.testing.expectEqual(@as(?usize, 0), index.commandBlockIndexForEntry(20)); try std.testing.expectEqual( @as(?usize, 0), index.commandBlockIndexForLifecycle(.{ .turn_id = 7, .call_id = lookup_call_id }), ); try std.testing.expectEqual(@as(?usize, 0), index.commandBlockIndexForDetail(&details[0])); try std.testing.expect(index.commandSourceOwned(21));} test "interruptible full projection checks inside one oversized assistant entry" { const alloc = std.testing.allocator; var entries = [_]transcript_blocks.TranscriptEntry{.{ .assistant_turn = .{ .id = 1, .segments = .{}, } }}; defer entries[0].assistant_turn.segments.deinit(alloc); try entries[0].assistant_turn.segments.text.appendNTimes(alloc, 'x', 16 * 1024); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, &checkpoint, ), ); try std.testing.expectEqual(@as(usize, 1), probe.polls); var retry = try buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, null, ); defer retry.deinit(alloc); var baseline = try buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, null, ); defer baseline.deinit(alloc); const retry_bytes = try renderProjectionViewportSource( alloc, &retry, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(retry_bytes); const baseline_bytes = try renderProjectionViewportSource( alloc, &baseline, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(baseline_bytes); try std.testing.expectEqualStrings(baseline_bytes, retry_bytes);} test "interruptible full projection measurement checks inside one static segment" { const alloc = std.testing.allocator; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); const bytes = try alloc.alloc(u8, 16 * 1024); @memset(bytes, 'x'); try projection.segments.append(alloc, .{ .static = bytes }); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, measureProjectionInterruptible(alloc, &projection, null, 80, &checkpoint), ); try std.testing.expectEqual(@as(usize, 1), probe.polls); const completed = try measureProjectionInterruptible(alloc, &projection, null, 80, null); try std.testing.expect(completed.total_rows > 0);} test "interruptible stored result measurement preserves projection state" { const alloc = std.testing.allocator; var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); try tmp.dir.createDirPath(io_mod.getIo(), "results"); const result_dir = try io_mod.dirRealpathAlloc(alloc, tmp.dir, "results"); defer alloc.free(result_dir); var capability = try session_child_store.SessionChildCapability.initLegacyRoute( alloc, result_dir, .tool_results, .writable, ); defer capability.deinit(); const content = try alloc.alloc(u8, 16 * 1024); defer alloc.free(content); @memset(content, 'x'); const handle = try result_store.storeLargeResultManaged( alloc, &capability, "interruptible-result", "read_file", content, ); defer alloc.free(handle); defer result_store.deleteManaged(&capability, handle) catch {}; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); try projection.segments.append(alloc, .{ .stored_result = .{ .handle = handle, .preview = "preview", } }); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, measureProjectionInterruptible(alloc, &projection, &capability, 80, &checkpoint), ); const stored = projection.segments.items[0].stored_result; try std.testing.expectEqual(StoredResultKind.tool_result, stored.kind); try std.testing.expectEqualStrings(handle, stored.handle); try std.testing.expect(stored.fallback_handle == null); try std.testing.expect(!stored.unavailable); var baseline = Projection{ .styles = .{} }; defer baseline.deinit(alloc); try baseline.segments.append(alloc, .{ .stored_result = .{ .handle = handle, .preview = "preview", } }); const retry_measurement = try measureProjection(alloc, &projection, &capability, 80); const baseline_measurement = try measureProjection(alloc, &baseline, &capability, 80); try std.testing.expectEqual(baseline_measurement.total_rows, retry_measurement.total_rows); const retry = try renderProjectionViewportSource( alloc, &projection, &capability, 80, @intCast(retry_measurement.total_rows), 0, ); defer alloc.free(retry); const uninterrupted = try renderProjectionViewportSource( alloc, &baseline, &capability, 80, @intCast(baseline_measurement.total_rows), 0, ); defer alloc.free(uninterrupted); try std.testing.expectEqualStrings(uninterrupted, retry);} test "interruptible full projection rendering retries after cancellation" { const alloc = std.testing.allocator; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); const bytes = try alloc.alloc(u8, 16 * 1024); @memset(bytes, 'x'); try projection.segments.append(alloc, .{ .static = bytes }); _ = try measureProjection(alloc, &projection, null, 80); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, renderProjectionViewportSourceWithSelection( alloc, &projection, null, 80, std.math.maxInt(u16), .{ .fixed_offset = 0 }, &checkpoint, ), ); const completed = try renderProjectionViewportSource( alloc, &projection, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(completed); try std.testing.expect(completed.len > 0);} pub const FullDiffResolver = struct { context: *anyopaque, full_for_marker: *const fn (context: *anyopaque, id: u32) ?[]const u8, has_full_for_lifecycle: *const fn (context: *anyopaque, lifecycle_id: types.ToolLifecycleId) bool,}; pub const ViewportOffsetSelector = struct { context: *anyopaque, select_offset: *const fn (context: *anyopaque, measurement: ProjectionMeasurement, visible_rows: u16) u32,}; const StoredResultKind = enum { tool_result, command_result, command_artifact, command_replay,}; const StoredResult = struct { kind: StoredResultKind = .tool_result, handle: []const u8, preview: ?[]const u8, framed_bytes: usize = 0, fallback_handle: ?[]const u8 = null, fallback_artifact_handle: ?[]const u8 = null, retained_command_fallback: ?[]u8 = null, retained_command_fallback_is_bounded_review: bool = false, start_record: usize = 0, end_record: ?usize = null, unavailable: bool = false, required_replay_unavailable: bool = false, detail_depth: DetailDepth = .full, line_prefix: []const u8 = " ", fn deinit(self: StoredResult, alloc: Allocator) void { if (self.retained_command_fallback) |bytes| alloc.free(bytes); }}; const CommandArtifactReader = struct { file: session_child_store.ManagedFile, size: usize, fn deinit(self: *CommandArtifactReader) void { self.file.deinit(); self.* = undefined; }}; const StoredResultReader = union(StoredResultKind) { tool_result: result_store.ResultReader, command_result: result_store.ResultReader, command_artifact: CommandArtifactReader, command_replay: command_replay_store.Reader, fn deinit(self: *StoredResultReader) void { switch (self.*) { .tool_result => |*reader| reader.deinit(), .command_result => |*reader| reader.deinit(), .command_artifact => |*reader| reader.deinit(), .command_replay => |*reader| reader.deinit(), } self.* = undefined; } fn size(self: *const StoredResultReader) usize { return switch (self.*) { .tool_result => |reader| reader.size, .command_result => |reader| reader.size, .command_artifact => |reader| reader.size, .command_replay => |reader| reader.size, }; } fn readPage( self: *StoredResultReader, alloc: Allocator, offset: usize, max_bytes: usize, ) ![]u8 { return switch (self.*) { .tool_result => |*reader| reader.readPage(alloc, offset, max_bytes), .command_result => |*reader| reader.readPage(alloc, offset, max_bytes), .command_artifact => |*reader| reader.file.readRange( alloc, @intCast(offset), @min(max_bytes, reader.size -| offset), ), .command_replay => error.InvalidReplayPageRead, }; }}; const Segment = union(enum) { static: []u8, stored_result: StoredResult,}; const ProjectionCheckpoint = struct { row: u32, col: u16, row_has_bytes: bool,}; const ProjectionWindowStart = struct { segment_index: usize, checkpoint: ProjectionCheckpoint,}; const ProjectionMeasurementPrefix = struct { cols: u16, segment_count: usize, item_count: usize, checkpoint: ProjectionCheckpoint, anchor_row: ?u32,}; /// A width-rendered Ctrl-O document. Static transcript bytes and retained/// command fallbacks are owned by the projection; stored-result handles remain/// borrowed and are read through the session capability only on demand.pub const Projection = struct { segments: std.ArrayList(Segment) = .empty, anchor_segment_index: ?usize = null, item_boundaries: std.ArrayList(ItemBoundary) = .empty, measured_item_rows: std.ArrayList(transcript_presentation.ItemRow) = .empty, measured_segment_checkpoints: std.ArrayList(ProjectionCheckpoint) = .empty, measurement_cols: ?u16 = null, measured_total_rows: u32 = 0, measured_anchor_row: ?u32 = null, measurement_prefix: ?ProjectionMeasurementPrefix = null, styles: transcript_blocks.Styles, fn invalidateMeasurement(self: *Projection) void { self.measurement_cols = null; self.measured_total_rows = 0; self.measured_anchor_row = null; self.measurement_prefix = null; } fn reusableMeasurementPrefix( self: *const Projection, first_item: usize, first_segment: usize, ) ?ProjectionMeasurementPrefix { if (self.measurement_cols) |cols| { if (self.measured_item_rows.items.len == self.item_boundaries.items.len and self.measured_segment_checkpoints.items.len == self.segments.items.len and first_segment < self.measured_segment_checkpoints.items.len) { return .{ .cols = cols, .segment_count = first_segment, .item_count = first_item, .checkpoint = self.measured_segment_checkpoints.items[first_segment], .anchor_row = if (self.anchor_segment_index) |anchor_index| if (anchor_index < first_segment) self.measured_anchor_row else null else null, }; } } if (self.measurement_prefix) |prefix| { if (first_segment >= prefix.segment_count and first_item >= prefix.item_count) { return prefix; } } return null; } fn windowStart(self: *const Projection, cols: u16, start_row: u32) ProjectionWindowStart { const origin = ProjectionCheckpoint{ .row = 0, .col = 1, .row_has_bytes = false, }; if (self.measurement_cols != cols or self.measured_segment_checkpoints.items.len != self.segments.items.len) { return .{ .segment_index = 0, .checkpoint = origin }; } var selected = ProjectionWindowStart{ .segment_index = 0, .checkpoint = origin }; for (self.measured_segment_checkpoints.items, 0..) |checkpoint, index| { if (checkpoint.row > start_row) break; const starts_inside_visible_row = checkpoint.row == start_row and (checkpoint.row_has_bytes or checkpoint.col != 1); if (starts_inside_visible_row) continue; selected = .{ .segment_index = index, .checkpoint = checkpoint }; } return selected; } pub fn deinit(self: *Projection, alloc: Allocator) void { for (self.segments.items) |segment| switch (segment) { .static => |bytes| alloc.free(bytes), .stored_result => |stored| stored.deinit(alloc), }; self.segments.deinit(alloc); self.item_boundaries.deinit(alloc); self.measured_item_rows.deinit(alloc); self.measured_segment_checkpoints.deinit(alloc); self.* = undefined; } fn boundaryIndexForEntry(self: *const Projection, entry_id: u32) ?usize { var index = self.item_boundaries.items.len; while (index > 0) { index -= 1; if (self.item_boundaries.items[index].entry_id == entry_id) return index; } return null; } fn boundaryHasContent(self: *const Projection, index: usize) bool { const start = self.item_boundaries.items[index].segment_index; const end = if (index + 1 < self.item_boundaries.items.len) self.item_boundaries.items[index + 1].segment_index else self.segments.items.len;Lines 1–500 of 8297. Load more
const std = @import("std"); const debug_trace = @import("../core/shared/debug_trace.zig"); const display_width = @import("../core/shared/display_width.zig"); const io_mod = @import("../core/shared/io.zig"); const text_utils = @import("../core/shared/text_utils.zig"); const tool_result_display = @import("../core/tooling/tool_result_display.zig"); const command_output_content = @import("../core/tooling/command_output_content.zig"); const command_replay_store = @import("../core/session/command_replay_store.zig"); const result_store = @import("../core/session/result_store.zig"); const session_child_store = @import("../core/session/session_child_store.zig"); const diff_mod = @import("../core/output/diff.zig"); const transcript_presentation = @import("../core/output/transcript_presentation.zig"); const assistant_wrap = @import("render_engine/assistant_wrap.zig"); const build_checkpoint = @import("render_engine/build_checkpoint.zig"); const transcript_blocks = @import("render_engine/transcript_blocks.zig"); const command_output_runtime = @import("transcript/command_output_runtime.zig"); const tool_group_projection = @import("transcript/tool_group_projection.zig"); const user_message_card = @import("assistant/user_message_card.zig"); const ui_render = @import("render.zig"); const types = @import("../core/shared/types.zig"); const Allocator = std.mem.Allocator; const ToolDetailRecord = transcript_blocks.ToolDetailRecord; const BuildCheckpoint = build_checkpoint.BuildCheckpoint; pub const DetailDepth = enum { review, full }; const review_detail_line_limit: usize = 3; const PendingInputProbe = struct { polls: usize = 0, fn pending(context: *anyopaque) bool { const self: *PendingInputProbe = @ptrCast(@alignCast(context)); self.polls += 1; return true; } }; test "projection source index resolves direct tool and command associations" { const alloc = std.testing.allocator; const block_call_id = try alloc.dupe(u8, "command-7"); defer alloc.free(block_call_id); const lookup_call_id = try alloc.dupe(u8, "command-7"); defer alloc.free(lookup_call_id); var block = command_output_runtime.CommandOutputBlock{ .entry_id = 20, .lifecycle_id = .{ .turn_id = 7, .call_id = block_call_id }, .retention_overflow = true, }; try block.source_entry_ids.append(alloc, 21); defer block.source_entry_ids.deinit(alloc); const blocks = [_]command_output_runtime.CommandOutputBlock{block}; const details = [_]ToolDetailRecord{.{ .entry_id = 10, .tool_name = @constCast("run_command"), .lifecycle_id = .{ .turn_id = 7, .call_id = lookup_call_id }, .command_output_entry_id = 20, }}; var index = try ProjectionSourceIndex.build(alloc, &details, &blocks, null); defer index.deinit(alloc); try std.testing.expect(index.detailForEntry(10) == &details[0]); try std.testing.expectEqual(@as(?usize, 0), index.commandBlockIndexForEntry(20)); try std.testing.expectEqual( @as(?usize, 0), index.commandBlockIndexForLifecycle(.{ .turn_id = 7, .call_id = lookup_call_id }), ); try std.testing.expectEqual(@as(?usize, 0), index.commandBlockIndexForDetail(&details[0])); try std.testing.expect(index.commandSourceOwned(21)); } test "interruptible full projection checks inside one oversized assistant entry" { const alloc = std.testing.allocator; var entries = [_]transcript_blocks.TranscriptEntry{.{ .assistant_turn = .{ .id = 1, .segments = .{}, } }}; defer entries[0].assistant_turn.segments.deinit(alloc); try entries[0].assistant_turn.segments.text.appendNTimes(alloc, 'x', 16 * 1024); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, &checkpoint, ), ); try std.testing.expectEqual(@as(usize, 1), probe.polls); var retry = try buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, null, ); defer retry.deinit(alloc); var baseline = try buildProjectionForDepthWithDiffResolverInterruptible( alloc, &entries, &.{}, &.{}, .{}, 80, null, .review, null, null, ); defer baseline.deinit(alloc); const retry_bytes = try renderProjectionViewportSource( alloc, &retry, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(retry_bytes); const baseline_bytes = try renderProjectionViewportSource( alloc, &baseline, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(baseline_bytes); try std.testing.expectEqualStrings(baseline_bytes, retry_bytes); } test "interruptible full projection measurement checks inside one static segment" { const alloc = std.testing.allocator; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); const bytes = try alloc.alloc(u8, 16 * 1024); @memset(bytes, 'x'); try projection.segments.append(alloc, .{ .static = bytes }); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, measureProjectionInterruptible(alloc, &projection, null, 80, &checkpoint), ); try std.testing.expectEqual(@as(usize, 1), probe.polls); const completed = try measureProjectionInterruptible(alloc, &projection, null, 80, null); try std.testing.expect(completed.total_rows > 0); } test "interruptible stored result measurement preserves projection state" { const alloc = std.testing.allocator; var tmp = std.testing.tmpDir(.{}); defer tmp.cleanup(); try tmp.dir.createDirPath(io_mod.getIo(), "results"); const result_dir = try io_mod.dirRealpathAlloc(alloc, tmp.dir, "results"); defer alloc.free(result_dir); var capability = try session_child_store.SessionChildCapability.initLegacyRoute( alloc, result_dir, .tool_results, .writable, ); defer capability.deinit(); const content = try alloc.alloc(u8, 16 * 1024); defer alloc.free(content); @memset(content, 'x'); const handle = try result_store.storeLargeResultManaged( alloc, &capability, "interruptible-result", "read_file", content, ); defer alloc.free(handle); defer result_store.deleteManaged(&capability, handle) catch {}; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); try projection.segments.append(alloc, .{ .stored_result = .{ .handle = handle, .preview = "preview", } }); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, measureProjectionInterruptible(alloc, &projection, &capability, 80, &checkpoint), ); const stored = projection.segments.items[0].stored_result; try std.testing.expectEqual(StoredResultKind.tool_result, stored.kind); try std.testing.expectEqualStrings(handle, stored.handle); try std.testing.expect(stored.fallback_handle == null); try std.testing.expect(!stored.unavailable); var baseline = Projection{ .styles = .{} }; defer baseline.deinit(alloc); try baseline.segments.append(alloc, .{ .stored_result = .{ .handle = handle, .preview = "preview", } }); const retry_measurement = try measureProjection(alloc, &projection, &capability, 80); const baseline_measurement = try measureProjection(alloc, &baseline, &capability, 80); try std.testing.expectEqual(baseline_measurement.total_rows, retry_measurement.total_rows); const retry = try renderProjectionViewportSource( alloc, &projection, &capability, 80, @intCast(retry_measurement.total_rows), 0, ); defer alloc.free(retry); const uninterrupted = try renderProjectionViewportSource( alloc, &baseline, &capability, 80, @intCast(baseline_measurement.total_rows), 0, ); defer alloc.free(uninterrupted); try std.testing.expectEqualStrings(uninterrupted, retry); } test "interruptible full projection rendering retries after cancellation" { const alloc = std.testing.allocator; var projection = Projection{ .styles = .{} }; defer projection.deinit(alloc); const bytes = try alloc.alloc(u8, 16 * 1024); @memset(bytes, 'x'); try projection.segments.append(alloc, .{ .static = bytes }); _ = try measureProjection(alloc, &projection, null, 80); var probe = PendingInputProbe{}; var checkpoint = BuildCheckpoint.init(&probe, PendingInputProbe.pending); try std.testing.expectError( error.InputPending, renderProjectionViewportSourceWithSelection( alloc, &projection, null, 80, std.math.maxInt(u16), .{ .fixed_offset = 0 }, &checkpoint, ), ); const completed = try renderProjectionViewportSource( alloc, &projection, null, 80, std.math.maxInt(u16), 0, ); defer alloc.free(completed); try std.testing.expect(completed.len > 0); } pub const FullDiffResolver = struct { context: *anyopaque, full_for_marker: *const fn (context: *anyopaque, id: u32) ?[]const u8, has_full_for_lifecycle: *const fn (context: *anyopaque, lifecycle_id: types.ToolLifecycleId) bool, }; pub const ViewportOffsetSelector = struct { context: *anyopaque, select_offset: *const fn (context: *anyopaque, measurement: ProjectionMeasurement, visible_rows: u16) u32, }; const StoredResultKind = enum { tool_result, command_result, command_artifact, command_replay, }; const StoredResult = struct { kind: StoredResultKind = .tool_result, handle: []const u8, preview: ?[]const u8, framed_bytes: usize = 0, fallback_handle: ?[]const u8 = null, fallback_artifact_handle: ?[]const u8 = null, retained_command_fallback: ?[]u8 = null, retained_command_fallback_is_bounded_review: bool = false, start_record: usize = 0, end_record: ?usize = null, unavailable: bool = false, required_replay_unavailable: bool = false, detail_depth: DetailDepth = .full, line_prefix: []const u8 = " ", fn deinit(self: StoredResult, alloc: Allocator) void { if (self.retained_command_fallback) |bytes| alloc.free(bytes); } }; const CommandArtifactReader = struct { file: session_child_store.ManagedFile, size: usize, fn deinit(self: *CommandArtifactReader) void { self.file.deinit(); self.* = undefined; } }; const StoredResultReader = union(StoredResultKind) { tool_result: result_store.ResultReader, command_result: result_store.ResultReader, command_artifact: CommandArtifactReader, command_replay: command_replay_store.Reader, fn deinit(self: *StoredResultReader) void { switch (self.*) { .tool_result => |*reader| reader.deinit(), .command_result => |*reader| reader.deinit(), .command_artifact => |*reader| reader.deinit(), .command_replay => |*reader| reader.deinit(), } self.* = undefined; } fn size(self: *const StoredResultReader) usize { return switch (self.*) { .tool_result => |reader| reader.size, .command_result => |reader| reader.size, .command_artifact => |reader| reader.size, .command_replay => |reader| reader.size, }; } fn readPage( self: *StoredResultReader, alloc: Allocator, offset: usize, max_bytes: usize, ) ![]u8 { return switch (self.*) { .tool_result => |*reader| reader.readPage(alloc, offset, max_bytes), .command_result => |*reader| reader.readPage(alloc, offset, max_bytes), .command_artifact => |*reader| reader.file.readRange( alloc, @intCast(offset), @min(max_bytes, reader.size -| offset), ), .command_replay => error.InvalidReplayPageRead, }; } }; const Segment = union(enum) { static: []u8, stored_result: StoredResult, }; const ProjectionCheckpoint = struct { row: u32, col: u16, row_has_bytes: bool, }; const ProjectionWindowStart = struct { segment_index: usize, checkpoint: ProjectionCheckpoint, }; const ProjectionMeasurementPrefix = struct { cols: u16, segment_count: usize, item_count: usize, checkpoint: ProjectionCheckpoint, anchor_row: ?u32, }; /// A width-rendered Ctrl-O document. Static transcript bytes and retained /// command fallbacks are owned by the projection; stored-result handles remain /// borrowed and are read through the session capability only on demand. pub const Projection = struct { segments: std.ArrayList(Segment) = .empty, anchor_segment_index: ?usize = null, item_boundaries: std.ArrayList(ItemBoundary) = .empty, measured_item_rows: std.ArrayList(transcript_presentation.ItemRow) = .empty, measured_segment_checkpoints: std.ArrayList(ProjectionCheckpoint) = .empty, measurement_cols: ?u16 = null, measured_total_rows: u32 = 0, measured_anchor_row: ?u32 = null, measurement_prefix: ?ProjectionMeasurementPrefix = null, styles: transcript_blocks.Styles, fn invalidateMeasurement(self: *Projection) void { self.measurement_cols = null; self.measured_total_rows = 0; self.measured_anchor_row = null; self.measurement_prefix = null; } fn reusableMeasurementPrefix( self: *const Projection, first_item: usize, first_segment: usize, ) ?ProjectionMeasurementPrefix { if (self.measurement_cols) |cols| { if (self.measured_item_rows.items.len == self.item_boundaries.items.len and self.measured_segment_checkpoints.items.len == self.segments.items.len and first_segment < self.measured_segment_checkpoints.items.len) { return .{ .cols = cols, .segment_count = first_segment, .item_count = first_item, .checkpoint = self.measured_segment_checkpoints.items[first_segment], .anchor_row = if (self.anchor_segment_index) |anchor_index| if (anchor_index < first_segment) self.measured_anchor_row else null else null, }; } } if (self.measurement_prefix) |prefix| { if (first_segment >= prefix.segment_count and first_item >= prefix.item_count) { return prefix; } } return null; } fn windowStart(self: *const Projection, cols: u16, start_row: u32) ProjectionWindowStart { const origin = ProjectionCheckpoint{ .row = 0, .col = 1, .row_has_bytes = false, }; if (self.measurement_cols != cols or self.measured_segment_checkpoints.items.len != self.segments.items.len) { return .{ .segment_index = 0, .checkpoint = origin }; } var selected = ProjectionWindowStart{ .segment_index = 0, .checkpoint = origin }; for (self.measured_segment_checkpoints.items, 0..) |checkpoint, index| { if (checkpoint.row > start_row) break; const starts_inside_visible_row = checkpoint.row == start_row and (checkpoint.row_has_bytes or checkpoint.col != 1); if (starts_inside_visible_row) continue; selected = .{ .segment_index = index, .checkpoint = checkpoint }; } return selected; } pub fn deinit(self: *Projection, alloc: Allocator) void { for (self.segments.items) |segment| switch (segment) { .static => |bytes| alloc.free(bytes), .stored_result => |stored| stored.deinit(alloc), }; self.segments.deinit(alloc); self.item_boundaries.deinit(alloc); self.measured_item_rows.deinit(alloc); self.measured_segment_checkpoints.deinit(alloc); self.* = undefined; } fn boundaryIndexForEntry(self: *const Projection, entry_id: u32) ?usize { var index = self.item_boundaries.items.len; while (index > 0) { index -= 1; if (self.item_boundaries.items[index].entry_id == entry_id) return index; } return null; } fn boundaryHasContent(self: *const Projection, index: usize) bool { const start = self.item_boundaries.items[index].segment_index; const end = if (index + 1 < self.item_boundaries.items.len) self.item_boundaries.items[index + 1].segment_index else self.segments.items.len;