fix(app): preserve sync state across retries

This commit is contained in:
Mohamed Boudra
2026-07-17 11:12:46 +02:00
parent 7c13224386
commit 46a6bced96
5 changed files with 33 additions and 18 deletions
@@ -412,7 +412,11 @@ function finalizeTimelineApplication(input: {
}
if (result.clearInitializing) {
markAgentHistorySynchronized(serverId, agentId);
getHostRuntimeStore().drainQueuedAgentMessage(serverId, agentId);
const session = useSessionStore.getState().sessions[serverId];
const agent = session?.agents.get(agentId) ?? session?.agentDetails.get(agentId);
if (agent && agent.status !== "running") {
getHostRuntimeStore().drainQueuedAgentMessage(serverId, agentId);
}
}
}
+5 -1
View File
@@ -908,7 +908,11 @@ function ChatAgentContent({
return;
}
if (agentState.id && hasAppliedAuthoritativeHistory) {
if (missingAgentState.kind === "resolving" || missingAgentState.kind === "not_found") {
if (
missingAgentState.kind === "resolving" ||
missingAgentState.kind === "not_found" ||
missingAgentState.kind === "error"
) {
setMissingAgentState(reconcileMissingAgentStateWithPresentAgent);
}
return;
@@ -2023,7 +2023,7 @@ function WorkspaceScreenContent({
layout: workspaceLayout,
tabs: uiTabs,
routeFocused: isRouteFocused,
focusedPaneOnly: isMobile || isFocusModeEnabled,
focusedPaneOnly: isMobile || isFocusModeEnabled || !supportsDesktopPaneSplits(),
}),
[isFocusModeEnabled, isMobile, isRouteFocused, uiTabs, workspaceLayout],
);
@@ -113,6 +113,11 @@ describe("agent directory reconciliation", () => {
});
it("keeps newer page metadata when a stale buffered upsert arrives", () => {
const snapshotEntry = entry("agent", "running");
const staleProject = {
...snapshotEntry.project,
projectName: "stale project",
};
const result = reconcileAgentDirectory({
previous: new Map([["agent", replica("agent", "running")]]),
snapshot: [
@@ -133,7 +138,7 @@ describe("agent directory reconciliation", () => {
title: "stale live",
updatedAt: "2026-07-12T11:00:00.000Z",
},
project: entry("agent", "idle").project,
project: staleProject,
},
],
});
@@ -141,8 +146,9 @@ describe("agent directory reconciliation", () => {
expect({
title: result.entries[0]?.agent.title,
status: result.entries[0]?.agent.status,
projectName: result.entries[0]?.project.projectName,
stopped: result.stoppedRunningAgentIds,
}).toEqual({ title: "newer page", status: "running", stopped: [] });
}).toEqual({ title: "newer page", status: "running", projectName: "repo", stopped: [] });
});
it("accepts usage from a stale buffered upsert without regressing metadata", () => {
@@ -33,22 +33,23 @@ export function reconcileAgentDirectory(input: {
}
statuses.set(delta.agent.id, acceptedAgent.status);
const previousProject = previousEntry?.project;
const acceptedProject =
acceptedAgent === delta.agent ? (delta.project ?? previousProject) : previousProject;
entries.set(delta.agent.id, {
agent: acceptedAgent,
project: delta.project ??
previousProject ?? {
projectKey: delta.agent.cwd,
projectName: /[^/]+$/.exec(delta.agent.cwd)?.[0] ?? delta.agent.cwd,
checkout: {
cwd: delta.agent.cwd,
isGit: false,
currentBranch: null,
remoteUrl: null,
worktreeRoot: null,
isPaseoOwnedWorktree: false,
mainRepoRoot: null,
},
project: acceptedProject ?? {
projectKey: delta.agent.cwd,
projectName: /[^/]+$/.exec(delta.agent.cwd)?.[0] ?? delta.agent.cwd,
checkout: {
cwd: delta.agent.cwd,
isGit: false,
currentBranch: null,
remoteUrl: null,
worktreeRoot: null,
isPaseoOwnedWorktree: false,
mainRepoRoot: null,
},
},
});
}