Skip to content

ECHO-450 Add conversation to chat context#292

Merged
ussaama merged 3 commits intomainfrom
add-conversation-to-chat
Sep 12, 2025
Merged

ECHO-450 Add conversation to chat context#292
ussaama merged 3 commits intomainfrom
add-conversation-to-chat

Conversation

@ussaama
Copy link
Copy Markdown
Contributor

@ussaama ussaama commented Sep 12, 2025

Summary by CodeRabbit

  • New Features

    • Starting a chat can now continue an existing conversation when launched from a linked context.
  • Bug Fixes

    • Chats created from a project reliably associate with the intended conversation.
  • Improvements

    • Immediate navigation to newly created chats for a smoother experience.
    • Smarter default selection of enhanced audio processing when continuing conversations.
  • Chores

    • Background changes to make adding chat context non-blocking and improve responsiveness.

@linear
Copy link
Copy Markdown

linear bot commented Sep 12, 2025

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 12, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds propagation of conversationId into chat-creation flow and refactors chat creation to use a non-blocking useAddChatContextMutation, adjust auto_select logic, and perform earlier navigation to the newly created chat. LGTM.

Changes

Cohort / File(s) Summary
ProjectSidebar integration
echo/frontend/src/components/project/ProjectSidebar.tsx
Passes conversationId (from route params) into createChatMutation.mutate({ project_id, navigateToNewChat, conversationId }).
Chat creation hooks refactor
echo/frontend/src/components/project/hooks/index.ts
Replaces direct addChatContext call with useAddChatContextMutation and calls addChatContextMutation.mutate({ chatId, conversationId }) (non-blocking). Updates auto_select to consider payload.conversationId with is_enhanced_audio_processing_enabled. Performs early navigation to the created chat when navigateToNewChat is set; removes the previous awaited context-call and trailing navigation block.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Pre-merge checks (3 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning In addition to the conversation association, the PR modifies auto_select logic related to enhanced audio processing and restructures navigation and error-handling by removing the awaited addChatContext and making it non-blocking; these behavioral changes are not mentioned in ECHO-450 and could affect unrelated flows. Split or clearly document and justify the unrelated behavioral changes in a separate PR, and add unit/integration tests for the modified auto_select behavior and the new navigation/timing/error-handling to prevent regressions.
Linked Issues Check ❓ Inconclusive The diff shows conversationId being passed into createChat and an addChatContextMutation invoked, which directly targets the ECHO-450 goal of associating a conversation with a newly created chat [ECHO-450]; however, because the new flow navigates to the chat immediately and the addChatContext call is non-blocking (not awaited), it is unclear from the changes alone whether the conversation association will be present at the time of navigation, so I cannot conclusively verify the bug is fully fixed. Ensure the association is applied before or at navigation by awaiting the addChatContext mutation or applying an optimistic client update, and add an automated integration test that reproduces "navigate to a conversation -> open chat" and asserts the conversation is selected for the new chat.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "ECHO-450 Add conversation to chat context" is concise, accurately describes the primary change (adding conversation association to chat creation/context), and includes the issue id for traceability; it matches the modifications shown in ProjectSidebar and the hooks. LGTM.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bbaf6be and 5f8e095.

📒 Files selected for processing (1)
  • echo/frontend/src/components/project/hooks/index.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-19T10:22:55.323Z
Learnt from: ussaama
PR: Dembrane/echo#266
File: echo/frontend/src/components/conversation/ConversationAccordion.tsx:675-678
Timestamp: 2025-08-19T10:22:55.323Z
Learning: In echo/frontend/src/components/conversation/hooks/index.ts, the useConversationsCountByProjectId hook uses regular useQuery (not useSuspenseQuery), which means conversationsCountQuery.data can be undefined during loading states. When using Number(conversationsCountQuery.data) ?? 0, this creates NaN because Number(undefined) = NaN and NaN is not nullish, so the fallback doesn't apply. The correct pattern is Number(conversationsCountQuery.data ?? 0) to ensure the fallback happens before type conversion.

Applied to files:

  • echo/frontend/src/components/project/hooks/index.ts
🧬 Code graph analysis (1)
echo/frontend/src/components/project/hooks/index.ts (1)
echo/frontend/src/components/conversation/hooks/index.ts (1)
  • useAddChatContextMutation (273-404)
🔇 Additional comments (2)
echo/frontend/src/components/project/hooks/index.ts (2)

19-19: Nice switch to a dedicated mutation hook.

Using useAddChatContextMutation centralizes optimistic updates and error toasts. LGTM.


117-119: Mutate chat context before navigation to avoid blank state on first paint.

Call addChatContextMutation.mutate(...) before navigate(...) so the optimistic update populates the cache prior to the new route rendering.

File: echo/frontend/src/components/project/hooks/index.ts (around lines 117–126)

-      if (payload.navigateToNewChat && chat && chat.id) {
-        navigate(`/projects/${payload.project_id.id}/chats/${chat.id}`);
-      }
-
-      if (payload.conversationId) {
-        addChatContextMutation.mutate({
-          chatId: chat.id,
-          conversationId: payload.conversationId,
-        });
-      }
+      if (payload.conversationId) {
+        addChatContextMutation.mutate({
+          chatId: chat.id,
+          conversationId: payload.conversationId,
+        });
+      }
+
+      if (payload.navigateToNewChat && chat && chat.id) {
+        navigate(`/projects/${payload.project_id.id}/chats/${chat.id}`);
+      }

Also verify UX: after clicking “Chat” from a conversation, the opened chat renders with that conversation pre-selected on first paint.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-conversation-to-chat

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 and usage tips.

spashii
spashii previously approved these changes Sep 12, 2025
cursor[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai bot added the Feature label Sep 12, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 998957c and bbaf6be.

📒 Files selected for processing (2)
  • echo/frontend/src/components/project/ProjectSidebar.tsx (1 hunks)
  • echo/frontend/src/components/project/hooks/index.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-19T10:22:55.323Z
Learnt from: ussaama
PR: Dembrane/echo#266
File: echo/frontend/src/components/conversation/ConversationAccordion.tsx:675-678
Timestamp: 2025-08-19T10:22:55.323Z
Learning: In echo/frontend/src/components/conversation/hooks/index.ts, the useConversationsCountByProjectId hook uses regular useQuery (not useSuspenseQuery), which means conversationsCountQuery.data can be undefined during loading states. When using Number(conversationsCountQuery.data) ?? 0, this creates NaN because Number(undefined) = NaN and NaN is not nullish, so the fallback doesn't apply. The correct pattern is Number(conversationsCountQuery.data ?? 0) to ensure the fallback happens before type conversion.

Applied to files:

  • echo/frontend/src/components/project/hooks/index.ts
🧬 Code graph analysis (1)
echo/frontend/src/components/project/hooks/index.ts (1)
echo/frontend/src/components/conversation/hooks/index.ts (1)
  • useAddChatContextMutation (273-404)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ci-build-servers (dbr-echo-directus, ./echo/directus, Dockerfile, dbr-echo-directus)
  • GitHub Check: ci-build-servers (dbr-echo-server, ./echo/server, Dockerfile, dbr-echo-server)
🔇 Additional comments (3)
echo/frontend/src/components/project/hooks/index.ts (3)

22-23: LGTM: localizing the chat-context mutation here is the right call.


118-121: Early navigate FTW.

Immediate route switch post-create is the right UX for this flow.


109-121: Confirm product intent: disabling auto-select when a conversation is preselected.

Logic now forces auto_select=false when conversationId is provided and enhanced audio is enabled. If the goal is “stick with the explicit conversation, don’t auto-switch,” this is perfect. If auto-select is independent of conversation pinning, revisit.

Would you like me to add an e2e covering: navigating from /conversations/:conversationId → Ask → verify chat context includes that conversation and auto_select=false?

Comment on lines 109 to 116
const chat = await directus.request(
createItem("project_chat", {
...(payload as any),
auto_select: !!project.is_enhanced_audio_processing_enabled,
auto_select: payload.conversationId && project.is_enhanced_audio_processing_enabled
? false
: !!project.is_enhanced_audio_processing_enabled,
}),
);
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.

🛠️ Refactor suggestion

⚠️ Potential issue

Blocker: don’t spread client-only keys into Directus createItem.

Spreading the whole payload leaks navigateToNewChat and conversationId to the API. Depending on Directus config, this can 400 or silently drop fields. Send only collection fields.

Apply:

-      const chat = await directus.request(
-        createItem("project_chat", {
-          ...(payload as any),
-          auto_select: payload.conversationId && project.is_enhanced_audio_processing_enabled 
-            ? false 
-            : !!project.is_enhanced_audio_processing_enabled,
-        }),
-      );
+      const chat = await directus.request(
+        createItem("project_chat", {
+          project_id: payload.project_id,
+          auto_select:
+            payload.conversationId &&
+            project.is_enhanced_audio_processing_enabled
+              ? false
+              : !!project.is_enhanced_audio_processing_enabled,
+        }),
+      );

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In echo/frontend/src/components/project/hooks/index.ts around lines 109 to 116,
the current createItem spreads the entire payload which leaks client-only keys
like navigateToNewChat and conversationId into the Directus API; instead, build
and pass an object that contains only the collection fields (whitelist) or
explicitly omit client-only keys before calling createItem, and compute
auto_select from payload.conversationId and
project.is_enhanced_audio_processing_enabled without including conversationId
itself; ensure you either pick allowed fields or destructure to remove
navigateToNewChat and conversationId so only valid Directus fields are sent.

Comment on lines 112 to 115
auto_select: payload.conversationId && project.is_enhanced_audio_processing_enabled
? false
: !!project.is_enhanced_audio_processing_enabled,
}),
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.

🧹 Nitpick (assertive)

Tiny cleanup: pull auto_select into a local const for clarity.

No behavior change; easier to reason and reuse.

Apply:

-          auto_select:
-            payload.conversationId &&
-            project.is_enhanced_audio_processing_enabled
-              ? false
-              : !!project.is_enhanced_audio_processing_enabled,
+          auto_select: shouldAutoSelect,

And just above:

const shouldAutoSelect =
  payload.conversationId && project.is_enhanced_audio_processing_enabled
    ? false
    : !!project.is_enhanced_audio_processing_enabled;
🤖 Prompt for AI Agents
In echo/frontend/src/components/project/hooks/index.ts around lines 112 to 115,
extract the inline ternary used for auto_select into a local constant named
shouldAutoSelect (defined just above the object) and then replace the inline
expression with auto_select: shouldAutoSelect; keep the exact logic: if
payload.conversationId is truthy and
project.is_enhanced_audio_processing_enabled is truthy then false, otherwise
coerce project.is_enhanced_audio_processing_enabled to boolean.

Comment on lines 35 to 39
createChatMutation.mutate({
project_id: { id: projectId ?? "" },
conversationId: conversationId,
navigateToNewChat: true,
});
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Sep 12, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Gate conversationId to avoid sending undefined; also use shorthand.

Keep the payload clean and avoid passing undefined. Minor readability bump too.

Apply:

   createChatMutation.mutate({
-    project_id: { id: projectId ?? "" },
-    conversationId: conversationId,
+    project_id: { id: projectId! },
+    ...(conversationId ? { conversationId } : {}),
     navigateToNewChat: true,
   });
🤖 Prompt for AI Agents
In echo/frontend/src/components/project/ProjectSidebar.tsx around lines 35-39,
the mutation payload currently sends conversationId even when it may be
undefined and uses the longhand property assignment; instead build the payload
object, only add conversationId when it's defined (e.g. if (conversationId !=
null) payload.conversationId = conversationId), and use shorthand property
syntax for navigateToNewChat (and conversationId when present), then call
createChatMutation.mutate(payload) so undefined is not sent and readability is
improved.

Copy link
Copy Markdown
Contributor Author

@ussaama ussaama Sep 12, 2025

Choose a reason for hiding this comment

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

no need its better when we want to see what parameters are coming in the request

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.

@ussaama Gotcha, no worries! LGTM then. 🚀

The code works as-is and the mutation will handle the undefined conversationId appropriately. Thanks for the quick response!


🧠 Learnings used
Learnt from: ussaama
PR: Dembrane/echo#266
File: echo/frontend/src/components/conversation/ConversationAccordion.tsx:675-678
Timestamp: 2025-08-19T10:22:55.323Z
Learning: In echo/frontend/src/components/conversation/hooks/index.ts, the useConversationsCountByProjectId hook uses regular useQuery (not useSuspenseQuery), which means conversationsCountQuery.data can be undefined during loading states. When using Number(conversationsCountQuery.data) ?? 0, this creates NaN because Number(undefined) = NaN and NaN is not nullish, so the fallback doesn't apply. The correct pattern is Number(conversationsCountQuery.data ?? 0) to ensure the fallback happens before type conversion.

@ussaama ussaama added this pull request to the merge queue Sep 12, 2025
Merged via the queue into main with commit 3c92ea9 Sep 12, 2025
11 of 12 checks passed
@ussaama ussaama deleted the add-conversation-to-chat branch September 12, 2025 14:42
spashii pushed a commit that referenced this pull request Nov 18, 2025
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- New Features
- Starting a chat can now continue an existing conversation when
launched from a linked context.

- Bug Fixes
- Chats created from a project reliably associate with the intended
conversation.

- Improvements
- Immediate navigation to newly created chats for a smoother experience.
- Smarter default selection of enhanced audio processing when continuing
conversations.

- Chores
- Background changes to make adding chat context non-blocking and
improve responsiveness.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants