Skip to content

perf(nuxi): optimise chat composables, caching and navigation#2305

Draft
HugoRCD wants to merge 13 commits into
mainfrom
fix/chat-persistence
Draft

perf(nuxi): optimise chat composables, caching and navigation#2305
HugoRCD wants to merge 13 commits into
mainfrom
fix/chat-persistence

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Jul 2, 2026

Copy link
Copy Markdown
Member

No description provided.

@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nuxt Ready Ready Preview, Comment Jul 3, 2026 2:42pm

@HugoRCD HugoRCD self-assigned this Jul 2, 2026
@nuxt nuxt deleted a comment from github-actions Bot Jul 2, 2026
@HugoRCD HugoRCD marked this pull request as ready for review July 2, 2026 12:54
@HugoRCD HugoRCD requested a review from atinux as a code owner July 2, 2026 12:54
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR restructures the Nuxi agent chat system. Eve session/thread-state helpers are removed and replaced by a new useEveChat composable, along with useNuxiChat and useStartChat orchestrating resume, voting, persistence, and chat creation. New useChatDetail utilities add caching, navigation-id, and route-id helpers. AgentChatBody.vue is added, AgentPanel/AgentPanelChat are updated to use the new state/handlers, dashboard chat pages are rewired to the new composables, the chat creation API returns full chat detail, and the view-transition plugin/config are adjusted.

Estimated code review effort: 5 (Critical) | ~120 minutes

Changes

Cohort / Area Changes
Chat data & cache Renamed message conversion helpers, createChatWithMessage now returns ChatDetail, added anonymous title persistence, new useChatDetail cache/navigation/route-id helpers, useChats uses shared cache key with login-gated refresh
Eve chat core New useEveChat composable; useAgentChat refactored to single options interface with centralized DB/title sync; usePasteAttachment exposes prompt
Resume & start New useNuxiChat (votes, headers, resume logic, stale refresh) and useStartChat composables
Agent UI New AgentChatBody.vue; AgentPanel/AgentPanelChat updated for initial state and new handlers; AgentChatMessages pending-message logic updated
Dashboard pages Chat index/[id] pages and dashboard layout rewired to new composables and rendering branches
Server & routing Chat creation API returns full detail; view-transition plugin added; nuxt.config.ts experimental flag removed

Sequence Diagram(s)

sequenceDiagram
  participant Page
  participant useNuxiChat
  participant useEveChat
  participant EveAgent
  participant API

  Page->>useNuxiChat: init(options)
  useNuxiChat->>useNuxiChat: resumeChatSession()
  useNuxiChat->>useEveChat: send(input)
  useEveChat->>EveAgent: submit payload
  EveAgent-->>useEveChat: messages/status/error
  useNuxiChat->>API: PATCH state/title
  useNuxiChat-->>Page: getVote/vote, onSubmit
Loading

Related issues: None specified.

Related PRs: None specified.

Suggested labels: area: nuxi, agent-chat, refactor

Suggested reviewers: None specified.

🐇 A chat once tangled in threads and states,
now flows through one composable gate,
Eve remembers where it left the sun,
resumes the story, message by one,
hopping onward, refactor complete!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive No meaningful description was provided, so there is no substantive summary to evaluate. Add a brief PR description that summarizes the key chat, caching, and navigation changes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main theme of the PR: chat composables, caching, and navigation improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chat-persistence

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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

🧹 Nitpick comments (1)
layers/nuxi/app/composables/useAgentChatSession.ts (1)

22-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate row-conversion logic.

The id/role/parts/createdAt-fallback mapping here duplicates uiMessagesToRows in useChatDetailCache.ts (Lines 7-14). Consider reusing uiMessagesToRows here to avoid the two implementations drifting (e.g. one gets a createdAt-stability fix and the other doesn't).

♻️ Proposed consolidation
-  const rows: ChatMessageRow[] = initialMessages.map(message => ({
-    id: message.id,
-    role: message.role,
-    parts: message.parts,
-    createdAt: (message.metadata as { createdAt?: string } | undefined)?.createdAt ?? new Date().toISOString()
-  }))
+  const rows: ChatMessageRow[] = uiMessagesToRows(initialMessages)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layers/nuxi/app/composables/useAgentChatSession.ts` around lines 22 - 49, The
row-mapping logic in chatDetailForResume duplicates the UI-message-to-row
conversion already implemented in uiMessagesToRows, so reuse that shared helper
instead of rebuilding the id/role/parts/createdAt mapping locally. Update
useAgentChatSession.ts to call uiMessagesToRows when constructing rows, keeping
the createdAt fallback behavior centralized in useChatDetailCache.ts so both
paths stay consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@layers/nuxi/app/components/agent/AgentPanelChat.vue`:
- Line 122: The AgentLoginHint in AgentPanelChat.vue is missing the logged-in
guard, so it renders for authenticated users too. Update the AgentPanelChat
template to match the AgentChatBody.vue logic by gating AgentLoginHint with the
same showLoginHint condition, using the existing loggedIn state and
props.loginHintBar so the sidebar hint only appears when appropriate.

In `@layers/nuxi/app/composables/useAgentChat.ts`:
- Around line 153-159: The persistence flag in useAgentChat should distinguish
an existing chat from a message that has already been saved, because
initialDbPersistDone is being set from initialMessages presence and blocks the
existing-chat append path in the prompt submit flow. Update the logic around
useAgentChat, initialDbPersistDone, and the submit/persist branch near the
existing-chat handling so only the resume/initial message is treated as already
persisted, while normal new prompts in an existing chat still go through the
append path immediately. Keep the resume-state tracking separate from the prompt
submission state so new user messages are not skipped before Eve finish sync.

In `@layers/nuxi/app/composables/useAgentChatSession.ts`:
- Around line 16-20: The needsGeneration helper in useAgentChatSession is using
“any assistant message ever” instead of checking whether the latest turn is
still unanswered. Update needsGeneration to inspect the message order and decide
based on the last message (or the last user/assistant pair) so it returns true
when the most recent message is a user turn without a following assistant reply;
this will correctly drive chatDetailForResume, setupStaleChatRefresh, and the
resumeChatSession owner-resume branch.

In `@layers/nuxi/app/composables/useStartChat.ts`:
- Around line 41-48: The draft is being cleared in onSubmit() before
createChat() confirms success, so move the input.value and
paste.clearAttachments() reset to after createChat(parts) succeeds. Update
createChat() to return a success boolean in useStartChat and have onSubmit()
only clear the draft when that result is true, while keeping the existing
paste.canSubmit, buildMessageParts, and track flow intact.

In `@layers/nuxi/app/pages/dashboard/chat/`[id].vue:
- Line 63: The vote loading flag is being snapshotted too early in the chat page
setup, so `useChatVotes()` never fetches owner votes after `useChatDetail()`
resolves. Update the `fetchVotes` usage in the `[id].vue` chat page to be
reactive to `isOwner` or defer triggering vote loading until ownership is known,
using the `useChatDetail`/`useChatVotes` flow rather than `isOwner.value` at
initialization.

In `@layers/nuxi/app/plugins/chat-view-transitions.client.ts`:
- Around line 8-55: The module-scoped view transition state in
chat-view-transitions.client.ts can be overwritten when router.beforeResolve
runs again before the prior document.startViewTransition() finishes. Add an
in-flight guard or cancel/skip path in beforeResolve so only one active
transition exists at a time, and ensure resetTransitionState only clears the
matching transition/finishTransition for the current ViewTransition. Use the
existing transition, finishTransition, resetTransitionState, and beforeResolve
symbols to keep the active chat prompt transition from getting stuck.

---

Nitpick comments:
In `@layers/nuxi/app/composables/useAgentChatSession.ts`:
- Around line 22-49: The row-mapping logic in chatDetailForResume duplicates the
UI-message-to-row conversion already implemented in uiMessagesToRows, so reuse
that shared helper instead of rebuilding the id/role/parts/createdAt mapping
locally. Update useAgentChatSession.ts to call uiMessagesToRows when
constructing rows, keeping the createdAt fallback behavior centralized in
useChatDetailCache.ts so both paths stay consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: afad961a-5be5-4c5d-9ab7-e9493d872d3a

📥 Commits

Reviewing files that changed from the base of the PR and between e35886e and fdaee15.

📒 Files selected for processing (22)
  • layers/nuxi/app/components/agent/AgentChatBody.vue
  • layers/nuxi/app/components/agent/AgentPanel.vue
  • layers/nuxi/app/components/agent/AgentPanelChat.vue
  • layers/nuxi/app/composables/eve/adapter.ts
  • layers/nuxi/app/composables/eve/init.ts
  • layers/nuxi/app/composables/eve/session.ts
  • layers/nuxi/app/composables/eve/thread-state.ts
  • layers/nuxi/app/composables/eve/types.ts
  • layers/nuxi/app/composables/eve/useEveChat.ts
  • layers/nuxi/app/composables/useAgentChat.ts
  • layers/nuxi/app/composables/useAgentChatSession.ts
  • layers/nuxi/app/composables/useChatDetail.ts
  • layers/nuxi/app/composables/useChatDetailCache.ts
  • layers/nuxi/app/composables/useChats.ts
  • layers/nuxi/app/composables/usePasteAttachment.ts
  • layers/nuxi/app/composables/useStartChat.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue
  • layers/nuxi/app/pages/dashboard/chat/index.vue
  • layers/nuxi/app/plugins/chat-view-transitions.client.ts
  • layers/nuxi/server/api/chats/index.post.ts
  • layers/nuxi/shared/utils/chat.ts
  • nuxt.config.ts
💤 Files with no reviewable changes (5)
  • layers/nuxi/app/composables/eve/init.ts
  • nuxt.config.ts
  • layers/nuxi/app/composables/eve/session.ts
  • layers/nuxi/app/composables/eve/thread-state.ts
  • layers/nuxi/app/composables/eve/types.ts

Comment thread layers/nuxi/app/components/agent/AgentPanelChat.vue Outdated
Comment thread layers/nuxi/app/composables/useAgentChat.ts Outdated
Comment thread layers/nuxi/app/composables/useAgentChatSession.ts Outdated
Comment thread layers/nuxi/app/composables/useStartChat.ts
Comment thread layers/nuxi/app/pages/dashboard/chat/[id].vue Outdated
Comment thread layers/nuxi/app/plugins/chat-view-transitions.client.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/layouts/dashboard.vue`:
- Around line 12-15: The logout flow in the `watch(loggedIn, ...)` block stops
calling `refreshChats()` when `next` is false, so the clear-chat-list branch
inside `useChats().refresh()` never runs. Update this watcher in
`app/layouts/dashboard.vue` so `refreshChats()` is invoked on logout as well as
login, while keeping `sidebarOpen.value = false` behavior intact. Use the
existing `refreshChats`/`loggedIn` watcher logic to ensure the sidebar’s
`groups`/`items` list is cleared immediately after sign-out.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a36826b1-2cc3-41c1-955e-f5aeebef9b34

📥 Commits

Reviewing files that changed from the base of the PR and between fdaee15 and 9284933.

📒 Files selected for processing (10)
  • app/layouts/dashboard.vue
  • layers/nuxi/app/components/agent/AgentChatMessages.vue
  • layers/nuxi/app/components/agent/AgentPanelChat.vue
  • layers/nuxi/app/composables/useAgentChat.ts
  • layers/nuxi/app/composables/useAgentChatSession.ts
  • layers/nuxi/app/composables/useChatVotes.ts
  • layers/nuxi/app/composables/useChats.ts
  • layers/nuxi/app/composables/useStartChat.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue
  • layers/nuxi/app/plugins/chat-view-transitions.client.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • layers/nuxi/app/components/agent/AgentPanelChat.vue
  • layers/nuxi/app/composables/useStartChat.ts
  • layers/nuxi/app/composables/useAgentChatSession.ts
  • layers/nuxi/app/composables/useAgentChat.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue
  • layers/nuxi/app/plugins/chat-view-transitions.client.ts

Comment thread app/layouts/dashboard.vue Outdated

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
layers/nuxi/app/composables/useChatRouteId.ts (2)

4-4: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Regex literal recompiled on every call.

The regex is created fresh on every invocation of resolveChatRouteId. Hoisting it to a module-level constant avoids redundant compilation given this runs on every route change/computed re-evaluation.

♻️ Proposed fix
+const CHAT_ROUTE_PATTERN = /^\/dashboard\/chat\/([^/]+)\/?$/
+
 export function resolveChatRouteId(path: string, param: string | string[] | undefined) {
   if (typeof param === 'string' && param) return param
   if (Array.isArray(param) && param[0]) return param[0]
-  const match = path.match(/^\/dashboard\/chat\/([^/]+)\/?$/)
+  const match = path.match(CHAT_ROUTE_PATTERN)
   return match?.[1] ?? ''
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layers/nuxi/app/composables/useChatRouteId.ts` at line 4, The regex used in
resolveChatRouteId is being recreated on every call, which is unnecessary for a
hot path triggered by route changes. Hoist the /^\/dashboard\/chat\/([^/]+)\/?$/
pattern to a module-level constant in useChatRouteId.ts and have
resolveChatRouteId reuse that shared regex instead of instantiating it inside
the function.

1-6: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Regex fallback is brittle for future /dashboard/chat child routes

resolveChatRouteId() works with the current /dashboard/chat and /dashboard/chat/[id] pages, but any future static child like /dashboard/chat/new would be treated as an id. If more routes are added here, prefer deriving the id from the [id] page/context instead of parsing route.path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layers/nuxi/app/composables/useChatRouteId.ts` around lines 1 - 6, The
fallback in resolveChatRouteId is parsing route.path with a regex, which can
misclassify future static /dashboard/chat child routes as an id. Update
resolveChatRouteId to prefer the route param/context for the [id] page and only
use path parsing as a last resort, or remove the regex fallback if the caller
can pass the route param reliably. Keep the fix localized to resolveChatRouteId
and the code that supplies its param/path inputs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@layers/nuxi/app/composables/useChatRouteId.ts`:
- Line 4: The regex used in resolveChatRouteId is being recreated on every call,
which is unnecessary for a hot path triggered by route changes. Hoist the
/^\/dashboard\/chat\/([^/]+)\/?$/ pattern to a module-level constant in
useChatRouteId.ts and have resolveChatRouteId reuse that shared regex instead of
instantiating it inside the function.
- Around line 1-6: The fallback in resolveChatRouteId is parsing route.path with
a regex, which can misclassify future static /dashboard/chat child routes as an
id. Update resolveChatRouteId to prefer the route param/context for the [id]
page and only use path parsing as a last resort, or remove the regex fallback if
the caller can pass the route param reliably. Keep the fix localized to
resolveChatRouteId and the code that supplies its param/path inputs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3b00555-59d6-4782-bc44-8dedb39b65aa

📥 Commits

Reviewing files that changed from the base of the PR and between 9284933 and 1b99339.

📒 Files selected for processing (8)
  • app/layouts/dashboard.vue
  • layers/nuxi/app/composables/eve/useEveChat.ts
  • layers/nuxi/app/composables/useAgentChat.ts
  • layers/nuxi/app/composables/useAgentChatSession.ts
  • layers/nuxi/app/composables/useChatDetail.ts
  • layers/nuxi/app/composables/useChatDetailCache.ts
  • layers/nuxi/app/composables/useChatRouteId.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue
🚧 Files skipped from review as they are similar to previous changes (7)
  • app/layouts/dashboard.vue
  • layers/nuxi/app/composables/useChatDetailCache.ts
  • layers/nuxi/app/composables/useChatDetail.ts
  • layers/nuxi/app/composables/eve/useEveChat.ts
  • layers/nuxi/app/composables/useAgentChat.ts
  • layers/nuxi/app/composables/useAgentChatSession.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
layers/nuxi/app/composables/useChatDetail.ts (1)

111-140: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Race condition: stale $fetch response can overwrite data for the current chat.

refresh() captures chatIdValue = id.value at the start but never re-checks it after the await $fetch(...) resolves (or rejects). If id changes while a fetch is in-flight (e.g. the user quickly navigates from chat A to chat B, triggering the watch([id, loggedIn], ...) again), an older, slower response for chat A can still land and overwrite data/status/error after the newer chat B's own fetch — the currently-viewed chat can end up displaying another chat's messages.

🛡️ Suggested fix: guard against out-of-order responses
     try {
-      data.value = await $fetch<ChatDetail>(`/api/chats/${chatIdValue}`)
-      status.value = 'success'
+      const result = await $fetch<ChatDetail>(`/api/chats/${chatIdValue}`)
+      if (id.value !== chatIdValue) return
+      data.value = result
+      status.value = 'success'
     } catch (err) {
+      if (id.value !== chatIdValue) return
       data.value = null
       error.value = err as Error
       status.value = 'error'
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layers/nuxi/app/composables/useChatDetail.ts` around lines 111 - 140, The
refresh() logic in useChatDetail can apply an out-of-date $fetch result after id
changes, so add an out-of-order response guard around the async request. Capture
the current chatIdValue at the start of refresh(), then after await
$fetch<ChatDetail>(`/api/chats/${chatIdValue}`) and inside the catch path,
verify id.value still matches that same chatIdValue before mutating data, error,
or status. If the active id has changed, ignore the stale result so the
watch([id, loggedIn], ...) flow cannot overwrite the currently selected chat.
🧹 Nitpick comments (1)
layers/nuxi/app/composables/useNuxiChat.ts (1)

419-425: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Persistence failure silently drops the user's message.

If persistUserMessage rejects, eveChat.send and agent.onMessageSent() never run. Since onSubmit already cleared input/attachments, the message is lost from the UI and never delivered to the agent, with no user-visible error. Consider handling the failure (e.g., surface a toast and/or still send to Eve, or restore input) rather than letting the rejection abort the flow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@layers/nuxi/app/composables/useNuxiChat.ts` around lines 419 - 425, The
submit flow in useNuxiChat’s onSubmit currently lets a persistUserMessage
rejection abort eveChat.send and agent.onMessageSent, which drops the user’s
message after the input is already cleared. Update the onSubmit path to handle
persistUserMessage failures explicitly: catch the error around
persistUserMessage, surface an error state/toast or restore the draft if needed,
and still decide whether to continue with eveChat.send so the message is not
silently lost. Use the existing onSubmit, persistUserMessage, eveChat.send, and
agent.onMessageSent flow as the place to fix it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@layers/nuxi/app/composables/useChatDetail.ts`:
- Around line 25-32: uiMessagesToRows is generating a fresh timestamp with new
Date().toISOString() whenever createdAt is missing, so repeated use during
useNuxiChat streaming updates changes the same message’s time on every patch.
Update uiMessagesToRows to preserve a stable createdAt for messages without
metadata by reusing an existing timestamp from the current row/cache or by
assigning it once when the message first appears, and keep the value unchanged
on subsequent calls from patchChatDetailCache.
- Around line 34-59: useChatDetail is not bound to the shared Nuxt cache ref, so
updates from seedChatDetailCache and patchChatDetailCache do not propagate to an
active chat view. Update useChatDetail to read directly from
useNuxtData(chatDetailCacheKey(chatId)).data, or watch and mirror that shared
ref, so title/state/messages stay synchronized with the cache; keep the
client-only cache helpers seedChatDetailCache and patchChatDetailCache updating
the same source of truth.

---

Outside diff comments:
In `@layers/nuxi/app/composables/useChatDetail.ts`:
- Around line 111-140: The refresh() logic in useChatDetail can apply an
out-of-date $fetch result after id changes, so add an out-of-order response
guard around the async request. Capture the current chatIdValue at the start of
refresh(), then after await $fetch<ChatDetail>(`/api/chats/${chatIdValue}`) and
inside the catch path, verify id.value still matches that same chatIdValue
before mutating data, error, or status. If the active id has changed, ignore the
stale result so the watch([id, loggedIn], ...) flow cannot overwrite the
currently selected chat.

---

Nitpick comments:
In `@layers/nuxi/app/composables/useNuxiChat.ts`:
- Around line 419-425: The submit flow in useNuxiChat’s onSubmit currently lets
a persistUserMessage rejection abort eveChat.send and agent.onMessageSent, which
drops the user’s message after the input is already cleared. Update the onSubmit
path to handle persistUserMessage failures explicitly: catch the error around
persistUserMessage, surface an error state/toast or restore the draft if needed,
and still decide whether to continue with eveChat.send so the message is not
silently lost. Use the existing onSubmit, persistUserMessage, eveChat.send, and
agent.onMessageSent flow as the place to fix it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2076970d-26c1-4245-9223-2bcae6bbffa5

📥 Commits

Reviewing files that changed from the base of the PR and between 4d6c15f and 2133946.

📒 Files selected for processing (8)
  • layers/nuxi/app/components/agent/AgentPanelChat.vue
  • layers/nuxi/app/composables/useChatDetail.ts
  • layers/nuxi/app/composables/useChatVotes.ts
  • layers/nuxi/app/composables/useChats.ts
  • layers/nuxi/app/composables/useNuxiChat.ts
  • layers/nuxi/app/composables/useStartChat.ts
  • layers/nuxi/app/pages/dashboard/chat/[id].vue
  • nuxt.config.ts
💤 Files with no reviewable changes (1)
  • layers/nuxi/app/composables/useChatVotes.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • nuxt.config.ts
  • layers/nuxi/app/composables/useStartChat.ts
  • layers/nuxi/app/composables/useChats.ts
  • layers/nuxi/app/components/agent/AgentPanelChat.vue
  • layers/nuxi/app/pages/dashboard/chat/[id].vue

Comment thread layers/nuxi/app/composables/useChatDetail.ts Outdated
Comment thread layers/nuxi/app/composables/useChatDetail.ts
Comment thread nuxt.config.ts
sourcemap: true,
experimental: {
extractAsyncDataHandlers: true,
viewTransition: true,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why are we turning off view transitions?

@danielroe

Copy link
Copy Markdown
Member

I mean, I trust you - but what should I be reviewing here? would you mind drafting a description? 🙏

@HugoRCD HugoRCD marked this pull request as draft July 3, 2026 15:11
@HugoRCD

HugoRCD commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

I mean, I trust you - but what should I be reviewing here? would you mind drafting a description? 🙏

I marked it as "ready" just to get some feedback from Code Rabbit, I forgot to change it back to "draft" (and yes, I'll add a description)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants