Skip to content

fix(chat): show history when its chat profile is unavailable - #3066

Open
tuanzirwar wants to merge 3 commits into
Chainlit:mainfrom
tuanzirwar:codex/handle-unavailable-chat-profiles
Open

tuanzirwar wants to merge 3 commits into
Chainlit:mainfrom
tuanzirwar:codex/handle-unavailable-chat-profiles

Conversation

@tuanzirwar

@tuanzirwar tuanzirwar commented Oct 3, 2026 •

Copy link
Copy Markdown

Fixes #2492.

If a saved thread references a deleted or renamed chat profile, restoring that name can invoke application resume hooks with an unavailable configuration and leave the conversation unusable. Validate the stored profile against the current user's profile registry after checking thread ownership and before restoring session metadata.

Emit an explicit unavailable-resume event and show the existing private read-only history view. Do not invoke chat start/resume hooks, accept new messages, or persist disconnect metadata for this unavailable session. Reconnects repeat the same state, while clearing the chat resets the fallback. Available profiles continue using normal resume behavior; no schema migration or profile substitution is introduced.

Validation: 117 backend socket/profile/server tests and all 39 frontend unit tests pass. Five new backend regressions fail on the original implementation. The full backend mypy check and all repository commit hooks pass with locked optional dependencies. Both changed TypeScript projects type-check, the react-client and frontend production builds pass, and changed-file Ruff/ESLint/Prettier checks pass. A real Chrome + SQLAlchemy/SQLite app verifies the owner can read the saved conversation without a chat input, an available profile continues replying, and a different user's private-thread request remains rejected with 401. The unavailable thread's original metadata and saved message remain unchanged after browsing.

AI-assisted implementation (commit includes the required co-author trailer). Tested on Windows/Python 3.12 within the supported runtime range; the official development target is Python 3.13. The complete upstream Cypress suite and production cloud data layers were not run. This addresses invalid-profile history access, separate from active-conversation profile hot swapping in #3015.


Summary by cubic

Fixes #2492. When a saved thread referenced a deleted or renamed chat profile, resuming it invoked application hooks with an unavailable configuration and left the conversation unusable. The stored profile is now validated against the current registry before restoring session metadata. If unavailable, the existing private read-only history view is shown without resuming, accepting messages, or persisting disconnect state. Leaving that history clears the session and resets to a valid chat profile when the stored one is stale. Available profiles continue normal resume behavior. No schema migration or profile substitution is introduced.

  • Read-only sessions reject all mutating events, including action calls (409), settings changes, audio input, stop, and message editing.
  • The unavailable state is enforced client-side, showing history without a chat input or loading loop and clearing the session when leaving.

Written for commit 02f8779. Summary will update on new commits.

Review in cubic

Review follow-up (2026-10-04)

Addressed the four automated review findings: guard the mutating Socket.IO handlers before callbacks, message changes or task creation; preserve unavailable-profile overrides in the test session factory; require a defined route ID before treating a thread as unavailable; and clear the unavailable session when returning to the home or optional /thread route so a fresh writable session connects. Also reject HTTP actions for the unavailable session with 409 after ownership checks; unauthorized users still receive 401 and normal actions remain functional.

Validation for this follow-up: 117 backend socket/profile/server tests and all 39 frontend unit tests pass. The new tests reproduce 11 backend failures and 3 frontend failures on the previous PR head. The full backend mypy check (110 source files), frontend type-check, production build, changed-file Ruff/ESLint/Prettier checks and repository commit hooks pass. A real Chrome/WebSocket/SQLite flow verifies read-only history, HTTP action rejection (409), SPA navigation home without a page reload followed by a new session and a successful reply, normal available-profile replies, and another user's private-history rejection (401). The original unavailable profile metadata and saved message remain unchanged. The complete upstream Cypress suite and production cloud data layers remain untested.

Profile selection follow-up (2026-10-04)

The shared clear() hook now validates the selected profile when leaving an
unavailable session, so both Home and the optional /thread route benefit.
It keeps a still-valid selection; otherwise it selects the configured default
or first available profile, and clears the selection if no profiles remain.
Normal chat clearing preserves the selected profile. This avoids sending a
deleted/renamed profile on the fresh connection and avoids an unnecessary
intermediate unset selection when a valid profile is already selected.

Six regression tests use the real hook and Recoil state. Three fail on the
previous PR head and all six pass after the change. All 22 react-client tests
and 39 frontend tests pass; both TypeScript projects, client/frontend production
builds, changed-file ESLint/Prettier and all applicable commit hooks pass.
No backend production code was changed in this follow-up; the backend validation
listed in the earlier section belongs to that earlier follow-up.

A real Chrome/WebSocket/SQLite scenario resumes a formerly available profile,
removes it in the local app, verifies the client requested settings for deleted,
keeps unavailable history read-only, and navigates home without reloading.
The fresh socket authenticates with active, the backend callback verifies that
profile, and its reply is persisted. Original unavailable history retains its
profile. The SQLite QA fixture normalizes JSON metadata to an object for the
resume event; that harness adjustment is not included in this PR.
Full Cypress, hosted models and production cloud databases remain untested.

Co-Authored-By: Codex <noreply@openai.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 10 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread backend/chainlit/socket.py
Comment thread frontend/src/pages/Thread.tsx Outdated
Comment thread libs/react-client/src/useChatSession.ts
Comment thread backend/tests/conftest.py Outdated
Co-Authored-By: Codex <noreply@openai.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/pages/Home.tsx

This branch has not been deployed

No deployments
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.

Preserve Thread History when Chat Profile no longer available or is renamed

1 participant