diff --git a/packages/client-runtime/src/state/threadInbox.ts b/packages/client-runtime/src/state/threadInbox.ts index 43294c02a9b40..09043c7d35ade 100644 --- a/packages/client-runtime/src/state/threadInbox.ts +++ b/packages/client-runtime/src/state/threadInbox.ts @@ -123,7 +123,7 @@ export function createInboxReturnTracker() { const keyOf = (thread: ThreadKeyInput) => `${thread.environmentId}:${thread.id}`; const states = new Map< string, - { working: boolean; deadline: number | null; placement: string } + { working: boolean; deadline: number | null; placement: string | null } >(); const returns = new Map(); const listeners = new Set<() => void>(); @@ -184,17 +184,21 @@ export function createInboxReturnTracker() { for (const thread of threads) { const key = keyOf(thread); present.add(key); - const placement = JSON.stringify([ - thread.archivedAt, - thread.deletedAt, - thread.pinnedAt, - thread.settledOverride, - thread.settledAt, - thread.snoozedAt, - thread.snoozedUntil, - thread.activeOrderKey, - ]); const previous = states.get(key); + const actual = isThreadWorking(thread); + const placement = + actual || previous?.working + ? JSON.stringify([ + thread.archivedAt, + thread.deletedAt, + thread.pinnedAt, + thread.settledOverride, + thread.settledAt, + thread.snoozedAt, + thread.snoozedUntil, + thread.activeOrderKey, + ]) + : null; const actionable = thread.hasPendingApprovals || thread.hasPendingUserInput || @@ -210,7 +214,6 @@ export function createInboxReturnTracker() { thread.pinnedAt != null || thread.settledOverride === "settled" || effectiveSnoozed(thread, { now: observedAt }); - const actual = isThreadWorking(thread); // Only shelf placement is held: execution state and attention requests stay authoritative. const deadline = !actual && previous?.working && !actionable && !moved && !excluded