Keep focused agent timelines live and catch up instantly (#2196)

* fix(app): keep focused agent timelines live

Window focus was conflated with app visibility, so switching OS windows could remove the selected timeline subscription. Separate those signals, grace every visibility-driven removal, and cover retained history until authoritative catch-up completes.

* fix(app): keep timeline catch-up failures non-blocking

* fix(app): surface timeline catch-up failures

* fix(app): preserve file preview refocus

* fix(app): preserve optimistic catch-up flow
This commit is contained in:
Mohamed Boudra
2026-07-18 16:30:59 +02:00
committed by GitHub
parent fcaa84f0e4
commit 7917532716
26 changed files with 527 additions and 64 deletions
@@ -46,6 +46,7 @@ export interface AgentScreenMachineInput {
isArchivingCurrentAgent: boolean;
isHistorySyncing: boolean;
needsAuthoritativeSync: boolean;
visibilityCatchUpStatus: "ready" | "pending" | "error";
continuity: AgentScreenContinuity;
hasHydratedHistoryBefore: boolean;
}
@@ -147,10 +148,12 @@ function resolveAgentScreenSource(args: {
function resolveCatchingUpUi(args: {
hasOptimisticCreateContinuity: boolean;
isVisibilityCatchUpPending: boolean;
hasHydratedHistoryBefore: boolean;
hadInitialSyncFailure: boolean;
}): "overlay" | "silent" {
if (args.hasOptimisticCreateContinuity) return "silent";
if (args.isVisibilityCatchUpPending) return "overlay";
if (args.hasHydratedHistoryBefore) return "silent";
if (args.hadInitialSyncFailure) return "silent";
return "overlay";
@@ -167,11 +170,19 @@ function resolveAgentScreenSync(args: {
if (input.missingAgentState.kind === "error") {
return { status: "sync_error" };
}
if (input.needsAuthoritativeSync || input.isHistorySyncing) {
if (input.visibilityCatchUpStatus === "error") {
return { status: "sync_error" };
}
if (
input.visibilityCatchUpStatus === "pending" ||
input.needsAuthoritativeSync ||
input.isHistorySyncing
) {
return {
status: "catching_up",
ui: resolveCatchingUpUi({
hasOptimisticCreateContinuity: hasOptimisticCreateContinuity(input),
isVisibilityCatchUpPending: input.visibilityCatchUpStatus === "pending",
hasHydratedHistoryBefore: input.hasHydratedHistoryBefore,
hadInitialSyncFailure,
}),