studio/chat: persist Anthropic container id on first turn of new thread (#5526)

* studio/chat: persist Anthropic container id on first turn of new thread

The container_ready SSE handler updated thread record via
db.threads.update, which silently affects 0 rows when the Dexie row
hasn't been inserted yet. On the first turn of a brand-new thread the
SSE event can arrive before assistant-ui persists the row, so the new
container id was dropped, and the next turn re-read null and let
Anthropic auto-create a fresh container instead of reusing the one
from turn 1. Call ensureThreadRecord first so the row exists before
the update lands.

* studio/chat: temp diag log for container persistence races

* studio/chat: drop temp diag logging

* studio/chat: retry container persist instead of forcing thread row

Drop ensureThreadRecord + circular runtime-provider import. Retry the
update for up to 500ms so assistant-ui's DexieAdapter.initialize wins
the race and creates the thread row with the right modelType (base /
lora / model1 / model2), then our update lands on a subsequent
attempt. Addresses gemini-code-assist review on #5526.
This commit is contained in:
Roland Tannous 2026-05-18 00:42:30 +04:00 committed by GitHub
commit 20e66adae3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1280,11 +1280,29 @@ export function createOpenAIStreamAdapter(): ChatModelAdapter {
externalProvider?.providerType === "anthropic"
? "anthropicCodeExecContainerId"
: "openaiCodeExecContainerId";
void db.threads
.update(resolvedThreadId, {
[field]: newContainerId,
})
.catch(() => {});
// On the first turn of a brand-new thread the row
// may not be in Dexie yet when this SSE event
// fires — db.threads.update silently affects 0
// rows, the next turn re-reads null, and Anthropic
// auto-creates a fresh container. Retry briefly so
// assistant-ui's own DexieAdapter.initialize lands
// the row first (with the correct modelType for
// base / lora / compare contexts) and our update
// sticks on a subsequent attempt.
try {
for (let attempt = 0; attempt < 10; attempt++) {
const affected = await db.threads.update(
resolvedThreadId,
{ [field]: newContainerId },
);
if (affected > 0) break;
await new Promise((resolve) =>
setTimeout(resolve, 50),
);
}
} catch {
/* best-effort: container reuse is an optimization */
}
}
continue;
}