fix: reload agent rehydrates timeline from disk under new epoch
Reload was a no-op for imported agents whose on-disk session was mutated externally. The server preserved the in-memory timeline + historyPrimed flag, so hydrate short-circuited and the epoch never changed. The client also fetched without a cursor on reload, so the server returned reset:false and the reducer dropped the new-epoch rows against a stale cursor — the chat stayed stale until refocus. Server: reloadAgentSession gains rehydrateFromDisk (used by the refresh RPC). When set, durable + in-memory timeline are wiped and historyPrimed is reset, so register mints a new epoch and hydrateTimelineFromProvider re-streams the freshly read provider history. Voice-mode reloads keep the existing preserve-timeline semantics. Client: handleReloadAgent shows a sticky "Reloading agent…" toast, sends the stale cursor with the fetch so the server returns reset:true, and only flips to "Reloaded agent" after the response listener has replaced the visible tail.
This commit is contained in:
@@ -2441,14 +2441,28 @@ function WorkspaceScreenContent({
|
||||
return;
|
||||
}
|
||||
|
||||
toast.show("Reloading agent…", { durationMs: null });
|
||||
try {
|
||||
await client.refreshAgent(agentId);
|
||||
// Send the existing cursor so the server detects the new epoch and
|
||||
// returns reset:true. Without a cursor, the server returns reset:false
|
||||
// and the client takes the incremental path, where new-epoch rows are
|
||||
// dropped against the stale cursor.
|
||||
const sessionState = useSessionStore.getState().sessions[normalizedServerId];
|
||||
const currentCursor = sessionState?.agentTimelineCursor.get(agentId);
|
||||
await client.fetchAgentTimeline(agentId, {
|
||||
direction: "tail",
|
||||
projection: "canonical",
|
||||
...(currentCursor
|
||||
? { cursor: { epoch: currentCursor.epoch, seq: currentCursor.endSeq } }
|
||||
: {}),
|
||||
});
|
||||
toast.show("Reloaded agent", { variant: "success" });
|
||||
} catch (error) {
|
||||
toast.error(error instanceof Error ? error.message : "Failed to reload agent");
|
||||
}
|
||||
},
|
||||
[client, isConnected, toast],
|
||||
[client, isConnected, normalizedServerId, toast],
|
||||
);
|
||||
|
||||
const handleCopyWorkspacePath = useCallback(async () => {
|
||||
|
||||
Reference in New Issue
Block a user