Files
Agent-System-Frontend/src/outbox.ts
T
weichenandCursor 763c4b4804 Send the same request id when an outbox message is retried
Why: A busy 409 used to enqueue a new id, so the retry created a second user message after the server had already stored the first.
Evidence: vitest run passed, 13 files and 69 tests, including the outbox retry case.
Impact: Data layer only. sendMessage and outbox flush reuse the queued message id as requestId. No screen changes.
Refs: Dev feature/pi-durable-borrow
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 14:37:50 +00:00

45 lines
1.5 KiB
TypeScript

// 输入排队(纯数据):回合进行中先入本地队列,终态再逐条发送。
export interface QueuedMessage {
id: string
text: string
attachmentIds: string[]
attachmentNames: string[]
}
export function newQueuedMessage(text: string, attachmentIds: string[], attachmentNames: string[]): QueuedMessage {
return {
id: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
text,
attachmentIds,
attachmentNames,
}
}
export function enqueueMessage(queue: QueuedMessage[], item: QueuedMessage): QueuedMessage[] {
return [...queue, item]
}
export function enqueueMessageFront(queue: QueuedMessage[], item: QueuedMessage): QueuedMessage[] {
return [item, ...queue.filter(q => q.id !== item.id)]
}
export function removeQueuedMessage(queue: QueuedMessage[], id: string): QueuedMessage[] {
return queue.filter(q => q.id !== id)
}
export function replaceQueuedText(queue: QueuedMessage[], id: string, text: string): QueuedMessage[] {
return queue.map(q => q.id === id ? { ...q, text } : q)
}
// deliveryRequestId 是这条排队消息重发时必须复用的 requestId。
// 服务端按它去重,避免忙时 409 再入队后写出第二条用户消息。
export function deliveryRequestId(item: QueuedMessage): string {
return item.id
}
export function promoteQueuedMessage(queue: QueuedMessage[], id: string): QueuedMessage[] {
const item = queue.find(q => q.id === id)
if (!item) return queue
return enqueueMessageFront(queue, item)
}