Something went wrong. Try again.
My version of https://github.com/vercel-labs/fx
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200const std = @import("std");const types = @import("session_store_types.zig");const sort_utils = @import("../shared/sort_utils.zig");
const Allocator = std.mem.Allocator;const SessionSummary = types.SessionSummary;const ResumableSessionContinuation = types.ResumableSessionContinuation;const ResumableSessionPage = types.ResumableSessionPage;
test "checkpoint-only summaries are resumable without changing turn counts" { const alloc = std.testing.allocator; const checkpoint = SessionSummary{ .id = @constCast("checkpoint"), .created_at_ms = 1, .updated_at_ms = 2, .conversation_language = .literal("en"), .history_len = 0, .has_checkpoint = true, }; var empty = checkpoint; empty.id = @constCast("empty"); empty.has_checkpoint = false; var page = try resumablePageFromSummaries(alloc, &.{ checkpoint, empty }, null, null, null, 10); defer page.deinit(alloc); try std.testing.expectEqual(@as(usize, 1), page.summaries.items.len); try std.testing.expectEqualStrings("checkpoint", page.summaries.items[0].id); try std.testing.expect(page.summaries.items[0].has_checkpoint); try std.testing.expectEqual(@as(usize, 0), page.summaries.items[0].history_len);}
pub fn freeSummaries( alloc: Allocator, sessions: *std.ArrayList(SessionSummary),) void { for (sessions.items) |*summary| summary.deinit(alloc); sessions.deinit(alloc);}
pub fn cloneSessionSummary( alloc: Allocator, source: SessionSummary,) !SessionSummary { const id = try alloc.dupe(u8, source.id); errdefer alloc.free(id); const workspace_root = if (source.workspace_root) |value| try alloc.dupe(u8, value) else null; errdefer if (workspace_root) |value| alloc.free(value); const origin_workspace_root = if (source.origin_workspace_root) |value| try alloc.dupe(u8, value) else null; errdefer if (origin_workspace_root) |value| alloc.free(value); const title = if (source.title) |value| try alloc.dupe(u8, value) else null; errdefer if (title) |value| alloc.free(value); const preview = if (source.preview) |value| try alloc.dupe(u8, value) else null; errdefer if (preview) |value| alloc.free(value); return .{ .id = id, .workspace_root = workspace_root, .origin_workspace_root = origin_workspace_root, .title = title, .preview = preview, .display_metadata_present = source.display_metadata_present, .created_at_ms = source.created_at_ms, .updated_at_ms = source.updated_at_ms, .conversation_language = source.conversation_language, .history_len = source.history_len, .has_checkpoint = source.has_checkpoint, .has_managed_children = source.has_managed_children, };}
pub fn resumablePageFromSummaries( alloc: Allocator, summaries: []const SessionSummary, workspace_root: ?[]const u8, active_id: ?[]const u8, continuation: ?ResumableSessionContinuation, limit: usize,) !ResumableSessionPage { const page_limit = @max(limit, 1); var page: ResumableSessionPage = .{}; errdefer page.deinit(alloc); for (summaries) |summary| { if (workspace_root) |root| { const summary_workspace = summary.workspace_root orelse continue; if (!std.mem.eql(u8, summary_workspace, root)) continue; } if (!summary.hasResumableContent()) continue; if (active_id) |id| { if (std.mem.eql(u8, summary.id, id)) continue; } if (continuation) |position| { if (!summaryFollowsContinuation(summary, position)) continue; } if (page.summaries.items.len >= page_limit) { page.has_more = true; break; } var copied = try cloneSessionSummary(alloc, summary); page.summaries.append(alloc, copied) catch |err| { copied.deinit(alloc); return err; }; } return page;}
pub fn sessionListPageFromSummaries( alloc: Allocator, summaries: []const SessionSummary, workspace_root: ?[]const u8, continuation: ?ResumableSessionContinuation, limit: usize,) !types.SessionListPage { var page: types.SessionListPage = .{}; errdefer page.deinit(alloc); for (summaries) |summary| { if (workspace_root) |root| { const summary_workspace = summary.workspace_root orelse continue; if (!std.mem.eql(u8, summary_workspace, root)) continue; } if (continuation) |position| { if (!summaryFollowsContinuation(summary, position)) continue; } if (page.summaries.items.len == limit) { page.has_more = true; break; } var copied = try cloneSessionSummary(alloc, summary); page.summaries.append(alloc, copied) catch |err| { copied.deinit(alloc); return err; }; } return page;}
fn summaryFollowsContinuation( summary: SessionSummary, continuation: ResumableSessionContinuation,) bool { if (summary.updated_at_ms != continuation.updated_at_ms) { return summary.updated_at_ms < continuation.updated_at_ms; } return std.mem.order(u8, summary.id, continuation.id) == .lt;}
pub fn sortSummariesNewestFirst(items: []SessionSummary) void { sort_utils.sort(SessionSummary, items, {}, lessSummaryNewerFirst);}
fn lessSummaryNewerFirst(_: void, a: SessionSummary, b: SessionSummary) bool { if (a.updated_at_ms != b.updated_at_ms) return a.updated_at_ms > b.updated_at_ms; return std.mem.order(u8, a.id, b.id) == .gt;}
test "summary clone owns every string" { const alloc = std.testing.allocator; var clone = try cloneSessionSummary(alloc, .{ .id = @constCast("session"), .workspace_root = @constCast("/workspace"), .origin_workspace_root = @constCast("/origin"), .title = @constCast("Title"), .preview = @constCast("Preview"), .display_metadata_present = true, .created_at_ms = 1, .updated_at_ms = 2, .conversation_language = .literal("en"), .history_len = 3, }); defer clone.deinit(alloc); try std.testing.expectEqualStrings("session", clone.id); try std.testing.expectEqualStrings("Title", clone.title.?); try std.testing.expectEqualStrings("Preview", clone.preview.?);}
test "summary pages filter and preserve append cursor order" { var summaries = [_]SessionSummary{ .{ .id = @constCast("new"), .workspace_root = @constCast("/workspace"), .created_at_ms = 1, .updated_at_ms = 3, .conversation_language = .literal("en"), .history_len = 1 }, .{ .id = @constCast("active"), .workspace_root = @constCast("/workspace"), .created_at_ms = 1, .updated_at_ms = 2, .conversation_language = .literal("en"), .history_len = 1 }, .{ .id = @constCast("old"), .workspace_root = @constCast("/workspace"), .created_at_ms = 1, .updated_at_ms = 1, .conversation_language = .literal("en"), .history_len = 1 }, }; sortSummariesNewestFirst(&summaries); var page = try resumablePageFromSummaries( std.testing.allocator, &summaries, "/workspace", "active", null, 1, ); defer page.deinit(std.testing.allocator); try std.testing.expectEqual(@as(usize, 1), page.summaries.items.len); try std.testing.expectEqualStrings("new", page.summaries.items[0].id); try std.testing.expect(page.has_more);}