Skip to content

fix(local): offer a new chat when an agent thread's model cannot run it - #2175

Merged
MODSetter merged 5 commits into
MODSetter:devfrom
Cedric921:fix/agent-refusal-offers-new-chat
Oct 6, 2026
Merged

MODSetter merged 5 commits into
MODSetter:devfrom
Cedric921:fix/agent-refusal-offers-new-chat

Conversation

@Cedric921

@Cedric921 Cedric921 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

What

When the selected model cannot run the agent, a turn sent to an agent thread used to show a generic error with Retry. It now says the thread can't continue with that model and offers Start a new chat, as the agent proposal has it.

This is built on the new-chat action dev added for legacy threads in cf80ccf, and follows its pattern:

  • features/agent/unsupported-model.ts: isUnsupportedModelRefusal recognises the backend's 409 sentence, mirroring outdated-thread.ts.
  • use-chat-runtime: turns that refusal into a turn error of the frontend-only kind agent_model_unsupported, beside agent_thread_outdated.
  • ChatErrorNotice: gives that kind the existing new-chat action, so the reply shows "Start a new chat" and no Retry.
  • Strings: one new string, chat_error_agent_model_unsupported, in all ten languages. It follows the glossary and the existing context-too-long wording for chat.

There are no backend changes. The refusal's text is unchanged, and unsupported-model.ts names the backend line it mirrors.

Why

docs/architecture/agent.md listed it under Known gaps: "A turn refused because the selected model cannot run the agent shows as an error with Retry; the composer does not offer a new thread". A thread keeps its engine, so Retry meets the same refusal, and only a new thread takes that model.

Fixes

No issue. This closes that Known gaps line, which is deleted here. agent.md (Which threads get it) and chat.md (agent threads, Sending) describe what the screen shows.

How to test

cd surfsense_local/frontend
pnpm test src/features/agent src/features/chat src/features/dashboard
pnpm lint && pnpm exec tsc --noEmit
pnpm translations:verify && (cd ../.. && node scripts/check_translations.mjs)
cd ../.. && python scripts/check_docs.py

New test unsupported-model-thread.test.tsx, mirroring outdated-agent-thread.test.tsx: the refused turn shows the notice with no Retry, and "Start a new chat" opens a new chat. It failed before the change. Agent, chat and dashboard: 126 passed.

Summary by CodeRabbit

  • Bug Fixes
    • When the selected model cannot continue an agent conversation, the error now explains that the conversation cannot continue and offers Start a new chat instead of Retry.
    • The message is available in the user’s language and suggests starting a new chat or choosing another model. Selecting Start a new chat returns the user to a fresh conversation.

@vercel

vercel Bot commented Oct 5, 2026

Copy link
Copy Markdown

@Cedric921 is attempting to deploy a commit to the Rohan Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: MODSetter/SurfSense/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aa1b585f-a5bc-400e-ba34-d528df38430e
📥 Commits

Reviewing files that changed from the base of the PR and between f2c8828 and 0752ea5.

📒 Files selected for processing (1)
  • surfsense_local/frontend/src/features/chat/api.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The frontend now recognizes a specific unsupported-model refusal and records it as a chat error. The error notice offers “Start a new chat” instead of Retry. Localized guidance tells users to start a new chat or choose another model.

Changes

Unsupported model refusal

Layer / File(s) Summary
Refusal matching and capture
surfsense_local/frontend/src/features/agent/unsupported-model.ts, surfsense_local/frontend/src/features/chat/api.ts, surfsense_local/frontend/src/features/chat/use-chat-runtime.ts, docs/architecture/chat.md
A predicate matches an ApiError with status 409 and the exact refusal message. When it matches, the runtime records agent_model_unsupported with an empty message. The chat API type includes this client-only error. The architecture documentation describes the 409 rejection condition.
New-chat recovery and validation
surfsense_local/frontend/src/features/chat/chat-error-notice.tsx, surfsense_local/frontend/src/features/chat/chat-error-text.ts, surfsense_local/frontend/translations/*.json, surfsense_local/frontend/src/features/agent/unsupported-model-thread.test.tsx, docs/architecture/agent.md
The error notice offers a new-chat action, and the message is translated into ten locales. The test checks the cannot-continue message, absence of Retry, and composer after selecting “Start a new chat.” Architecture documentation describes the localized refusal and new-chat behavior.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 0752e

Unsupported-model refusals now direct users to start a new chat instead of retrying a turn that cannot proceed; the reviewed changes show no remaining merge-blocking risk.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to f2c88

The change provides a clearer recovery action without changing access permissions or allowing a refused request to proceed. No material security risk was identified in the changed flow.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The newly changed outcome is confined to client-side error presentation and conversation selection. The reviewed delta adds no server permission, credential, tool capability, or bypass of model eligibility.

Trust Boundaries and Controls

  • observed — The server remains responsible for refusing the turn. The frontend classifier only changes the displayed error and recovery action after receiving that refusal; it does not convert the rejected request into an accepted run.

Resilience and Maintainability Implications

  • observed — The new branch retains existing per-thread ownership, completion, abort handling, and selection guards. Repetition, interruption, concurrent thread runs, and thread switching do not acquire a new cleanup or ownership mechanism in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 14 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: offer a new chat when the selected model cannot run the agent thread.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…efusal-offers-new-chat

# Conflicts:
#	docs/architecture/agent.md
#	docs/architecture/chat.md
#	surfsense_local/backend/modules/agent/agent_threads/turn.py
#	surfsense_local/frontend/src/features/agent/agent-thread.test.tsx
#	surfsense_local/frontend/src/features/chat/chat-error-notice.tsx
#	surfsense_local/frontend/src/features/chat/message.tsx
#	surfsense_local/frontend/src/features/chat/use-chat-runtime.ts
#	surfsense_local/frontend/translations/de.json
#	surfsense_local/frontend/translations/en.json
#	surfsense_local/frontend/translations/es.json
#	surfsense_local/frontend/translations/fr.json
#	surfsense_local/frontend/translations/hi.json
#	surfsense_local/frontend/translations/ja.json
#	surfsense_local/frontend/translations/ko.json
#	surfsense_local/frontend/translations/pt-BR.json
#	surfsense_local/frontend/translations/ru.json
#	surfsense_local/frontend/translations/zh-CN.json
@Cedric921

Copy link
Copy Markdown
Contributor Author

Merged dev and reworked this onto the new-chat action from cf80ccf. The first version added its own button, its own prop chain and a backend error code, which would have duplicated what dev now has. It now recognises the refusal the way outdated-thread.ts does, and reuses new-chat and "Start a new chat". The PR body describes the current change.

…efusal-offers-new-chat

# Conflicts:
#	docs/architecture/chat.md
#	surfsense_local/frontend/src/features/chat/use-chat-runtime.ts
@MODSetter
MODSetter merged commit 5d527fe into MODSetter:dev Oct 6, 2026
22 of 23 checks passed
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.

2 participants