fix(web): preserve failed inactive send prompts#657
Conversation
There was a problem hiding this comment.
Findings
- [Major] Retried preserved prompts drop attachments — resolve failure now creates a failed bubble with
attachments, but the new retry path callsmutation.mutatewithout carrying those attachments forward.api.sendMessagetherefore receivesundefinedfor attachments, so a preserved image/file prompt retries as text-only; attachment-only preserved prompts also remain non-retryable because the retry guard rejects emptyoriginalText. Evidenceweb/src/hooks/mutations/useSendMessage.ts:226.
Suggested fix:const message = findMessageByLocalId(sessionId, localId) if (!message) return false const content = message.content const userContent = content && typeof content === 'object' && 'role' in content && (content as { role?: unknown }).role === 'user' && 'content' in content ? (content as { content?: unknown }).content : undefined const attachments = userContent && typeof userContent === 'object' && 'attachments' in userContent ? (userContent as { attachments?: AttachmentMetadata[] }).attachments : undefined const originalText = message.originalText ?? '' if (!originalText && !attachments?.length) return false mutation.mutate({ sessionId: targetSessionId, text: originalText, localId, createdAt: message.createdAt, attachments, scheduledAt: message.scheduledAt ?? null, })
Questions
- None.
Summary
- Review mode: initial
- One regression found in the new preserved-prompt retry path. Add coverage for text+attachment and attachment-only preserved resolve failures so retry behavior matches the bubble the user sees.
Testing
- Not run (automation):
bun --cwd web test src/hooks/mutations/useSendMessage.test.tsxfailed here becausebunis not on PATH (/bin/bash: bun: command not found).
HAPI Bot
| } | ||
| } | ||
|
|
||
| mutation.mutate({ |
There was a problem hiding this comment.
[MAJOR] Retrying a prompt preserved by the new resolve-failure path drops its attachments. createOptimisticMessage now stores attachments in the failed bubble, but this retry mutation does not pass them back to api.sendMessage, so image/file prompts get retried as text-only; attachment-only prompts are still rejected by the originalText guard.
Suggested fix:
const message = findMessageByLocalId(sessionId, localId)
if (!message) return false
const content = message.content
const userContent = content
&& typeof content === 'object'
&& 'role' in content
&& (content as { role?: unknown }).role === 'user'
&& 'content' in content
? (content as { content?: unknown }).content
: undefined
const attachments = userContent
&& typeof userContent === 'object'
&& 'attachments' in userContent
? (userContent as { attachments?: AttachmentMetadata[] }).attachments
: undefined
const originalText = message.originalText ?? ''
if (!originalText && !attachments?.length) return false
mutation.mutate({
sessionId: targetSessionId,
text: originalText,
localId,
createdAt: message.createdAt,
attachments,
scheduledAt: message.scheduledAt ?? null,
})10177bd to
b424e82
Compare
There was a problem hiding this comment.
Findings
- [Major] Retried preserved prompts still drop attachments — this PR now stores
attachmentsin the failed optimistic bubble when inactive-session resolution fails, but the retry mutation only sendsoriginalText. A text+file prompt retries as text-only, and an attachment-only prompt is still blocked by theoriginalTextguard, even though the user sees the attachment preserved in the failed bubble. Evidenceweb/src/hooks/mutations/useSendMessage.ts:226.
Suggested fix:const message = findMessageByLocalId(sessionId, localId) if (!message) return false const userContent = message.content?.role === 'user' ? message.content.content : undefined const attachments = userContent?.type === 'text' ? userContent.attachments : undefined const originalText = message.originalText ?? '' if (!originalText && !attachments?.length) return false mutation.mutate({ sessionId: targetSessionId, text: originalText, localId, createdAt: message.createdAt, attachments, scheduledAt: message.scheduledAt ?? null, })
Questions
- None.
Summary
- Review mode: follow-up after new commits
- The prior attachment retry issue is still present in the latest diff. The new tests cover text-only preserved retries and scheduled retry metadata, but not text+attachment or attachment-only preserved prompts.
Testing
- Not run (automation/security): review only; did not execute PR code.
HAPI Bot
| } | ||
| } | ||
|
|
||
| mutation.mutate({ |
There was a problem hiding this comment.
[MAJOR] Retrying a prompt preserved by the new resolve-failure path still drops its attachments. createOptimisticMessage stores attachments in the failed bubble, but this retry mutation does not pass them back to api.sendMessage; text+file prompts retry as text-only, and attachment-only prompts are rejected by the originalText guard.
Suggested fix:
const message = findMessageByLocalId(sessionId, localId)
if (!message) return false
const userContent = message.content?.role === 'user'
? message.content.content
: undefined
const attachments = userContent?.type === 'text'
? userContent.attachments
: undefined
const originalText = message.originalText ?? ''
if (!originalText && !attachments?.length) return false
mutation.mutate({
sessionId: targetSessionId,
text: originalText,
localId,
createdAt: message.createdAt,
attachments,
scheduledAt: message.scheduledAt ?? null,
})
Summary
Preserve the user’s prompt when sending to an inactive/invalid session fails during session resolution/resume.
Previously, if
resolveSessionIdfailed before the send mutation started, the composer had already cleared the input, so a 500/502 resume/send failure could make the user’s prompt disappear with no visible recovery path.Changes
resolveSessionIdfailure before send, append a failed optimistic user bubble containing the original prompt.scheduledAtand attachments in the failed bubble metadata/content.resolveSessionIdbefore sending.scheduledAt.Notes
Known pre-existing limitation: retrying a failed bubble does not currently re-send attachments. This PR preserves attachments visually in the failed bubble but does not change the broader retry attachment behavior.
Validation
git diff --check origin/main..HEADbun typecheckbun --cwd web test src/hooks/mutations/useSendMessage.test.tsxenv -u HAPI_CLI_EXECUTABLE bun run testFull suite passed.