Skip to content
3 changes: 2 additions & 1 deletion packages/client-runtime/src/state/threadWorkflows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ describe("thread workflows", () => {
...projection,
providerThreads: [{ ...projection.providerThreads[0]!, nativeThreadRef: null }],
}),
).toBe(false);
).toBe(true);
expect(threadSupportsProviderHandoff({ ...projection, providerThreads: [] })).toBe(false);
});

it("sorts queued messages and gates promotion from capabilities", () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/client-runtime/src/state/threadWorkflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ export function threadSupportsProviderHandoff(projection: Projection | null | un
if (resolveActiveThreadRun(projection) !== null) return false;
if (projection.thread.historyOrigin === "v1_import" || projection.runs.length === 0) return true;

// Detaching a stopped session removes it from the projection, but its native
// provider thread remains available for the next turn's portable handoff.
// Detaching a stopped session removes it from the projection. The server still
// hands off from saved app history, which needs the source provider thread but
// not its native ref.
return projection.providerThreads.some(
(thread) =>
thread.id === projection.thread.activeProviderThreadId &&
thread.appThreadId === projection.thread.id &&
thread.providerInstanceId === projection.thread.modelSelection.instanceId &&
thread.nativeThreadRef !== null,
thread.providerInstanceId === projection.thread.modelSelection.instanceId,
);
}

Expand Down
Loading