| … | … | @@ -903,6 +903,15 @@ export const ThreadDetailScreen = function ThreadDetailScreen(props: ThreadDetai | |
| 903 | 903 | const hasUserMessage = selectedThreadFeed.some( | |
| 904 | 904 | (entry) => entry.type === "message" && entry.message.role === "user", | |
| 905 | 905 | ); | |
| 906 | + | if (props.activePendingApproval !== null && props.activePendingUserInput === null) { | |
🟠 High threads/ThreadDetailScreen.tsx:906
Saving a queued-message edit declines the pending approval even though the edit sends no redirect, so the agent’s active command is rejected just to update a queued message. onSendMessage handles the edit and returns null only after this block runs; skip the decline when props.queuedRunEdit is non-null.
Also found in 1 other location(s)
apps/web/src/components/chat/ChatComposer.tsx:3985
Do not decline approvals when submitting a queued-message edit. If an approval is pending while the user edits an existing queued message, this block declines it before invoking
onSend, butChatView.tsx'sonSendhandlesqueuedRunEdit.isEditingby callingsaveEditand returning without dispatching a redirect. Saving an edit therefore unexpectedly rejects the agent's current command even though no replacement message is sent. Exclude queued-message edits from this decline path.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/mobile/src/features/threads/ThreadDetailScreen.tsx around line 906: |
| 2 | |
| 3 | Saving a queued-message edit declines the pending approval even though the edit sends no redirect, so the agent’s active command is rejected just to update a queued message. `onSendMessage` handles the edit and returns `null` only after this block runs; skip the decline when `props.queuedRunEdit` is non-null. |
| 4 | |
| 5 | Also found in 1 other location(s): |
| 6 | - apps/web/src/components/chat/ChatComposer.tsx:3985 -- Do not decline approvals when submitting a queued-message edit. If an approval is pending while the user edits an existing queued message, this block declines it before invoking `onSend`, but `ChatView.tsx`'s `onSend` handles `queuedRunEdit.isEditing` by calling `saveEdit` and returning without dispatching a redirect. Saving an edit therefore unexpectedly rejects the agent's current command even though no replacement message is sent. Exclude queued-message edits from this decline path. |
Note
Written by claude-opus-5-5 on behalf of Maria
Fixed in fb6bd388c3. Saving a queued-message edit no longer declines the approval: web skips the decline while isEditingQueuedMessage, and mobile skips it while queuedRunEdit is set.
| … | … | @@ -3981,6 +3982,31 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | |
| 4002 | + | !(await declinePendingApproval(activePendingApproval, onRespondToApproval)) || | |
| 4003 | + | composerDraftTargetKey !== composerDraftTargetKeyRef.current | |
| 4004 | + | ) | |
| 4005 | + | return; | |
🟠 High chat/ChatComposer.tsx:4005
A pasted attachment can be omitted from the approval follow-up send and then appear in the next message: pendingDraftWork is checked before declinePendingApproval is awaited, but not after it, so an import started during a slow decline is not included in the send snapshot. Recheck pendingDraftWork after the await and abort the send if work is still pending.
No longer relevant as of fb6bd388c3357b120591156f22fba919b4b82c32
Note
Written by claude-opus-5-5 on behalf of Maria
Fixed in fb6bd388c3. After the decline resolves, the send re-checks image compressions and pendingDraftWork against attachmentTargetKeyRef.current, and stops with the same toast if anything is still pending. The draft stays, so the next send goes through normally.