fix(native-chat): preserve confirmed send queue ordering

This commit is contained in:
Brennan Benson
2026-07-29 16:36:36 -07:00
parent b5982baabb
commit 81404913d7
2 changed files with 53 additions and 18 deletions
@@ -13,6 +13,7 @@ vi.mock('@/runtime/runtime-terminal-inspection', () => ({
import {
NATIVE_CHAT_CLEAR_CONFIRM_MS,
NATIVE_CHAT_CLEAR_UNSUBMITTED_INPUT,
NATIVE_CHAT_IMAGE_ATTACHMENT_SETTLE_MS,
NATIVE_CHAT_SUBMIT_DELAY_MS,
resetNativeChatPtySendQueuesForTests,
sendNativeChatMessage,
@@ -103,6 +104,25 @@ describe('sendNativeChatMessage with a parked multi-line draft', () => {
NATIVE_CHAT_SUBMIT_DELAY_MS + NATIVE_CHAT_CLEAR_CONFIRM_MS
)
})
it('submits before a queued send starts after clear confirmation', async () => {
const clearInput = buildAgentTuiClearInputForText(DRAFT)
sendNativeChatMessage(SETTINGS, PTY, 'first', {
clearInput,
confirmCleared: () => true
})
sendNativeChatMessage(SETTINGS, PTY, 'second')
await vi.advanceTimersByTimeAsync(NATIVE_CHAT_CLEAR_CONFIRM_MS + NATIVE_CHAT_SUBMIT_DELAY_MS)
expect(writes()).toEqual([
clearInput,
buildNativeChatPasteBytes('first'),
NATIVE_CHAT_SUBMIT,
NATIVE_CHAT_CLEAR_UNSUBMITTED_INPUT,
buildNativeChatPasteBytes('second')
])
})
})
describe('image sends with a parked multi-line draft', () => {
@@ -122,4 +142,23 @@ describe('image sends with a parked multi-line draft', () => {
vi.advanceTimersByTime(10_000)
expect(writes().filter((write) => write === clearInput)).toHaveLength(1)
})
it('submits the image send before a queued message starts', async () => {
const clearInput = buildAgentTuiClearInputForText(DRAFT)
sendNativeChatMessageWithImageAttachments(SETTINGS, PTY, 'caption', ['/tmp/a.png'], {
clearInput,
confirmCleared: () => true
})
sendNativeChatMessage(SETTINGS, PTY, 'second')
await vi.advanceTimersByTimeAsync(
NATIVE_CHAT_CLEAR_CONFIRM_MS +
NATIVE_CHAT_IMAGE_ATTACHMENT_SETTLE_MS +
NATIVE_CHAT_SUBMIT_DELAY_MS
)
expect(writes().indexOf(NATIVE_CHAT_SUBMIT)).toBeLessThan(
writes().indexOf(NATIVE_CHAT_CLEAR_UNSUBMITTED_INPUT)
)
})
})
@@ -130,15 +130,15 @@ export function sendNativeChatMessage(
if (isCancelled()) {
return
}
delay(NATIVE_CHAT_SUBMIT_DELAY_MS + clearConfirmDurationMs(options), () => {
sendRuntimePtyInput(settings, ptyId, NATIVE_CHAT_SUBMIT)
markSubmitted()
})
clearThenWrite(settings, ptyId, options, delay, () => {
if (isCancelled()) {
return
}
sendRuntimePtyInput(settings, ptyId, buildNativeChatPasteBytes(text))
delay(NATIVE_CHAT_SUBMIT_DELAY_MS, () => {
sendRuntimePtyInput(settings, ptyId, NATIVE_CHAT_SUBMIT)
markSubmitted()
})
})
},
{
@@ -225,6 +225,16 @@ export function sendNativeChatMessageWithImageAttachments(
if (isCancelled()) {
return
}
const clearConfirmMs = clearConfirmDurationMs(options)
if (trimmedText.length > 0) {
delay(clearConfirmMs + NATIVE_CHAT_IMAGE_ATTACHMENT_SETTLE_MS, () => {
sendRuntimePtyInput(settings, ptyId, buildNativeChatPasteBytes(text))
})
}
delay(durationMs, () => {
sendRuntimePtyInput(settings, ptyId, NATIVE_CHAT_SUBMIT)
markSubmitted()
})
clearThenWrite(settings, ptyId, options, delay, () => {
if (isCancelled()) {
return
@@ -232,20 +242,6 @@ export function sendNativeChatMessageWithImageAttachments(
for (const imagePath of imagePaths) {
sendRuntimePtyInput(settings, ptyId, buildNativeChatImagePasteBytes(imagePath))
}
if (trimmedText.length > 0) {
delay(NATIVE_CHAT_IMAGE_ATTACHMENT_SETTLE_MS, () => {
sendRuntimePtyInput(settings, ptyId, buildNativeChatPasteBytes(text))
})
delay(NATIVE_CHAT_IMAGE_ATTACHMENT_SETTLE_MS + NATIVE_CHAT_SUBMIT_DELAY_MS, () => {
sendRuntimePtyInput(settings, ptyId, NATIVE_CHAT_SUBMIT)
markSubmitted()
})
return
}
delay(NATIVE_CHAT_SUBMIT_DELAY_MS, () => {
sendRuntimePtyInput(settings, ptyId, NATIVE_CHAT_SUBMIT)
markSubmitted()
})
})
},
{