Skip to content

feat(PromptInput): restore user message to textarea after provider errors#5629

Draft
janet-e4 wants to merge 1 commit into
Mintplex-Labs:masterfrom
janet-e4:feature/message-draft-autosave
Draft

feat(PromptInput): restore user message to textarea after provider errors#5629
janet-e4 wants to merge 1 commit into
Mintplex-Labs:masterfrom
janet-e4:feature/message-draft-autosave

Conversation

@janet-e4
Copy link
Copy Markdown

Problem

When the LLM backend returns an error response (e.g. the provider is unreachable), the user's typed message is silently lost. This happens because:

  1. clearPromptInputDraft() fires in handleSubmit before the API call
  2. setMessageEmit("") clears the textarea immediately after
  3. The stream error arrives asynchronously — by then both the textarea and the localStorage draft are already wiped

The user sees "Could not respond to message" with an empty input box and must re-type their entire message to retry.

Solution

Added savePromptInputDraft(storageKey, value) to usePromptInputStorage — a counterpart to the existing clearPromptInputDraft. In ChatContainer, the chatHandler passed to multiplexStream now tracks whether the stream ended with type: "abort". If it did, after multiplexStream resolves:

  • setMessageEmit(promptMessage.userMessage) restores the text to the textarea
  • savePromptInputDraft(storageKey, message) writes it back to localStorage

The user's message reappears in the input ready to retry — no re-typing needed.

Changes

  • frontend/src/hooks/usePromptInputStorage.js — add exported savePromptInputDraft(storageKey, value) (mirrors existing clearPromptInputDraft, 15 lines)
  • frontend/src/components/WorkspaceChat/ChatContainer/index.jsx — import savePromptInputDraft; wrap chatHandler in fetchReply to detect type: "abort"; restore message after stream resolves on error (14 lines)

No new dependencies. No changes to existing autosave/restore behavior (page-refresh drafts, debounced writes, thread/workspace scoping).

Test steps

  1. Open any workspace in chat mode
  2. Type a message
  3. Temporarily break the LLM provider (e.g. set an invalid API key or base URL in Settings)
  4. Submit the message
  5. ✅ "Could not respond to message" error appears in chat history
  6. ✅ The typed message reappears in the textarea
  7. ✅ On page refresh, the draft is also still there
  8. Restore the correct provider config
  9. Resubmit — message sends successfully
  10. ✅ Textarea clears, draft is gone, response appears

Affected providers

Provider-agnostic — triggers on any type: "abort" stream response regardless of which LLM backend is configured.

…rors

When the LLM backend returns an abort/error response (e.g. "Ollama service
could not be reached"), the user's typed message was silently lost because
clearPromptInputDraft() and setMessageEmit("") fire before the API call
completes. On error there was no recovery path.

This adds savePromptInputDraft() to usePromptInputStorage and hooks it into
the fetchReply error path in ChatContainer: when the stream returns
type:"abort", the original message is restored to the textarea and written
back to localStorage so the user can retry without re-typing.

The existing draft-autosave flow (usePromptInputStorage hook, debounced
writes, page-refresh restore) is unchanged.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
janet-e4 added a commit to janet-e4/anything-llm that referenced this pull request May 15, 2026
Comprehensive documentation pass — every fork doc verified against the
live deployment and corrected:

- README: reframed as an independent project (tracks upstream only for
  security, not features); fixed stale "localStorage drafts" claim, the
  embedding model name, and the divergence baseline.
- DEPLOYMENT: removed non-existent SIG_KEY/SIG_SALT env vars; corrected
  GENERIC_OPEN_AI_MAX_TOKENS (4096, not 8192); added the missing Qdrant
  corpus setup and the explicit 5-bind-mount table.
- SECURITY: corrected the telemetry mechanism (forced DISABLE_TELEMETRY
  env flag, not a code no-op); added the upstream security-sync policy.
- UPGRADING (both files): fixed the wrong "native is 384-dim" claim
  (it is 768-dim) and removed references to a non-existent collection
  and agent skill; split fork-repo (rebase mechanics) vs deployment runbook.
- Added docs/PROVENANCE.md: full origin + sources record — every fork
  commit traced to its reason, the NAS voice-spec source, PR Mintplex-Labs#5629, the
  Qdrant corpus origin, retained upstream components, MIT license.
- Added .upstream-sync baseline marker (anchors the security-sync scan).
- Corrected the Z-Health corpus count (41,048 = 41,041 + 7) and the
  verified-retrieval example across the docs.

The upstream-security-sync process is documented as a Claude Code skill
+ agent kept at ~/Desktop/anythingllm-fork-maintenance/ (outside the repo).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant