docs(ai-chat): atomic onTurnComplete writes + Anthropic prose (#3693)
## Summary Three post-merge fixes for the AI Agents docs (#3226), all caught by review after merge. ## Fixes - **`onTurnComplete` examples now use `db.$transaction`** — both the Database persistence "Complete example" and the Lifecycle hooks reference example were doing two separate `await` calls (`db.chat.update` then `db.chatSession.upsert`). That's the exact non-atomic pattern the warning earlier on the persistence page calls out as ❌: a refresh between the two writes reads a stale `lastEventId` and duplicates the assistant message on resume. Both examples now use the recommended atomic form. - **Background injection self-review prose aligned with the code** — the prose said "gpt-4o-mini" but the example above it had been swapped to `claude-haiku-4-5`. The Anthropic-sweep script only touched code blocks; this prose line wasn't picked up. ## Test plan - [x] Both updated examples use `db.$transaction([...])` - [x] Prose matches the model used in the code block - [ ] Mintlify deployment passes
This commit is contained in:
@@ -154,7 +154,7 @@ export const myChat = chat.agent({
|
||||
});
|
||||
```
|
||||
|
||||
The self-review runs on `gpt-4o-mini` (fast, cheap) in the background. If the user sends another message before it completes, the coaching is still injected — `chat.inject()` persists across the idle wait.
|
||||
The self-review runs on `claude-haiku-4-5` (fast, cheap) in the background. If the user sends another message before it completes, the coaching is still injected — `chat.inject()` persists across the idle wait.
|
||||
|
||||
## Other use cases
|
||||
|
||||
|
||||
@@ -412,15 +412,18 @@ Fires after each turn completes, after the response is captured and the stream i
|
||||
export const myChat = chat.agent({
|
||||
id: "my-chat",
|
||||
onTurnComplete: async ({ chatId, uiMessages, runId, chatAccessToken, lastEventId }) => {
|
||||
await db.chat.update({
|
||||
where: { id: chatId },
|
||||
data: { messages: uiMessages },
|
||||
});
|
||||
await db.chatSession.upsert({
|
||||
where: { id: chatId },
|
||||
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
});
|
||||
// Atomic write — see Database persistence for the race-condition rationale
|
||||
await db.$transaction([
|
||||
db.chat.update({
|
||||
where: { id: chatId },
|
||||
data: { messages: uiMessages },
|
||||
}),
|
||||
db.chatSession.upsert({
|
||||
where: { id: chatId },
|
||||
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
}),
|
||||
]);
|
||||
},
|
||||
run: async ({ messages, signal }) => {
|
||||
return streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal });
|
||||
|
||||
@@ -258,16 +258,19 @@ export const myChat = chat.agent({
|
||||
});
|
||||
},
|
||||
onTurnComplete: async ({ chatId, uiMessages, runId, chatAccessToken, lastEventId }) => {
|
||||
// Persist assistant response + stream position
|
||||
await db.chat.update({
|
||||
where: { id: chatId },
|
||||
data: { messages: uiMessages },
|
||||
});
|
||||
await db.chatSession.upsert({
|
||||
where: { id: chatId },
|
||||
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
});
|
||||
// Persist assistant response + stream position atomically — see the
|
||||
// race-condition warning earlier on this page.
|
||||
await db.$transaction([
|
||||
db.chat.update({
|
||||
where: { id: chatId },
|
||||
data: { messages: uiMessages },
|
||||
}),
|
||||
db.chatSession.upsert({
|
||||
where: { id: chatId },
|
||||
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
|
||||
}),
|
||||
]);
|
||||
},
|
||||
run: async ({ messages, signal }) => {
|
||||
return streamText({
|
||||
|
||||
Reference in New Issue
Block a user