Skip to content

feat: a Snapshots page, and a checkpoint listing that pages, searches and sorts - #2798

Draft
Charlesthebird wants to merge 1 commit into
charlesthebird/chatCheckpointsfrom
charlesthebird/snapshotsPage
Draft

feat: a Snapshots page, and a checkpoint listing that pages, searches and sorts#2798
Charlesthebird wants to merge 1 commit into
charlesthebird/chatCheckpointsfrom
charlesthebird/snapshotsPage

Conversation

@Charlesthebird

Copy link
Copy Markdown
Collaborator

🤖 written by Claude (start)

Stacked on #2775, which adds the chat side. Closes #2783.

A checkpoint pins a copy of the conversation's runtime in the substrate. They were reachable only from inside the conversation they belong to and could not be removed at all, while duplicating a chat takes one every time — so a cluster accumulated snapshots nobody had asked for and nobody could find.

The page

Lists every snapshot the reader holds, searches them, and deletes them singly or in a batch. A batch is one request each, sequential, under one toast.promise; a failure does not stop the run, each is logged, and the toast says how it went rather than claiming success over a partial one.

Deleting can refuse: the controller will not remove a snapshot while a chat forked from it still exists, and reports that as NotFound. The page states the condition rather than guessing at it per failure.

The listing

ListCheckpoints takes a filter, a sort column and an offset, and answers with the count the filter matched. agent_instance_id became optional so one request spans a caller's conversations rather than one per conversation. Reading everything into the browser and narrowing it there reports "no matches" about rows it never fetched.

Rows are named, searched and sorted by the conversation's name as recorded when the snapshot was taken — the only name a query can reach, since the current one lives inside an encoded payload. A rename leaves earlier rows reading as they did.

In the store that is one statement: count(*) OVER () carries the total, and the ordering is passed as parameters rather than concatenated in, so it stays preparable by TestInlineSQLPrepares and there is no ORDER BY to inject into.

Not here: the index the listing wants, (user_id, state, id DESC). Migration files are immutable once merged, so it needs its own; without it a listing is a sequential scan. Tracked in #2783.

Testing

  1. ENABLE_MOCK_UI=true yarn dev, open a conversation and press Checkpoint beside Send a couple of times.
  2. Go to Snapshots. Search, and the count beside the table moves with the rows.
  3. Sort by Conversation, then page forward — the order holds across the break.
  4. Pick two rows and delete them together, then delete one from its own button.

Reels against a real cluster are in the comments.


🤖 written by Claude (end)

… and sorts

Closes #2783.

A checkpoint pins a copy of the conversation's runtime in the substrate. They were
reachable only from inside the conversation they belong to and could not be removed
at all, while duplicating a chat takes one every time — so a cluster accumulated
snapshots nobody had asked for and nobody could find.

The page lists them, searches them, and deletes them singly or in a batch. A batch
is one request each, sequential, under one `toast.promise`; a failure does not stop
the run, each is logged, and the toast says how it went.

`ListCheckpoints` does the narrowing: it takes a filter, a sort column and an
offset, answers with the count the filter matched, and `agent_instance_id` became
optional so one request spans a caller's conversations. Reading everything into the
browser and filtering there reports "no matches" about rows it never fetched.

Rows are named, searched and sorted by the conversation's name as recorded when the
snapshot was taken — the only name a query can reach, since the current one lives
inside an encoded payload.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Nicholas Bucher <behappy54321@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant