Skip to content

🗂️ feat: Add Private Chat Projects#13467

Merged
danny-avila merged 48 commits into
devfrom
danny-avila/private-chat-projects-v1
Jun 3, 2026
Merged

🗂️ feat: Add Private Chat Projects#13467
danny-avila merged 48 commits into
devfrom
danny-avila/private-chat-projects-v1

Conversation

@danny-avila

Copy link
Copy Markdown
Owner

Summary

I implemented private, user-owned chat projects as a V1 organizing layer for LibreChat conversations.

  • Added a ChatProject data-schemas module backed by the chatprojects collection, with per-user CRUD, one-project-per-chat assignment, stats maintenance, delete-unassign behavior, and Mongo memory tests.
  • Added chatProjectId to conversations and extended cursor-paginated conversation listing to filter by project or unassigned without grouping all chats client-side.
  • Added /api/projects CRUD and conversation assignment routes, with shared data-provider endpoints, types, query keys, services, schemas, and React Query hooks.
  • Added sidebar organization modes for chronological, by project, and recent projects, plus updated/created chat sorting while keeping conversation rows virtualized.
  • Added /projects and /projects/:projectId UI surfaces for project grid browsing, project-scoped chat listing, and project-scoped new chat creation.
  • Added conversation menu actions to change or remove a chat project assignment.

Change Type

  • New feature (non-breaking change which adds functionality)

Testing

  • npm run build:data-provider
  • npm run build:data-schemas
  • npm run build:client-package
  • npm run build:client
  • npm run build:api exits 0; it still reports existing unrelated TypeScript warnings in API config/auth/share files
  • cd packages/data-provider && npx jest src/schemas.spec.ts --runInBand
  • cd packages/data-schemas && npx jest src/methods/chatProject.spec.ts --runInBand
  • node -c api/server/routes/projects.js
  • Started npm run frontend:dev and smoke-checked /projects; unauthenticated routing landed on login with no console errors

Test Configuration:

  • Local macOS worktree
  • Node/npm via repository scripts
  • MongoDB memory server for packages/data-schemas tests

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

Copilot AI review requested due to automatic review settings June 2, 2026 03:02

Copy link
Copy Markdown
Owner Author

@codex review

1 similar comment

Copy link
Copy Markdown
Owner Author

@codex review

Copilot AI 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.

Pull request overview

This PR introduces a first-class “private chat projects” feature that lets users organize conversations into user-owned projects end-to-end (DB schema/model/methods, API routes, data-provider types/hooks, and client UI + sidebar organization modes).

Changes:

  • Added ChatProject persistence (schema/model/methods) with per-user CRUD, assignment/unassignment, and derived stats (conversation count + last activity).
  • Extended conversation listing/pagination to filter by projectId (including an "unassigned" sentinel) and surfaced chatProjectId in conversation payloads.
  • Added /api/projects endpoints and client UI surfaces (/projects, /projects/:projectId) plus sidebar “by project / recent projects” views and convo menu actions.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/data-schemas/src/types/index.ts Exposes new chatProject types via barrel export.
packages/data-schemas/src/types/convo.ts Adds chatProjectId field to conversation type.
packages/data-schemas/src/types/chatProject.ts New ChatProject TS types.
packages/data-schemas/src/schema/index.ts Exports new chatProjectSchema.
packages/data-schemas/src/schema/convo.ts Adds chatProjectId field + supporting indexes to conversations.
packages/data-schemas/src/schema/chatProject.ts New Mongoose schema for chatprojects.
packages/data-schemas/src/models/index.ts Registers the ChatProject model.
packages/data-schemas/src/models/chatProject.ts Creates tenant-isolated ChatProject model.
packages/data-schemas/src/methods/index.ts Registers ChatProject methods in data-schemas methods bundle.
packages/data-schemas/src/methods/conversation.ts Adds projectId filtering + project stat refresh hooks.
packages/data-schemas/src/methods/chatProject.ts Implements CRUD, assignment, cursor pagination, and stat refresh.
packages/data-schemas/src/methods/chatProject.spec.ts Adds Mongo-memory tests for ChatProject behavior.
packages/data-provider/src/types/queries.ts Adds projectId to convo list params + project list response types.
packages/data-provider/src/types.ts Adds ChatProject API types + includes chatProjectId in endpoint options.
packages/data-provider/src/schemas.ts Adds chatProjectId to conversation zod schema and derived schemas.
packages/data-provider/src/schemas.spec.ts Adds schema test ensuring chatProjectId survives compact parsing.
packages/data-provider/src/keys.ts Adds React Query keys/mutation keys for projects.
packages/data-provider/src/data-service.ts Adds project CRUD + assignment API calls.
packages/data-provider/src/bedrock.ts Preserves chatProjectId through Bedrock input parsing.
packages/data-provider/src/api-endpoints.ts Adds /api/projects endpoints.
packages/api/src/db/utils.ts Ensures chatprojects collection exists for migrations/compat.
client/src/utils/convos.ts Adds project-aware query-cache update helpers + dateField grouping.
client/src/routes/index.tsx Adds /projects and /projects/:projectId routes.
client/src/routes/ChatRoute.tsx Supports seeding new chats with chatProjectId via query param.
client/src/locales/en/translation.json Adds UI strings for projects and sidebar organization.
client/src/data-provider/queries.ts Passes projectId through conversation infinite query key/fetch.
client/src/data-provider/Projects/queries.ts New project list + project detail queries.
client/src/data-provider/Projects/mutations.ts New project create/update/delete + assignment mutations.
client/src/data-provider/Projects/index.ts Exports Projects query/mutation hooks.
client/src/data-provider/mutations.ts Invalidates projects on convo archive/delete/duplicate/fork.
client/src/data-provider/index.ts Re-exports Projects hooks.
client/src/components/UnifiedSidebar/ConversationsSection.tsx Adds sidebar organization modes + “new project” affordance.
client/src/components/Projects/ProjectWorkspace.tsx New project-scoped chat listing + “new chat in project” UX.
client/src/components/Projects/ProjectsView.tsx New projects grid view + create flow + search/sort.
client/src/components/Projects/ProjectChatList.tsx Virtualized project chat list grouped by date.
client/src/components/Projects/index.ts Exports Projects UI components.
client/src/components/Conversations/ProjectConversations.tsx New sidebar project/grouped conversations virtualized view.
client/src/components/Conversations/ConvoOptions/ProjectButton.tsx New dialog for assigning a convo to a project.
client/src/components/Conversations/ConvoOptions/index.ts Exports ProjectButton (TS barrel).
client/src/components/Conversations/ConvoOptions/index.js Exports ProjectButton (JS barrel).
client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx Adds “Change project” / “Remove from project” menu actions.
client/src/components/Conversations/Convo.tsx Passes chatProjectId into convo options.
client/src/components/Conversations/Conversations.tsx Adds dateField option for grouping/sorting display.
api/server/routes/projects.js New authenticated /api/projects CRUD + assignment routes.
api/server/routes/index.js Registers new projects router module.
api/server/routes/convos.js Adds projectId query param passthrough to convo cursor listing.
api/server/index.js Mounts /api/projects.
api/server/experimental.js Mounts /api/projects in experimental server.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +146 to +155
return null;
}

const op = sortDirection === 'asc' ? '$gt' : '$lt';
const id = new mongoose.Types.ObjectId(cursor.id);
const primary = cursorPrimaryValue(cursor.primary, sortBy);

return {
$or: [{ [sortBy]: { [op]: primary } }, { [sortBy]: primary, _id: { [op]: id } }],
} as FilterQuery<IChatProjectDocument>;
Comment on lines +67 to +69

const VALID_SORT_FIELDS = new Set<ChatProjectSortBy>(['name', 'createdAt', 'lastConversationAt']);

Comment on lines +288 to +290
if (conversation.chatProjectId) {
await refreshChatProjectStatsForUser(mongoose, userId, conversation.chatProjectId);
}
};

return (
<OGDialogContent className="w-11/12 max-w-md" showCloseButton={false}>
Comment on lines +254 to +258
parseCursor(options.cursor),
sortBy,
sortDirection,
);
if (cursorFilter) {
Comment on lines +36 to +46
const handleCreate = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const trimmedName = name.trim();
if (!trimmedName) {
return;
}
const project = await createProject.mutateAsync({ name: trimmedName });
setName('');
setIsCreating(false);
navigate(`/projects/${project._id}`);
};
Comment thread client/src/routes/ChatRoute.tsx Outdated
const index = 0;
const [searchParams] = useSearchParams();
const { conversationId = '' } = useParams();
const chatProjectId = searchParams.get('projectId');

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1df7035aa1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/conversation.ts Outdated
Comment thread client/src/data-provider/Projects/mutations.ts
Comment thread packages/data-provider/src/schemas.ts
Comment thread client/src/routes/ChatRoute.tsx
Comment thread client/src/components/UnifiedSidebar/ConversationsSection.tsx Outdated
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a27e88d441

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-schemas/src/methods/chatProject.ts Outdated
Comment thread client/src/components/Conversations/ProjectConversations.tsx Outdated
Comment thread packages/data-provider/src/schemas.ts
Comment thread client/src/data-provider/mutations.ts
@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila danny-avila changed the base branch from main to dev June 2, 2026 18:02
@danny-avila danny-avila marked this pull request as ready for review June 2, 2026 18:02
@danny-avila danny-avila force-pushed the danny-avila/private-chat-projects-v1 branch from 358fd09 to 77e9c0c Compare June 2, 2026 20:42
@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

…delete redirect, project-detail invalidation
@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b258d374a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-provider/src/config.ts
Comment thread packages/data-schemas/src/methods/conversation.ts
Comment thread client/src/components/Projects/ProjectChatList.tsx Outdated
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90dd1af803

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/data-provider/src/schemas.ts
Comment thread client/src/hooks/Chat/useChatFunctions.ts
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@danny-avila

Copy link
Copy Markdown
Owner Author

Codex triage (as of e68ce3d48f)

The automated reviewer re-emits its full finding set each run without tracking resolution, so most of the latest batch are repeats of already-fixed code. Mapping each category to its status for reviewers:

Fixed this review cycle

  • chatProjectId added to excludedKeys — continuations that don't echo it no longer unset the project assignment (config.ts).
  • Project-detail cache ([project, id]) invalidated alongside the list in all SSE save paths and after conversation deletes (the delete lookup now also scans the projectConversations cache).
  • Project workspace chat rows navigate via useNavigateToConvo, so a clicked chat no longer renders with the previously-loaded conversation's state.
  • Basename-safe redirect after project delete (useLocation instead of raw window.location.pathname).
  • A save or bulk write that moves a chat between projects now fully recomputes both the old and new project stats (gated to saves that touch project membership, so non-project saves add no query). Covered by new tests.

Already implemented in earlier commits (re-posts)

  • Assign mutation updates the active Recoil conversation and invalidates previous/new project details; delete-project mutation clears the active conversation's project.
  • MemoizedConvo comparator includes chatProjectId.
  • saveConvo/bulkSaveConvos validate project ownership and drop orphan ids server-side.
  • shouldRefreshProjectStats already accounts for archive and retention-visibility (temporary/expired) changes.
  • useQueryParams carries chatProjectId into the new-conversation template when applying URL settings.

Intentional — won't change

  • api/server/routes/projects.js is a 25-line thin wrapper delegating to createProjectHandlers in @librechat/api (the typed backend). The implementation already lives in packages/api, per the repo's workspace boundaries.
  • Project chats appear in both the Projects section and the chronological Chats list — a deliberate product decision for this iteration.
  • Assistants/Azure-Assistants chatProjectId persistence is out of scope (the Assistants endpoints are being deprecated); the Agents path carries the field.
  • Time-based retention/TTL expiry refreshing denormalized project stats is a separate architectural concern, not part of this PR.

@danny-avila

Copy link
Copy Markdown
Owner Author

@codex review

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

{
tags: tags.length === 0 ? undefined : tags,
search: search.debouncedQuery || undefined,
},

P2 Badge Filter the Chats query to unassigned chats

With the new Projects section rendering project-scoped conversations separately, this main Chats query still omits projectId: 'unassigned', so the backend returns every non-archived conversation, including ones assigned to projects. In the sidebar, any project chat that is shown under ProjectsSection will also remain in the general Chats list (unless a search is active), defeating the separate project organization and making project moves look duplicated. Use the new unassigned filter for the default Chats list while preserving all-chat search if that is desired.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/Chat/useChatFunctions.ts
Comment thread packages/data-provider/src/schemas.ts
# Conflicts:
#	client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13467 index is now live on the MCP server.
Deploy run

@danny-avila danny-avila merged commit baa23a8 into dev Jun 3, 2026
19 checks passed
@danny-avila danny-avila deleted the danny-avila/private-chat-projects-v1 branch June 3, 2026 19:29
fuuuzzy pushed a commit to fuuuzzy/LibreChat that referenced this pull request Jun 4, 2026
* feat: Add private chat projects

* fix: Format project files

* fix: Address project review findings

* fix: Resolve project review follow-ups

* fix: Handle project stats and cache edge cases

* style: align projects UI with sidebar patterns

* fix: resolve projects UI lint issues

* style: Align project menus and composer

* fix: Avoid project placeholder shadowing

* fix: Handle project search and stale ids

* fix: Polish project sidebar behavior

* fix: Preserve new chat stream after creation

* fix: Stabilize project sidebar sections

* fix: Smooth project sidebar organization

* fix: stabilize project chat entry

* fix: keep project workspace outside chat context

* fix: show default model on project workspace

* fix: fallback project workspace model label

* fix: preserve project scope during draft hydration

* fix: include route project in new chat submission

* fix: persist project id in agent chat saves

* fix: refine project sidebar and creation UX

* fix: export chat project method types

* fix: polish project landing context

* fix: refine project navigation affordances

* feat: rework projects UX — coexisting sidebar sections + URL-driven scope

Sidebar
- Replace the chronological/by-project mode toggle with coexisting
  Projects + Chats sections (both always visible)
- Remove ProjectConversations (927 lines), the org-mode Header, and types
- Add ProjectsSection: collapsible project rows that unfurl chats inline
  (full-size rows), with per-project new chat and an open/rename/delete menu
- Lift the marketplace/favorites shortcuts above the Projects section

Chat scope
- Derive a new chat's project strictly from the URL ?projectId, so the
  global New Chat no longer stays stuck in a project after a project chat

Surfaces
- Chat landing: subtle, clickable project chip instead of the floating badge
- Project workspace: modest header, composer-style entry, chats list
- All-projects grid: Claude-style cards with pluralized chat counts

* chore: prune unused i18n keys; fix project chat-count pluralization

* fix: project new-chat keeps model spec; sidebar header + row polish

- newConversation: ignore a chatProjectId-only template when deciding to
  apply the default model spec, so starting a chat in a project no longer
  strips the conversation `spec`
- useSelectMention: the Model Selector and @ command now retain the active
  project across endpoint/spec/preset switches; other new-chat paths still
  clear it
- Chats header now matches the Projects header (inline chevron + a new-chat
  icon button) and starts a non-project chat
- Project rows: use the new-chat icon for the per-project add button, render
  at text-sm to match the chat list, and align the row actions + hover color
  with conversation rows

* fix: read project scope from router params; align sidebar header icons

- useSelectMention now reads the active project from React Router's search
  params instead of window.location, which can drift out of sync because
  new-chat params are written to the URL via raw history.pushState; the
  Model Selector and @ command now reliably keep the project on switch
- Move the Chats section header out of the virtualized list so it renders
  in the same context as the Projects header and isn't shifted by the
  list scrollbar
- Inset header action icons (pr-2) so Projects/Chats header icons line up
  with the project-row and conversation-row trailing actions
- Extract getRouteChatProjectId into utils for the submit path

* fix: preserve chatProjectId through the new-chat template reduction

The param-endpoint guard in newConversation reduced a new chat's template to
{ endpoint } only, dropping the chatProjectId injected by the Model Selector /
@ switch — so switching models cleared the project scope. Keep chatProjectId
in the reduced template.

* style: align chat-history panel top padding; improve projects page contrast

- Add pt-2 to the chat-history panel so its top spacing matches the other
  side panels (agent builder, skills, files, etc.)
- Projects grid + workspace now use the darkest surface for the page
  (surface-primary) with cards, inputs, and the composer one step lighter
  (surface-secondary) and tertiary on hover, so cards read as elevated
  rather than darker than the background

* feat: interactive project landing chip + gallery icon for all-projects

- All-projects sidebar button uses the gallery-vertical-end icon
- The project landing chip is now interactive: click it to switch projects
  via a searchable combobox (ControlCombobox), or the trailing × to drop the
  project scope. Both update the draft conversation and the ?projectId search
  param in place, so the typed message and selected model are preserved

* test: fix Conversations unit test for refactored sidebar; add projects e2e

- Update Conversations.test.tsx mocks for the inline Chats header
  (useNewConvo, useQueryClient, conversation atom, NewChatIcon, TooltipAnchor),
  drop the removed chatsHeaderControls prop, and remove the mock for the
  deleted ../Header module — fixes the failing frontend Jest job
- Add e2e/specs/mock/projects.spec.ts covering project creation, the
  project-scoped new-chat landing + interactive chip (switch/remove), and
  listing projects on /projects
- Give the landing chip combobox a stable selectId for reliable targeting

* fix: refresh project stats after project-chat activity; stabilize e2e

- useEventHandlers: when a project chat is created/updated, invalidate the
  live [projects] query (gated on chatProjectId) instead of the now-unused
  projectConversations key, so the sidebar + all-projects stats refresh
  after a streamed reply (addresses a Codex finding)
- projects e2e: assert the reliable project-landing behavior (chip, scoped
  composer, accepted send) rather than the /c/:id transition, which the
  mock LLM harness doesn't complete

* test: verify a project chat saves and is filed under its project (e2e)

- Switch to a mock endpoint before sending so the message streams without a
  real API key (the default model failed with "No key found", so no chat was
  saved and the page never left /c/new); this also asserts the project chip
  survives the model switch
- Restore the reply + /c/:id transition assertions and add a check that the
  chat is listed under the expanded project in the sidebar
- Add data-testid="project-chats-<id>" to the inline project chat list

* fix: address Codex review findings (project scope edge cases)

- useSelectMention: fall back to the conversation's chatProjectId when the
  URL has no projectId, so switching model/spec inside an existing project
  chat (/c/:id) keeps the project assignment
- Conversations: include chatProjectId in the MemoizedConvo comparator so a
  sidebar row's project menu doesn't stay stale after a reassignment
- useDeleteProjectMutation: clear the active conversation's chatProjectId
  when its project is deleted (mirrors the assignment mutation); drop the
  now-dead projectConversations invalidation
- useQueryParams: carry the project into the new conversation when applying
  URL settings, so /c/new?projectId=...&<settings> stays scoped

* fix: project stats pagination + archived-chat edge cases (data-schemas)

- listChatProjects: include the null lastConversationAt bucket in the desc
  cursor so empty projects paginate (a $lt:<date> predicate excluded nulls,
  hiding chat-less projects from "Load more")
- saveConvo: recompute project stats instead of the incremental fast path
  when the saved conversation is itself archived/temporary/expired, so a
  project's lastConversationAt/Id no longer points at a hidden chat

* test: cover chat-less project pagination across the dated→null boundary

* fix: validate project ownership in bulkSaveConvos

Bulk paths (import/duplicate/fork) persisted whatever chatProjectId the
payload carried; an id that does not belong to the user created an orphan
assignment hidden from both the project and the unassigned sidebar. Validate
ownership like saveConvo and strip un-owned project ids before persisting,
refreshing stats only for owned projects.

* fix(projects): preserve chatProjectId on continuation, basename-safe delete redirect, project-detail invalidation

* fix(projects): navigate project workspace chats via useNavigateToConvo to avoid stale conversation state

* fix(projects): include projectConversations cache when resolving deleted chat's project for detail invalidation

* fix(projects): refresh both projects when a save or bulk write moves a chat between them

* style(projects): use Folders icon for the sidebar Projects header

* fix(projects): require id on ProjectUser so ProjectRequest extends Express Request cleanly

* style(projects): taller project chip with hover-revealed remove button, upward combobox; sort en translations

* style(projects): show endpoint/agent icon for project workspace chat rows
danny-avila added a commit that referenced this pull request Jun 5, 2026
…ted (#13525)

* fix(projects): clear landing scope when the selected project is deleted

When a project-scoped new-chat landing (/c/new?projectId=...) was open and the
project got deleted, the chip kept showing the dead project and sends targeted it
(saving unscoped with a visual glitch).

- ChatRoute: only trust the scope when the project query succeeds (isSuccess), so
  React Query's retained-on-error data can't keep a deleted project's chip alive;
  strip ?projectId once the query settles to not-found so the landing reverts to a
  normal unscoped chat.
- useDeleteProjectMutation: invalidate the project-detail query instead of removing
  it, so active observers refetch and settle into an error state (removing left them
  stuck loading under refetchOnMount: false).
- e2e: regression test for delete-while-scoped.

Fixes a follow-up issue to the projects feature (#13467).

* fix(projects): only drop scope on definitive not-found; clear inactive deleted detail

Address Codex review on #13525:
- ChatRoute: gate scope removal on a 404 (isNotFoundError) or a success that
  resolves to a different/empty project, so a transient (non-404) failure under
  retry:false no longer unscopes a valid project; keep the chip through transient
  errors via retained data.
- useDeleteProjectMutation: also removeQueries({ type: 'inactive' }) so a deleted
  project's inactive cached detail is dropped and a later visit refetches into a
  not-found state instead of rendering stale cache within cacheTime.
fuuuzzy pushed a commit to fuuuzzy/LibreChat that referenced this pull request Jun 18, 2026
…ted (danny-avila#13525)

* fix(projects): clear landing scope when the selected project is deleted

When a project-scoped new-chat landing (/c/new?projectId=...) was open and the
project got deleted, the chip kept showing the dead project and sends targeted it
(saving unscoped with a visual glitch).

- ChatRoute: only trust the scope when the project query succeeds (isSuccess), so
  React Query's retained-on-error data can't keep a deleted project's chip alive;
  strip ?projectId once the query settles to not-found so the landing reverts to a
  normal unscoped chat.
- useDeleteProjectMutation: invalidate the project-detail query instead of removing
  it, so active observers refetch and settle into an error state (removing left them
  stuck loading under refetchOnMount: false).
- e2e: regression test for delete-while-scoped.

Fixes a follow-up issue to the projects feature (danny-avila#13467).

* fix(projects): only drop scope on definitive not-found; clear inactive deleted detail

Address Codex review on danny-avila#13525:
- ChatRoute: gate scope removal on a 404 (isNotFoundError) or a success that
  resolves to a different/empty project, so a transient (non-404) failure under
  retry:false no longer unscopes a valid project; keep the chip through transient
  errors via retained data.
- useDeleteProjectMutation: also removeQueries({ type: 'inactive' }) so a deleted
  project's inactive cached detail is dropped and a later visit refetches into a
  not-found state instead of rendering stale cache within cacheTime.
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