Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR implements a major UI redesign, replacing the top navigation bar with a collapsible sidebar navigation system. It includes new database seeding tooling, API routes for chat listing with pagination, reorganized settings pages, removed legacy navigation components, and updated styling/theming tokens. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
4bf4405 to
d4cd1c5
Compare
This comment has been minimized.
This comment has been minimized.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (11)
packages/web/src/app/onboard/page.tsx (1)
312-318: Remove unnecessary attributes from the mailto link.The
target="_blank"andrel="noopener"attributes are intended for external HTTP links that open in new browser tabs. Formailto:links, these attributes have no effect since email clients handle the protocol directly. Consider removing them for cleaner code.♻️ Proposed cleanup
<a href="mailto:team@sourcebot.dev" className="text-primary hover:underline font-medium transition-colors" - target="_blank" - rel="noopener" > reach out </a>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/onboard/page.tsx` around lines 312 - 318, The mailto anchor in packages/web/src/app/onboard/page.tsx (the <a> element with href="mailto:team@sourcebot.dev" and className="text-primary hover:underline font-medium transition-colors") includes unnecessary target="_blank" and rel="noopener" attributes; remove those two attributes from that anchor so the mailto link is clean and only relies on href and className.packages/web/src/app/(app)/repos/layout.tsx (1)
1-17: MovegetReposStats()call from layout to specific page or API route.This layout fetches repo statistics but never uses the value—only checks for errors. This blocks all routes under
/reposunnecessarily. If stats are needed, fetch them in the page that consumes them or use an API route with client-side caching (react-query) instead.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/repos/layout.tsx around lines 1 - 17, The Layout component is calling getReposStats and only using isServiceError to potentially throw ServiceErrorException, which blocks all /repos child routes; remove the await getReposStats() call and the associated imports (getReposStats, isServiceError, ServiceErrorException) from the Layout function and instead fetch repo stats where they are actually consumed—either inside the specific page component that needs repoStats or via a new API route that the client can call and cache with react-query; if you need to preserve the same error behavior, perform the isServiceError check and throw ServiceErrorException in the page or API handler that performs the fetch.packages/db/tools/scriptRunner.ts (1)
10-10: Use camelCase for the new script filename/import.Line 10 introduces
inject-chat-data, which conflicts with the TS filename convention in this repo. Please rename toinjectChatData.tsand update this import.Proposed fix
-import { injectChatData } from "./scripts/inject-chat-data"; +import { injectChatData } from "./scripts/injectChatData";As per coding guidelines,
**/*.{ts,tsx,js,jsx}: Files should use camelCase starting with a lowercase letter (e.g., shareChatPopover.tsx, userAvatar.tsx, apiClient.ts).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/db/tools/scriptRunner.ts` at line 10, The import uses a kebab-case filename ("./scripts/inject-chat-data") which violates the repo's TS filename convention; rename the script file to camelCase (injectChatData.ts) and update the import in scriptRunner.ts to import { injectChatData } from "./scripts/injectChatData"; ensure any exports inside the file remain named injectChatData so references resolve.packages/db/tools/scripts/inject-chat-data.ts (1)
73-82: Make chat injection atomic to avoid partial writes.If one create fails, earlier inserts remain committed. Wrap the batch in a transaction.
Proposed refactor
- for (const name of chatNames) { - await prisma.chat.create({ - data: { - name, - orgId, - createdById: user.id, - messages: [], - } - }); - } + await prisma.$transaction( + chatNames.map((name) => + prisma.chat.create({ + data: { + name, + orgId, + createdById: user.id, + messages: [], + }, + }) + ) + );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/db/tools/scripts/inject-chat-data.ts` around lines 73 - 82, The loop that creates chats using prisma.chat.create over chatNames should be wrapped in a single transaction so partial inserts can't be committed on failure; replace the per-iteration creates with a single transactional operation (use prisma.$transaction or a createMany within prisma.$transaction) that performs all inserts for chatNames with the same orgId and createdById (user.id) and messages=[], ensuring the operation is atomic and errors roll back all created chat records.packages/web/src/app/(app)/chat/chatLandingPage.tsx (1)
17-31: Avoid the server-side fetch waterfall on first render.These calls are independent and currently serialized, which adds avoidable latency to the landing page.
♻️ Suggested refactor
export async function ChatLandingPage() { - const languageModels = await getConfiguredLanguageModelsInfo(); - const searchContexts = await getSearchContexts(); - const allRepos = await getRepos(); - const session = await auth(); - - const carouselRepos = await getRepos({ - where: { - indexedAt: { - not: null, - }, - }, - take: 10, - }); - - const repoStats = await getReposStats(); + const [ + languageModels, + searchContexts, + allRepos, + session, + carouselRepos, + repoStats, + ] = await Promise.all([ + getConfiguredLanguageModelsInfo(), + getSearchContexts(), + getRepos(), + auth(), + getRepos({ + where: { + indexedAt: { + not: null, + }, + }, + take: 10, + }), + getReposStats(), + ]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/chat/chatLandingPage.tsx around lines 17 - 31, The server-side fetches in chatLandingPage.tsx (calls to getConfiguredLanguageModelsInfo(), getSearchContexts(), getRepos(), auth(), the carousel getRepos(...) and getReposStats()) are currently awaited serially; run the independent calls in parallel using Promise.all (or Promise.allSettled if you want partial results) so that languageModels, searchContexts, allRepos, session, carouselRepos and repoStats are fetched concurrently and then assigned from the resolved results instead of awaiting each call sequentially.packages/web/src/auth.ts (1)
207-211: Consider fire-and-forget for analytics event.Awaiting
captureEventcould add latency to the sign-in flow if the analytics service is slow. Since this is a non-critical analytics event, consider not awaiting it:♻️ Suggested change
if (result.count > 0) { - await captureEvent('wa_anonymous_chats_claimed', { + captureEvent('wa_anonymous_chats_claimed', { claimedCount: result.count, }); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/auth.ts` around lines 207 - 211, The analytics call to captureEvent inside the result.count > 0 branch should be fire-and-forget to avoid adding latency to sign-in: remove the await and invoke captureEvent('wa_anonymous_chats_claimed', { claimedCount: result.count }) as a non-blocking call (e.g., prefix with void or call and attach .catch to swallow/report errors) so the sign-in flow doesn't wait for the analytics service; update the code around the result.count check and captureEvent invocation accordingly.packages/web/src/app/(app)/layout.tsx (1)
176-176: Consider using Tailwind color tokens for border colors.The hardcoded hex values
border-[#e6e6e6] dark:border-[#1d1d1f]could be replaced with Tailwind's semantic color classes (e.g.,border-borderor a custom design token) for better maintainability and theme consistency. As per coding guidelines, prefer Tailwind color classes directly instead of arbitrary value syntax.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/layout.tsx at line 176, The border color uses hardcoded hex classes in the layout div (the element in layout.tsx with className containing "border-[`#e6e6e6`] dark:border-[`#1d1d1f`]"); replace those arbitrary-value tokens with the appropriate Tailwind semantic tokens (for example "border-border" and "dark:border-border-dark" or the project's chosen tokens) to match design system tokens, update the className on that div accordingly, and ensure the new token names exist in the Tailwind theme (add them to theme.extend.colors if needed).packages/web/src/app/(app)/@sidebar/components/defaultSidebar/nav.tsx (1)
80-96: Consider:/chat/*routes don't highlight "Ask" nav item.The
isActivelogic for/chatuses exact match (pathname === "/chat"), so navigating to/chat/[chatId]won't show "Ask" as active. This may be intentional to distinguish the landing page from active chat threads, but worth confirming this is the desired UX.If chat thread routes should highlight "Ask":
♻️ Optional change
if (href === "/chat") { - return pathname === "/chat"; + return pathname === "/chat" || pathname.startsWith("/chat/"); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/@sidebar/components/defaultSidebar/nav.tsx around lines 80 - 96, The isActive function currently treats "/chat" as active only on exact match (pathname === "/chat"), so routes like "/chat/[chatId]" won't highlight Ask; change the "/chat" branch in isActive to use pathname.startsWith("/chat") (or a more specific check such as pathname === "/chat" || pathname.startsWith("/chat/")) so thread routes also mark the Ask nav item active; update the isActive function accordingly (refer to the isActive helper in nav.tsx).packages/web/src/app/(app)/chats/chatsPage.tsx (1)
226-243: Consider increasing debounce delay for search.The 100ms debounce is quite aggressive and will trigger URL updates rapidly as the user types. A more typical debounce of 300-500ms would reduce unnecessary navigation events while still feeling responsive.
♻️ Suggested change
useEffect(() => { const timer = setTimeout(() => { const params = new URLSearchParams(searchParams.toString()); if (searchValue) { params.set("query", searchValue); } else { params.delete("query"); } isOwnUpdateRef.current = true; router.replace(`${pathname}?${params.toString()}`); - }, 100); + }, 300); return () => { clearTimeout(timer); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/chats/chatsPage.tsx around lines 226 - 243, The debounce delay inside the useEffect that updates the URL (the setTimeout in the effect watching searchValue) is too short (100ms); increase it to a more typical 300–500ms to avoid rapid router.replace navigations. Update the timer duration in the useEffect where searchValue, searchParams, pathname, isOwnUpdateRef, and router.replace are used—prefer extracting a constant like DEBOUNCE_MS (set to 300 or 400) near the top of the module and use it in the setTimeout/clearTimeout so the delay is easy to tweak.packages/web/src/app/(app)/@sidebar/components/defaultSidebar/index.tsx (1)
40-43: Fetch the owner notification sources in parallel.These calls are independent and they block sidebar render on every owner page load. Running them sequentially adds avoidable latency to a shared layout path.
⚡ Suggested change
- const connectionStats = await getConnectionStats(); - const joinRequests = await getOrgAccountRequests(); + const [connectionStats, joinRequests] = await Promise.all([ + getConnectionStats(), + getOrgAccountRequests(), + ]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/@sidebar/components/defaultSidebar/index.tsx around lines 40 - 43, The two independent async calls getConnectionStats() and getOrgAccountRequests() are awaited sequentially causing added latency; update the logic in defaultSidebar (index.tsx) to run them in parallel using Promise.all and destructure the results (e.g., const [connectionStats, joinRequests] = await Promise.all([getConnectionStats(), getOrgAccountRequests()])), then keep the existing checks for hasConnectionNotification and hasJoinRequestNotification (using isServiceError and the same property checks) so behavior is unchanged but fetches complete concurrently.packages/web/src/app/(app)/@sidebar/components/whatsNewSidebarButton.tsx (1)
159-170: Usecn()for the conditional classes in the news list.These two interpolated class strings are the only style-composition regression in the component. Converting them to
cn()will keep the conditional styling consistent with the rest of the repo.♻️ Suggested cleanup
+import { cn } from "@/lib/utils" - className={`relative rounded-md transition-colors ${item.read ? "opacity-60" : ""} ${index !== newsItemsWithReadState.length - 1 ? "border-b border-border/50" : ""}`} + className={cn( + "relative rounded-md transition-colors", + item.read && "opacity-60", + index !== newsItemsWithReadState.length - 1 && "border-b border-border/50", + )} - <h4 className={`font-medium text-sm leading-tight group-hover:text-primary ${item.read ? "text-muted-foreground" : ""}`}> + <h4 + className={cn( + "font-medium text-sm leading-tight group-hover:text-primary", + item.read && "text-muted-foreground", + )} + >As per coding guidelines, "Use cn() from
@/lib/utilsfor conditional classNames instead of template literal interpolation".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/`(app)/@sidebar/components/whatsNewSidebarButton.tsx around lines 159 - 170, Replace the template-literal conditional classNames with the cn() helper from "@/lib/utils": import cn and update the outer wrapper div (currently using className={`relative ... ${item.read ? "opacity-60" : ""} ${index !== newsItemsWithReadState.length - 1 ? "border-b border-border/50" : ""}`}) and the h4 (currently using className={`font-medium ... ${item.read ? "text-muted-foreground" : ""}`}) to use cn("static classes", { "opacity-60": item.read, "border-b border-border/50": index !== newsItemsWithReadState.length - 1 }, { "text-muted-foreground": item.read }) so the conditional styling for item.read and the last-item border matches the repo convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/db/tools/scripts/inject-chat-data.ts`:
- Around line 53-61: When resolving the target user, currently
prisma.user.findUnique({ where: { id: userIdArg } }) allows selecting a user by
ID regardless of org; change this to scope the lookup to the target org by
querying prisma.user.findFirst({ where: { id: userIdArg, orgs: { some: { orgId }
} } }) (or alternatively keep findUnique but add a subsequent check that
user.orgs contains orgId), and handle the case where no user is found (throw/log
and exit) so chats cannot be created for a user outside the specified org;
update the code that assigns to the variable user and references to userIdArg,
orgId, and prisma accordingly.
In
`@packages/web/src/app/`(app)/@sidebar/components/defaultSidebar/chatHistory.tsx:
- Around line 108-124: The chat actions trigger is only visible on hover which
hides it from keyboard users; update the SidebarMenuAction inside
ChatActionsDropdown to use its built-in showOnHover behavior (e.g., add the
showOnHover prop to SidebarMenuAction) instead of relying solely on the manual
"opacity-0 group-hover/chat:opacity-100" classes so it also becomes visible on
keyboard focus/focus-within; locate the SidebarMenuAction in the
ChatActionsDropdown block and add showOnHover and remove or replace the
opacity-only classes accordingly.
In `@packages/web/src/app/`(app)/chat/chatLandingPage.tsx:
- Around line 84-86: The fixed-width separator (<Separator className="mt-5
w-[700px]" />) can overflow on small screens; replace the hard-coded w-[700px]
with responsive/bounded classes such as using full width with a max width (e.g.
w-full max-w-[700px] or w-full sm:w-[700px]) so the Separator in
chatLandingPage.tsx scales down on small viewports while preserving the intended
max width on larger screens.
In `@packages/web/src/app/`(app)/search/components/searchResultsPage.tsx:
- Line 22: Remove the unused LogIn import from the module import list (the
import statement that currently imports AlertTriangleIcon, BugIcon, FilterIcon,
LogIn, RefreshCwIcon); update the import to only include the icons actually used
(e.g., AlertTriangleIcon, BugIcon, FilterIcon, RefreshCwIcon) so the unused
LogIn symbol is eliminated.
In `@packages/web/src/app/`(app)/settings/apiKeys/apiKeysPage.tsx:
- Around line 271-276: The delete Button inside AlertDialogTrigger is only
revealed on hover, making it inaccessible to keyboard users; update its
visibility classes so it also becomes visible on keyboard focus by adding
focus-visible:opacity-100 and focus:opacity-100 (and optionally
group-focus-within:opacity-100 on the parent 'group') to the Button's className,
ensuring AlertDialogTrigger/Button remain keyboard-focusable (they already are
via AlertDialogTrigger asChild) so tabbing will reveal the control for screen
and keyboard users.
- Around line 114-127: handleDeleteApiKey currently assumes deleteApiKey throws
on failure but deleteApiKey returns a ServiceError for expected failures; change
handleDeleteApiKey to inspect the result of deleteApiKey (check for
instanceOf/shape of ServiceError or a returned error flag) instead of relying on
catch: if the result is a ServiceError, call toast with a destructive error
message using the ServiceError details and do not call router.refresh(); if the
result indicates success, then call router.refresh() and show the "API key
deleted" toast. Ensure you reference deleteApiKey and the ServiceError
type/shape when implementing the check inside handleDeleteApiKey.
In `@packages/web/src/app/`(app)/settings/page.tsx:
- Around line 13-17: Add a defensive guard before using groups[0].items[0].href:
after calling getSidebarNavGroups() and the isServiceError check, verify groups
is a non-empty array and groups[0].items is a non-empty array (e.g. if
(!groups?.length || !groups[0]?.items?.length) { throw new
ServiceErrorException(groups) } or redirect to a safe fallback route) so you
avoid a TypeError when groups or items are empty; update the redirect call to
use the validated location only after these checks.
In `@packages/web/src/app/api/`(server)/chats/route.ts:
- Around line 37-44: The orderBy currently uses a single key [sortBy] which can
be non-unique (e.g., "name" or "updatedAt") and leads to unstable cursor
pagination; update the orderBy object used in the chats route to include a
secondary tiebreaker id with ascending order (i.e., keep orderBy: { [sortBy]:
sortOrder, id: "asc" }) so that queries using cursor/skip produce deterministic,
stable ordering; modify the orderBy construction where variables orderBy,
sortBy, sortOrder, take/limit, and cursor are used in route.ts to add this id
tiebreaker (id always "asc" regardless of sortOrder).
In `@packages/web/src/app/api/`(server)/chats/types.ts:
- Around line 3-8: The limit in listChatsQueryParamsSchema is user-controlled
and can be abused when passed directly into Prisma's findMany({ take: limit + 1
}); add a hard cap (e.g., MAX_LIMIT = 100) so the effective limit is
bounded—either update listChatsQueryParamsSchema to enforce .max(MAX_LIMIT) on
limit or, if you prefer keeping schema flexible, clamp the parsed limit before
calling findMany (use Math.min(parsedLimit, MAX_LIMIT) and then pass that
clamped value into take). Ensure the clamp is applied wherever findMany(...,
take: ...) is used so a client cannot request an arbitrarily large take.
---
Nitpick comments:
In `@packages/db/tools/scriptRunner.ts`:
- Line 10: The import uses a kebab-case filename ("./scripts/inject-chat-data")
which violates the repo's TS filename convention; rename the script file to
camelCase (injectChatData.ts) and update the import in scriptRunner.ts to import
{ injectChatData } from "./scripts/injectChatData"; ensure any exports inside
the file remain named injectChatData so references resolve.
In `@packages/db/tools/scripts/inject-chat-data.ts`:
- Around line 73-82: The loop that creates chats using prisma.chat.create over
chatNames should be wrapped in a single transaction so partial inserts can't be
committed on failure; replace the per-iteration creates with a single
transactional operation (use prisma.$transaction or a createMany within
prisma.$transaction) that performs all inserts for chatNames with the same orgId
and createdById (user.id) and messages=[], ensuring the operation is atomic and
errors roll back all created chat records.
In `@packages/web/src/app/`(app)/@sidebar/components/defaultSidebar/index.tsx:
- Around line 40-43: The two independent async calls getConnectionStats() and
getOrgAccountRequests() are awaited sequentially causing added latency; update
the logic in defaultSidebar (index.tsx) to run them in parallel using
Promise.all and destructure the results (e.g., const [connectionStats,
joinRequests] = await Promise.all([getConnectionStats(),
getOrgAccountRequests()])), then keep the existing checks for
hasConnectionNotification and hasJoinRequestNotification (using isServiceError
and the same property checks) so behavior is unchanged but fetches complete
concurrently.
In `@packages/web/src/app/`(app)/@sidebar/components/defaultSidebar/nav.tsx:
- Around line 80-96: The isActive function currently treats "/chat" as active
only on exact match (pathname === "/chat"), so routes like "/chat/[chatId]"
won't highlight Ask; change the "/chat" branch in isActive to use
pathname.startsWith("/chat") (or a more specific check such as pathname ===
"/chat" || pathname.startsWith("/chat/")) so thread routes also mark the Ask nav
item active; update the isActive function accordingly (refer to the isActive
helper in nav.tsx).
In `@packages/web/src/app/`(app)/@sidebar/components/whatsNewSidebarButton.tsx:
- Around line 159-170: Replace the template-literal conditional classNames with
the cn() helper from "@/lib/utils": import cn and update the outer wrapper div
(currently using className={`relative ... ${item.read ? "opacity-60" : ""}
${index !== newsItemsWithReadState.length - 1 ? "border-b border-border/50" :
""}`}) and the h4 (currently using className={`font-medium ... ${item.read ?
"text-muted-foreground" : ""}`}) to use cn("static classes", { "opacity-60":
item.read, "border-b border-border/50": index !== newsItemsWithReadState.length
- 1 }, { "text-muted-foreground": item.read }) so the conditional styling for
item.read and the last-item border matches the repo convention.
In `@packages/web/src/app/`(app)/chat/chatLandingPage.tsx:
- Around line 17-31: The server-side fetches in chatLandingPage.tsx (calls to
getConfiguredLanguageModelsInfo(), getSearchContexts(), getRepos(), auth(), the
carousel getRepos(...) and getReposStats()) are currently awaited serially; run
the independent calls in parallel using Promise.all (or Promise.allSettled if
you want partial results) so that languageModels, searchContexts, allRepos,
session, carouselRepos and repoStats are fetched concurrently and then assigned
from the resolved results instead of awaiting each call sequentially.
In `@packages/web/src/app/`(app)/chats/chatsPage.tsx:
- Around line 226-243: The debounce delay inside the useEffect that updates the
URL (the setTimeout in the effect watching searchValue) is too short (100ms);
increase it to a more typical 300–500ms to avoid rapid router.replace
navigations. Update the timer duration in the useEffect where searchValue,
searchParams, pathname, isOwnUpdateRef, and router.replace are used—prefer
extracting a constant like DEBOUNCE_MS (set to 300 or 400) near the top of the
module and use it in the setTimeout/clearTimeout so the delay is easy to tweak.
In `@packages/web/src/app/`(app)/layout.tsx:
- Line 176: The border color uses hardcoded hex classes in the layout div (the
element in layout.tsx with className containing "border-[`#e6e6e6`]
dark:border-[`#1d1d1f`]"); replace those arbitrary-value tokens with the
appropriate Tailwind semantic tokens (for example "border-border" and
"dark:border-border-dark" or the project's chosen tokens) to match design system
tokens, update the className on that div accordingly, and ensure the new token
names exist in the Tailwind theme (add them to theme.extend.colors if needed).
In `@packages/web/src/app/`(app)/repos/layout.tsx:
- Around line 1-17: The Layout component is calling getReposStats and only using
isServiceError to potentially throw ServiceErrorException, which blocks all
/repos child routes; remove the await getReposStats() call and the associated
imports (getReposStats, isServiceError, ServiceErrorException) from the Layout
function and instead fetch repo stats where they are actually consumed—either
inside the specific page component that needs repoStats or via a new API route
that the client can call and cache with react-query; if you need to preserve the
same error behavior, perform the isServiceError check and throw
ServiceErrorException in the page or API handler that performs the fetch.
In `@packages/web/src/app/onboard/page.tsx`:
- Around line 312-318: The mailto anchor in
packages/web/src/app/onboard/page.tsx (the <a> element with
href="mailto:team@sourcebot.dev" and className="text-primary hover:underline
font-medium transition-colors") includes unnecessary target="_blank" and
rel="noopener" attributes; remove those two attributes from that anchor so the
mailto link is clean and only relies on href and className.
In `@packages/web/src/auth.ts`:
- Around line 207-211: The analytics call to captureEvent inside the
result.count > 0 branch should be fire-and-forget to avoid adding latency to
sign-in: remove the await and invoke captureEvent('wa_anonymous_chats_claimed',
{ claimedCount: result.count }) as a non-blocking call (e.g., prefix with void
or call and attach .catch to swallow/report errors) so the sign-in flow doesn't
wait for the analytics service; update the code around the result.count check
and captureEvent invocation accordingly.
🪄 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: 6f35e5b0-9134-4283-b6ff-f6ca2fed3e90
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (73)
CHANGELOG.mdCLAUDE.mdpackages/db/tools/scriptRunner.tspackages/db/tools/scripts/inject-chat-data.tspackages/web/package.jsonpackages/web/src/app/(app)/@sidebar/(routes)/(default)/[...slug]/page.tsxpackages/web/src/app/(app)/@sidebar/(routes)/(default)/page.tsxpackages/web/src/app/(app)/@sidebar/(routes)/settings/[...slug]/page.tsxpackages/web/src/app/(app)/@sidebar/(routes)/settings/page.tsxpackages/web/src/app/(app)/@sidebar/components/defaultSidebar/chatHistory.tsxpackages/web/src/app/(app)/@sidebar/components/defaultSidebar/index.tsxpackages/web/src/app/(app)/@sidebar/components/defaultSidebar/nav.tsxpackages/web/src/app/(app)/@sidebar/components/settingsSidebar/index.tsxpackages/web/src/app/(app)/@sidebar/components/settingsSidebar/nav.tsxpackages/web/src/app/(app)/@sidebar/components/sidebarBase.tsxpackages/web/src/app/(app)/@sidebar/components/whatsNewSidebarButton.tsxpackages/web/src/app/(app)/agents/page.tsxpackages/web/src/app/(app)/browse/components/bottomPanel.tsxpackages/web/src/app/(app)/browse/layout.tsxpackages/web/src/app/(app)/browse/layoutClient.tsxpackages/web/src/app/(app)/chat/[id]/components/chatThreadPanel.tsxpackages/web/src/app/(app)/chat/[id]/page.tsxpackages/web/src/app/(app)/chat/chatLandingPage.tsxpackages/web/src/app/(app)/chat/components/chatActionsDropdown.tsxpackages/web/src/app/(app)/chat/components/chatSidePanel.tsxpackages/web/src/app/(app)/chat/page.tsxpackages/web/src/app/(app)/chats/chatsPage.tsxpackages/web/src/app/(app)/chats/page.tsxpackages/web/src/app/(app)/components/appearanceDropdownMenu.tsxpackages/web/src/app/(app)/components/appearanceDropdownMenuGroup.tsxpackages/web/src/app/(app)/components/meControlDropdownMenu.tsxpackages/web/src/app/(app)/components/navigationMenu/index.tsxpackages/web/src/app/(app)/components/navigationMenu/navigationItems.tsxpackages/web/src/app/(app)/components/navigationMenu/progressIndicator.tsxpackages/web/src/app/(app)/components/notFound.tsxpackages/web/src/app/(app)/components/pageNotFound.tsxpackages/web/src/app/(app)/components/topBar.tsxpackages/web/src/app/(app)/components/whatsNewIndicator.tsxpackages/web/src/app/(app)/layout.tsxpackages/web/src/app/(app)/page.tsxpackages/web/src/app/(app)/repos/layout.tsxpackages/web/src/app/(app)/search/components/searchLandingPage.tsxpackages/web/src/app/(app)/search/components/searchResultsPage.tsxpackages/web/src/app/(app)/settings/apiKeys/apiKeysPage.tsxpackages/web/src/app/(app)/settings/apiKeys/columns.tsxpackages/web/src/app/(app)/settings/apiKeys/page.tsxpackages/web/src/app/(app)/settings/components/settingsCard.tsxpackages/web/src/app/(app)/settings/components/sidebar-nav.tsxpackages/web/src/app/(app)/settings/general/generalPage.tsxpackages/web/src/app/(app)/settings/general/page.tsxpackages/web/src/app/(app)/settings/layout.tsxpackages/web/src/app/(app)/settings/linked-accounts/page.tsxpackages/web/src/app/(app)/settings/page.tsxpackages/web/src/app/api/(client)/client.tspackages/web/src/app/api/(server)/chats/route.tspackages/web/src/app/api/(server)/chats/types.tspackages/web/src/app/globals.csspackages/web/src/app/not-found.tsxpackages/web/src/app/onboard/page.tsxpackages/web/src/auth.tspackages/web/src/components/ui/data-table.tsxpackages/web/src/components/ui/sidebar.tsxpackages/web/src/components/ui/table.tsxpackages/web/src/components/ui/tooltip.tsxpackages/web/src/ee/features/analytics/analyticsContent.tsxpackages/web/src/ee/features/analytics/analyticsEntitlementMessage.tsxpackages/web/src/ee/features/sso/components/connectAccountsCard.tsxpackages/web/src/ee/features/sso/components/linkedAccountProviderCard.tsxpackages/web/src/features/chat/actions.tspackages/web/src/hooks/use-mobile.tsxpackages/web/src/hooks/useHomeView.tspackages/web/src/lib/constants.tspackages/web/tailwind.config.ts
💤 Files with no reviewable changes (16)
- packages/web/src/app/(app)/components/pageNotFound.tsx
- packages/web/src/app/(app)/components/appearanceDropdownMenu.tsx
- packages/web/src/app/(app)/components/notFound.tsx
- packages/web/src/app/(app)/components/meControlDropdownMenu.tsx
- packages/web/src/app/(app)/agents/page.tsx
- packages/web/src/app/(app)/components/appearanceDropdownMenuGroup.tsx
- packages/web/src/features/chat/actions.ts
- packages/web/src/app/(app)/components/navigationMenu/index.tsx
- packages/web/src/app/(app)/components/navigationMenu/progressIndicator.tsx
- packages/web/src/app/(app)/chat/components/chatSidePanel.tsx
- packages/web/src/app/(app)/components/navigationMenu/navigationItems.tsx
- packages/web/src/components/ui/data-table.tsx
- packages/web/src/app/(app)/components/topBar.tsx
- packages/web/src/app/(app)/settings/components/sidebar-nav.tsx
- packages/web/src/app/(app)/components/whatsNewIndicator.tsx
- packages/web/src/app/(app)/settings/apiKeys/columns.tsx
Permission sync banner:

Summary by CodeRabbit
Release Notes
New Features
Bug Fixes & Improvements
Documentation