fix(app): preserve History agent unarchive

This commit is contained in:
Mohamed Boudra
2026-07-16 15:10:11 +02:00
parent 6152a6044e
commit 81218ba7a4
2 changed files with 36 additions and 5 deletions
@@ -64,10 +64,7 @@ function restoreArchivedWorkspace(serverId: string, agentId: string, workspaceId
const store = useSessionStore.getState();
const session = store.sessions[serverId];
// History carries restore intent explicitly. Workspace lifecycle is separate
// from agent lifecycle, so a closed non-archived agent can legitimately own an
// archived workspace. A present workspace or in-flight restore stays a no-op.
if (!session || session.workspaces.has(workspaceId)) {
if (!session) {
return;
}
if (session.restoringWorkspaces.get(workspaceId) === "restoring") {
@@ -81,6 +78,23 @@ function restoreArchivedWorkspace(serverId: string, agentId: string, workspaceId
return;
}
// Workspace and agent archive lifecycles are independent. A missing workspace
// must restore even when its agent survived unarchived; an archived agent must
// still reopen when its workspace survived.
if (session.workspaces.has(workspaceId)) {
const agent = session.agents.get(agentId) ?? session.agentDetails.get(agentId);
if (agent?.archivedAt) {
client.refreshAgent(agentId).catch((error) => {
console.error("[HistoryRestore] Failed to reopen archived agent", {
serverId,
agentId,
error,
});
});
}
return;
}
// COMPAT(worktreeRestore): added in v0.1.97, drop the gate when floor >= v0.1.97
// Single capability read for restore. An old daemon recreates nothing on
// refresh_agent, so a gone directory would spin then flash a misleading
@@ -269,12 +269,29 @@ describe("restoreArchivedWorkspace via navigateToAgent", () => {
expect(status()).toBe("needs-host-upgrade");
});
it("is a no-op when the workspace descriptor is already present", () => {
it("reopens an archived History agent when its workspace descriptor is already present", () => {
refreshAgent.mockImplementation(() => new Promise(() => {}));
useSessionStore.getState().mergeWorkspaces(SERVER_ID, [workspace()]);
openFromHistory();
expect(refreshAgent).toHaveBeenCalledTimes(1);
expect(refreshAgent).toHaveBeenCalledWith(AGENT_ID);
expect(status()).toBeNull();
});
it("is a no-op when a non-archived workspace descriptor is already present", () => {
const store = useSessionStore.getState();
store.setAgents(SERVER_ID, (prev) => {
const next = new Map(prev);
next.set(AGENT_ID, agent(null));
return next;
});
refreshAgent.mockImplementation(() => new Promise(() => {}));
store.mergeWorkspaces(SERVER_ID, [workspace()]);
openFromHistory();
expect(refreshAgent).not.toHaveBeenCalled();
});
});