-
Notifications
You must be signed in to change notification settings - Fork 437
Open
Description
Bug
regenerate() from useAgentChat fails with Anthropic models. The AI SDK correctly truncates messages client-side (removes last assistant message), but two issues in @cloudflare/ai-chat prevent it from working:
ws-chat-transport.tsdrops thetriggerfield — AI SDK passestrigger: 'regenerate-message'to the transport, but the transport never includes it in the WebSocket bodypersistMessagesonly UPSERTs, never DELETEs — when the client sends a truncated array, the old assistant message row stays in SQLite
Result: this.messages on the server still ends with the stale assistant message → Anthropic rejects with 400:
AI_APICallError: This model does not support assistant message prefill.
The conversation must end with a user message.
statusCode: 400
requestBodyValues.messages: [{ role: 'user', ... }, { role: 'assistant', ... }]
^^^^^^^^^^^^^^^^^^^^^^^^
stale — should have been deleted
Steps to reproduce
Repro repo: https://github.com/alexander-zuev/ai-chat-regenerate-bug-repro
pnpm install
npx wrangler dev- Send a message, wait for assistant response
- Click "Regenerate Last"
- Fails with the error above
The repro includes a side-by-side comparison: stock SDK (broken) vs a patched persistMessages that deletes stale rows (works).
Root cause
Transport (ws-chat-transport.ts):
// trigger is on options but never included in the body
const bodyPayload = JSON.stringify({
messages: options.messages,
...extraBody, // trigger is NOT here
});Server (persistMessages in index.ts):
// UPSERT only — old rows never deleted
this.sql`
insert into cf_ai_chat_agent_messages (id, message)
values (${safe.id}, ${json})
on conflict(id) do update set message = excluded.message
`;
// Then reloads ALL rows from SQLite, including stale ones
const persisted = this._loadMessagesFromDb();
this.messages = autoTransformMessages(persisted);Suggested fix
ws-chat-transport.ts— includetriggerin the body:
const bodyPayload = JSON.stringify({
messages: options.messages,
trigger: options.trigger,
...extraBody,
});- Server handler — when
trigger === 'regenerate-message', delete DB rows not in the incoming array:
const incomingIds = new Set(mergedMessages.map(m => m.id));
const allDbIds = this.sql`SELECT id FROM cf_ai_chat_agent_messages`.toArray();
for (const row of allDbIds) {
if (!incomingIds.has(row.id)) {
this.sql`DELETE FROM cf_ai_chat_agent_messages WHERE id = ${row.id}`;
}
}Versions
@cloudflare/ai-chat: 0.1.5agents: 0.6.0ai: 6.0.104
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels