-
-
Notifications
You must be signed in to change notification settings - Fork 461
fix(web): preserve failed inactive send prompts #657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,7 +31,7 @@ type UseSendMessageOptions = { | |
|
|
||
| /** Create an optimistic message for display. Extracted as an extension point | ||
| * so a future floating-UI PR can route queued messages to a separate area. */ | ||
| function createOptimisticMessage(input: SendMessageInput, status: 'queued' | 'sending'): DecryptedMessage { | ||
| function createOptimisticMessage(input: SendMessageInput, status: 'queued' | 'sending' | 'failed'): DecryptedMessage { | ||
| return { | ||
| id: input.localId, | ||
| seq: null, | ||
|
|
@@ -145,6 +145,21 @@ export function useSendMessage( | |
| targetSessionId = resolved | ||
| } | ||
| } catch (error) { | ||
| // The composer has already cleared its text by the time async | ||
| // inactive-session resume fails. Surface a failed local prompt | ||
| // bubble so 500/502 resume errors cannot make the user's prompt | ||
| // disappear with no way to copy or retry it. | ||
| appendOptimisticMessage( | ||
| sessionId, | ||
| createOptimisticMessage({ | ||
| sessionId, | ||
| text, | ||
| localId, | ||
| createdAt, | ||
| attachments, | ||
| scheduledAt, | ||
| }, 'failed') | ||
| ) | ||
| haptic.notification('error') | ||
| console.error('Failed to resolve session before send:', error) | ||
| return false | ||
|
|
@@ -182,16 +197,40 @@ export function useSendMessage( | |
|
|
||
| const message = findMessageByLocalId(sessionId, localId) | ||
| if (!message?.originalText) return false | ||
| const originalText = message.originalText | ||
|
|
||
| updateMessageStatus(sessionId, localId, 'sending') | ||
|
|
||
| mutation.mutate({ | ||
| sessionId, | ||
| text: message.originalText, | ||
| localId, | ||
| createdAt: message.createdAt, | ||
| scheduledAt: message.scheduledAt ?? null, | ||
| }) | ||
| void (async () => { | ||
| let targetSessionId = sessionId | ||
| if (options?.resolveSessionId) { | ||
| resolveGuardRef.current = true | ||
| setIsResolving(true) | ||
| try { | ||
| const resolved = await options.resolveSessionId(sessionId) | ||
| if (resolved && resolved !== sessionId) { | ||
| options.onSessionResolved?.(resolved) | ||
| targetSessionId = resolved | ||
| } | ||
| } catch (error) { | ||
| updateMessageStatus(sessionId, localId, 'failed') | ||
| haptic.notification('error') | ||
| console.error('Failed to resolve session before retry:', error) | ||
| return | ||
| } finally { | ||
| resolveGuardRef.current = false | ||
| setIsResolving(false) | ||
| } | ||
| } | ||
|
|
||
| mutation.mutate({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [MAJOR] Retrying a prompt preserved by the new resolve-failure path still drops its attachments. 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,
}) |
||
| sessionId: targetSessionId, | ||
| text: originalText, | ||
| localId, | ||
| createdAt: message.createdAt, | ||
| scheduledAt: message.scheduledAt ?? null, | ||
| }) | ||
| })() | ||
| return true | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[MAJOR] Retrying a prompt preserved by the new resolve-failure path drops its attachments.
createOptimisticMessagenow storesattachmentsin the failed bubble, but this retry mutation does not pass them back toapi.sendMessage, so image/file prompts get retried as text-only; attachment-only prompts are still rejected by theoriginalTextguard.Suggested fix: