Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughReplaces the legacy search context with a split Orama-based search engine and UI, adds a ToolRegistry with factory-based tools, rewires transport to consume the registry and changes model selection, refactors chat message UI into shared primitives, and updates app layout to mount new providers and register tools. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant UI as Chat UI
participant TR as ToolRegistry
participant TT as CustomChatTransport
participant LLM as Model
participant SE as Search Engine
rect rgba(200,230,255,0.20)
note over UI,TR: App mount
UI->>TR: ToolRegistryProvider mounts
UI->>TR: register("search_sessions", toolFactory({ search: SE.search }))
end
User->>UI: Send message
UI->>TT: instantiate CustomChatTransport(TR)
UI->>TT: streamText({ tools: TR.getForTransport() })
TT->>LLM: start chat with model + tools
alt model invokes tool
LLM->>TT: tool_call("search_sessions", params)
TT->>TR: invoke("search_sessions", params)
TR->>SE: search(query, filters)
SE-->>TR: hits
TR-->>TT: tool result { results: [...] }
TT-->>LLM: relay tool result
end
LLM-->>UI: assistant response stream
sequenceDiagram
autonumber
participant Layout as App Layout
participant SEP as SearchEngineProvider
participant Store as PersistedStore
participant Orama as Orama Index
participant Listeners as Row Listeners
participant SUI as SearchUIProvider
participant UI as Consumer
rect rgba(230,255,230,0.20)
Layout->>SEP: mount with store
SEP->>Orama: create index (schema, plugins)
SEP->>Store: subscribe sessions/humans/orgs
Store-->>Listeners: row add/update/remove
Listeners->>Orama: insert/update/remove docs
end
UI->>SUI: set query/filters
SUI->>SEP: search(query, filters)
SEP->>Orama: search(normalized, filters)
Orama-->>SEP: hits
SEP-->>SUI: hits
SUI-->>UI: grouped/highlighted results
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (14)
apps/desktop2/src/components/chat/message/tool/search.tsx (2)
52-58: Consider making the empty state more actionable.The "No results found" message is clear but lacks guidance for the user. Consider adding helpful text such as suggestions to refine the search query or links to documentation.
Apply this diff to enhance the empty state:
if (!results || results.length === 0) { return ( - <div className="text-xs text-muted-foreground flex justify-center items-center py-2"> - No results found + <div className="text-xs text-muted-foreground flex flex-col justify-center items-center py-2 gap-1"> + <span>No results found</span> + <span className="text-[10px]">Try refining your search query</span> </div> ); }
67-68: Replaceanyon search results with a concrete type
Theresults.map((result: any, …)callback weakens type safety. Define an interface matching your result shape (e.g.{ id: string; title?: string; /* … */ }) and replaceanywith that type.apps/desktop2/src/chat/tools.ts (4)
3-5: Consider stricter typing for search results.The
searchfunction returnsPromise<any[]>, which loses type safety. Consider defining an explicit result type (e.g.,SearchHitwithdocument,score, etc.) to improve type checking and IDE support.Define a result type before the interface:
+interface SearchHit { + document: { + id: string; + title: string; + content: string; + created_at: string; + }; + score: number; +} + export interface ToolDependencies { - search: (query: string, filters?: Record<string, any>) => Promise<any[]>; + search: (query: string, filters?: Record<string, any>) => Promise<SearchHit[]>; }
19-19: Magic number: Consider making content truncation configurable.The content is truncated to 500 characters. This might be too short or too long depending on the use case. Consider making this a configurable parameter in
ToolDependenciesor as a constant.Extract to a constant:
+const MAX_RESULT_CONTENT_LENGTH = 500; + export const toolFactories = { search_sessions: (deps: ToolDependencies) => ({ description: "Search for sessions (meeting notes) using keywords. Returns relevant sessions with their content.", parameters: z.object({ query: z.string().describe("The search query to find relevant sessions"), }), execute: async (params: { query: string }) => { const hits = await deps.search(params.query); const results = hits.slice(0, 10).map((hit: any) => ({ id: hit.document.id, title: hit.document.title, - content: hit.document.content.slice(0, 500), + content: hit.document.content.slice(0, MAX_RESULT_CONTENT_LENGTH), score: hit.score, created_at: hit.document.created_at, }));
16-16: Magic number: Consider making result limit configurable.The results are hard-limited to 10 items. This might not suit all use cases. Consider making this configurable via parameters or a constant.
Add a configurable limit:
+const DEFAULT_RESULT_LIMIT = 10; + export const toolFactories = { search_sessions: (deps: ToolDependencies) => ({ description: "Search for sessions (meeting notes) using keywords. Returns relevant sessions with their content.", parameters: z.object({ query: z.string().describe("The search query to find relevant sessions"), + limit: z.number().optional().describe("Maximum number of results to return (default: 10)"), }), - execute: async (params: { query: string }) => { + execute: async (params: { query: string; limit?: number }) => { const hits = await deps.search(params.query); - const results = hits.slice(0, 10).map((hit: any) => ({ + const results = hits.slice(0, params.limit ?? DEFAULT_RESULT_LIMIT).map((hit: any) => ({
14-22: Use compile-time types for search results
- Define a
SearchHitinterface matching{ document: { id, title, content, created_at } }.- Replace
hit: any(and updatedeps.searchreturn type toSearchHit[]) so TypeScript enforces the structure and prevents runtime errors if the API shape changes.apps/desktop2/src/chat/transport.ts (1)
8-8: Consider externalizing model selection to config.Make modelName configurable (env/user settings) to avoid code changes for model swaps.
apps/desktop2/src/routes/app/main/_layout.tsx (1)
56-63: Add missing dependencies to useEffect to avoid stale closures.Include persistedStore, internalStore, and openNew.
Apply this diff:
- useEffect(() => { + useEffect(() => { if (!currentTab) { const user_id = internalStore?.getValue("user_id"); const sessionId = id(); persistedStore?.setRow("sessions", sessionId, { user_id, created_at: new Date().toISOString() }); openNew({ id: sessionId, type: "sessions", active: true, state: { editor: "raw" } }); } - }, [currentTab]); + }, [currentTab, internalStore, persistedStore, openNew]);apps/desktop2/src/contexts/tool.tsx (1)
17-18: Import ReactNode type instead of using React.ReactNode.Avoid reliance on the React namespace.
Apply this diff:
-import { createContext, useCallback, useContext, useMemo, useRef } from "react"; +import { createContext, useCallback, useContext, useMemo, useRef } from "react"; +import type { ReactNode } from "react"; @@ -export function ToolRegistryProvider({ children }: { children: React.ReactNode }) { +export function ToolRegistryProvider({ children }: { children: ReactNode }) {apps/desktop2/src/contexts/search/ui.tsx (2)
184-185: Import ReactNode type for provider props.Avoid React namespace reference.
-import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; +import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; +import type { ReactNode } from "react"; @@ -export function SearchUIProvider({ children }: { children: React.ReactNode }) { +export function SearchUIProvider({ children }: { children: ReactNode }) {
99-103: Optional: reuse a single highlighter per query for perf.Instantiate Highlight once per group instead of per hit.
Example approach: create one Highlight in groupSearchResults and pass it into createSearchResult.
apps/desktop2/src/contexts/search/engine.tsx (3)
153-159: Rename helper to avoid shadowing global "toString".This triggers linters and can confuse readers.
Apply this diff:
-function toString(value: unknown): string { +function toNonEmptyString(value: unknown): string { if (typeof value === "string" && value.length > 0) { return value; } return ""; } @@ - folder_id: toString(row.folder_id), - event_id: toString(row.event_id), + folder_id: toNonEmptyString(row.folder_id), + event_id: toNonEmptyString(row.event_id), @@ - folder_id: toString(row.folder_id), - event_id: toString(row.event_id), + folder_id: toNonEmptyString(row.folder_id), + event_id: toNonEmptyString(row.event_id), @@ - org_id: toString(row.org_id), + org_id: toNonEmptyString(row.org_id), @@ - org_id: toString(row.org_id), + org_id: toNonEmptyString(row.org_id),Also applies to: 181-195, 189-191, 351-352, 221-223, 393-394
283-284: Import ReactNode type for provider props.Avoid React namespace reference.
-import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; +import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react"; +import type { ReactNode } from "react"; @@ -export function SearchEngineProvider({ children, persistedStore }: { children: React.ReactNode; persistedStore: any }) { +export function SearchEngineProvider({ children, persistedStore }: { children: ReactNode; persistedStore: any }) {
293-318: Initial indexing may not complete before isIndexing=false.insert/update/remove are async. Consider awaiting initial inserts before flipping isIndexing to avoid empty/partial results on first search.
Based on learnings
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
apps/desktop2/src/chat/tools.ts(1 hunks)apps/desktop2/src/chat/transport.ts(2 hunks)apps/desktop2/src/components/chat/message/tool/search.tsx(3 hunks)apps/desktop2/src/components/chat/session.tsx(2 hunks)apps/desktop2/src/components/main/body/search.tsx(1 hunks)apps/desktop2/src/components/main/sidebar/index.tsx(1 hunks)apps/desktop2/src/components/main/sidebar/search/group.tsx(1 hunks)apps/desktop2/src/components/main/sidebar/search/index.tsx(1 hunks)apps/desktop2/src/components/main/sidebar/search/item.tsx(1 hunks)apps/desktop2/src/contexts/search/engine.tsx(1 hunks)apps/desktop2/src/contexts/search/index.tsx(0 hunks)apps/desktop2/src/contexts/search/ui.tsx(1 hunks)apps/desktop2/src/contexts/tool.tsx(1 hunks)apps/desktop2/src/routes/app/main/_layout.tsx(2 hunks)
💤 Files with no reviewable changes (1)
- apps/desktop2/src/contexts/search/index.tsx
🧰 Additional context used
📓 Path-based instructions (2)
apps/desktop2/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)
apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported asimport { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames
Files:
apps/desktop2/src/components/main/sidebar/search/item.tsxapps/desktop2/src/components/main/sidebar/index.tsxapps/desktop2/src/components/main/sidebar/search/group.tsxapps/desktop2/src/contexts/tool.tsxapps/desktop2/src/routes/app/main/_layout.tsxapps/desktop2/src/components/chat/session.tsxapps/desktop2/src/contexts/search/engine.tsxapps/desktop2/src/components/main/body/search.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/components/main/sidebar/search/index.tsxapps/desktop2/src/contexts/search/ui.tsx
**/*.{js,ts,tsx,rs}
⚙️ CodeRabbit configuration file
**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".
Files:
apps/desktop2/src/components/main/sidebar/search/item.tsxapps/desktop2/src/components/main/sidebar/index.tsxapps/desktop2/src/components/main/sidebar/search/group.tsxapps/desktop2/src/chat/transport.tsapps/desktop2/src/contexts/tool.tsxapps/desktop2/src/routes/app/main/_layout.tsxapps/desktop2/src/chat/tools.tsapps/desktop2/src/components/chat/session.tsxapps/desktop2/src/contexts/search/engine.tsxapps/desktop2/src/components/main/body/search.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/components/main/sidebar/search/index.tsxapps/desktop2/src/contexts/search/ui.tsx
🧬 Code graph analysis (6)
apps/desktop2/src/chat/transport.ts (3)
packages/utils/src/ai.ts (1)
ChatTransport(12-12)apps/desktop2/src/chat/types.ts (1)
HyprUIMessage(9-9)apps/desktop2/src/contexts/tool.tsx (1)
ToolRegistry(3-9)
apps/desktop2/src/routes/app/main/_layout.tsx (4)
apps/desktop2/src/contexts/search/engine.tsx (2)
SearchEngineProvider(283-502)useSearchEngine(504-510)apps/desktop2/src/contexts/search/ui.tsx (1)
SearchUIProvider(184-264)apps/desktop2/src/contexts/tool.tsx (2)
ToolRegistryProvider(17-67)useToolRegistry(69-75)apps/desktop2/src/chat/tools.ts (1)
toolFactories(7-27)
apps/desktop2/src/components/chat/session.tsx (2)
apps/desktop2/src/contexts/tool.tsx (1)
useToolRegistry(69-75)apps/desktop2/src/chat/transport.ts (1)
CustomChatTransport(15-57)
apps/desktop2/src/contexts/search/engine.tsx (1)
apps/desktop2/src/contexts/search/ui.tsx (2)
SearchEntityType(7-7)SearchFilters(7-7)
apps/desktop2/src/components/chat/message/tool/search.tsx (3)
apps/desktop2/src/components/chat/message/types.ts (1)
Part(6-6)packages/ui/src/components/ui/carousel.tsx (5)
Carousel(259-259)CarouselContent(259-259)CarouselItem(259-259)CarouselPrevious(259-259)CarouselNext(259-259)packages/ui/src/components/ui/card.tsx (2)
Card(9-23)CardContent(80-93)
apps/desktop2/src/contexts/search/ui.tsx (1)
apps/desktop2/src/contexts/search/engine.tsx (4)
SearchEntityType(6-6)SearchFilters(8-16)SearchHit(31-34)useSearchEngine(504-510)
🪛 Biome (2.1.2)
apps/desktop2/src/contexts/search/engine.tsx
[error] 153-153: Do not shadow the global "toString" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
🪛 Gitleaks (8.28.0)
apps/desktop2/src/chat/transport.ts
[high] 12-12: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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 (macos, macos-14)
- GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (17)
apps/desktop2/src/components/chat/message/tool/search.tsx (3)
3-11: LGTM! Clean imports for carousel-based rendering.The new imports properly support the enhanced UI with card-based carousel rendering for search results, and the persisted store import enables session data fetching.
61-80: Verify carousel navigation button positioning.The carousel navigation buttons use negative positioning (
-left-4,-right-4) which might cause overlap or clipping issues depending on the parent container's overflow settings.Manually test the carousel navigation to ensure:
- Navigation buttons are fully visible and clickable
- No visual clipping or overlap occurs
- Buttons work correctly on different screen sizes (basis-full, sm:basis-1/2, lg:basis-1/3)
91-98: Guard against undefined session in RenderSession
persisted.UI.useRowcan returnundefinedif the row is missing. Update rendering to guard the session itself, e.g.:const title = session?.title ?? "Untitled";or early-return when
!sessionbefore accessingtitle.
apps/desktop2/src/components/chat/message/tool/search.tsx:91-98apps/desktop2/src/components/main/sidebar/search/index.tsx (1)
4-4: LGTM! Import path updated correctly.The import path change from
contexts/searchtocontexts/search/uialigns with the architectural refactor introducing a dedicated Search UI context. No functional changes to the component logic.apps/desktop2/src/components/main/sidebar/search/group.tsx (1)
5-5: LGTM! Import path updated correctly.The import path change aligns with the architectural refactor introducing a UI-focused search context. No functional changes.
apps/desktop2/src/components/main/sidebar/index.tsx (1)
4-4: LGTM! Import path updated correctly.The import path change is consistent with the broader architectural refactor separating UI and engine concerns in the search context.
apps/desktop2/src/components/main/body/search.tsx (1)
6-6: LGTM! Import path updated correctly.The import path change maintains consistency with the search context refactor across all UI components.
apps/desktop2/src/components/main/sidebar/search/item.tsx (1)
5-5: LGTM! Import path updated correctly.The import path change completes the migration of all search UI components to the new
contexts/search/uimodule.apps/desktop2/src/components/chat/session.tsx (2)
30-31: LGTM! Registry integration implemented correctly.The integration with
useToolRegistryenables the dependency-injected tool system. The transport is correctly memoized withregistryas a dependency, ensuring it recreates when the registry changes.
30-31: Transport won’t be recreated unexpectedly. Theregistryobject is memoized over stable callbacks and never changes reference, sotransportwill only be instantiated once.Likely an incorrect or invalid review comment.
apps/desktop2/src/chat/transport.ts (2)
16-16: Good move to DI ToolRegistry.Constructor injection simplifies testing and decouples transport from tool creation.
Confirm all transport instantiations now pass a registry (e.g., components/chat/session.tsx).
28-36: Tools sourced from registry look correct.Passing registry.getForTransport() into streamText aligns with the AI SDK tools API.
apps/desktop2/src/routes/app/main/_layout.tsx (2)
23-31: Provider composition looks solid.Engine → UI → ToolRegistry nesting aligns with dependencies and keeps concerns separated.
36-49: Tool bootstrapping via registry is clean.Registering factories with deps.search on mount is straightforward and extensible.
apps/desktop2/src/contexts/tool.tsx (1)
24-31: getForTransport implementation is fine.Returning a plain object map is compatible with the AI SDK tools shape.
apps/desktop2/src/contexts/search/engine.tsx (1)
299-311: No changes needed for enum schema
Orama v3 supportstype: "enum"without explicit values.apps/desktop2/src/contexts/search/ui.tsx (1)
99-111: .HTML property usage is correct Highlight.highlight returns an object with a capitalized HTML property.
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (2)
apps/desktop2/src/contexts/search/engine/utils.ts (1)
19-50: LGTM, but consider renamingtoString.The type conversion utilities are well-implemented with proper type guards and fallback values. However, the
toStringfunction name shadows the globalObject.prototype.toStringproperty, which could cause confusion.Based on static analysis hints. Consider renaming to avoid shadowing:
-export function toString(value: unknown): string { +export function toStringValue(value: unknown): string { if (typeof value === "string" && value.length > 0) { return value; } return ""; }If you apply this change, update the imports in
indexing.tsandlisteners.tsaccordingly.apps/desktop2/src/contexts/search/engine/index.tsx (1)
108-108: Type assertion relies on schema correctness.The cast to
SearchHit[]assumes Orama's search results match the expected shape. While the schema should enforce this, consider adding a runtime type guard if Orama's types might change or if additional validation is needed for robustness.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
apps/desktop2/src/chat/tools.ts(1 hunks)apps/desktop2/src/components/chat/body.tsx(2 hunks)apps/desktop2/src/components/chat/message/error.tsx(1 hunks)apps/desktop2/src/components/chat/message/loading.tsx(1 hunks)apps/desktop2/src/components/chat/message/normal.tsx(2 hunks)apps/desktop2/src/components/chat/message/shared.tsx(1 hunks)apps/desktop2/src/components/chat/message/tool/search.tsx(3 hunks)apps/desktop2/src/contexts/search/engine/content.ts(1 hunks)apps/desktop2/src/contexts/search/engine/filters.ts(1 hunks)apps/desktop2/src/contexts/search/engine/index.tsx(1 hunks)apps/desktop2/src/contexts/search/engine/indexing.ts(1 hunks)apps/desktop2/src/contexts/search/engine/listeners.ts(1 hunks)apps/desktop2/src/contexts/search/engine/types.ts(1 hunks)apps/desktop2/src/contexts/search/engine/utils.ts(1 hunks)apps/desktop2/src/routes/app/main/_layout.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
apps/desktop2/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)
apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported asimport { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames
Files:
apps/desktop2/src/components/chat/message/loading.tsxapps/desktop2/src/components/chat/message/shared.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/components/chat/message/normal.tsxapps/desktop2/src/components/chat/body.tsxapps/desktop2/src/components/chat/message/error.tsxapps/desktop2/src/contexts/search/engine/index.tsxapps/desktop2/src/routes/app/main/_layout.tsx
**/*.{js,ts,tsx,rs}
⚙️ CodeRabbit configuration file
**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".
Files:
apps/desktop2/src/components/chat/message/loading.tsxapps/desktop2/src/contexts/search/engine/filters.tsapps/desktop2/src/components/chat/message/shared.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/contexts/search/engine/content.tsapps/desktop2/src/contexts/search/engine/utils.tsapps/desktop2/src/chat/tools.tsapps/desktop2/src/components/chat/message/normal.tsxapps/desktop2/src/components/chat/body.tsxapps/desktop2/src/contexts/search/engine/listeners.tsapps/desktop2/src/components/chat/message/error.tsxapps/desktop2/src/contexts/search/engine/indexing.tsapps/desktop2/src/contexts/search/engine/index.tsxapps/desktop2/src/routes/app/main/_layout.tsxapps/desktop2/src/contexts/search/engine/types.ts
🧬 Code graph analysis (15)
apps/desktop2/src/components/chat/message/loading.tsx (1)
apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)
apps/desktop2/src/contexts/search/engine/filters.ts (2)
apps/desktop2/src/contexts/search/engine/types.ts (1)
SearchFilters(39-39)apps/desktop2/src/contexts/search/index.tsx (1)
buildOramaFilters(316-342)
apps/desktop2/src/components/chat/message/shared.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
apps/desktop2/src/components/chat/message/tool/search.tsx (3)
apps/desktop2/src/components/chat/message/types.ts (1)
Part(6-6)packages/ui/src/components/ui/card.tsx (2)
Card(9-23)CardContent(80-93)apps/desktop2/src/store/zustand/tabs.ts (1)
useTabs(31-121)
apps/desktop2/src/contexts/search/engine/content.ts (1)
apps/desktop2/src/contexts/search/engine/utils.ts (2)
mergeContent(52-57)flattenTranscript(59-101)
apps/desktop2/src/contexts/search/engine/utils.ts (1)
crates/db-script/src/lib.rs (1)
transcript(10-21)
apps/desktop2/src/chat/tools.ts (1)
apps/desktop2/src/contexts/search/engine/types.ts (3)
SearchFilters(39-39)SearchHit(41-44)searchFiltersSchema(35-37)
apps/desktop2/src/components/chat/message/normal.tsx (3)
apps/desktop2/src/chat/types.ts (1)
HyprUIMessage(9-9)apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)apps/desktop2/src/components/chat/message/types.ts (1)
Part(6-6)
apps/desktop2/src/components/chat/body.tsx (1)
apps/desktop2/src/components/chat/message/normal.tsx (1)
NormalMessage(12-48)
apps/desktop2/src/contexts/search/engine/listeners.ts (3)
apps/desktop2/src/contexts/search/engine/types.ts (1)
Index(25-25)apps/desktop2/src/contexts/search/engine/utils.ts (5)
collectCells(103-113)toTrimmedString(19-25)toNumber(27-36)toString(38-43)toBoolean(45-50)apps/desktop2/src/contexts/search/engine/content.ts (2)
createSessionSearchableContent(3-9)createHumanSearchableContent(11-13)
apps/desktop2/src/components/chat/message/error.tsx (1)
apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)
apps/desktop2/src/contexts/search/engine/indexing.ts (4)
apps/desktop2/src/contexts/search/engine/types.ts (1)
Index(25-25)apps/desktop2/src/contexts/search/engine/utils.ts (3)
collectCells(103-113)toTrimmedString(19-25)toNumber(27-36)apps/desktop2/src/contexts/search/engine/content.ts (2)
createSessionSearchableContent(3-9)createHumanSearchableContent(11-13)apps/desktop2/src/contexts/search/index.tsx (1)
indexSessions(230-259)
apps/desktop2/src/contexts/search/engine/index.tsx (5)
apps/desktop2/src/contexts/search/engine/types.ts (4)
SearchFilters(39-39)SearchHit(41-44)Index(25-25)SEARCH_SCHEMA(17-23)apps/desktop2/src/contexts/search/engine/indexing.ts (3)
indexSessions(7-31)indexHumans(33-56)indexOrganizations(58-73)apps/desktop2/src/contexts/search/engine/listeners.ts (3)
createSessionListener(9-47)createHumanListener(49-89)createOrganizationListener(91-120)apps/desktop2/src/contexts/search/engine/utils.ts (1)
normalizeQuery(15-17)apps/desktop2/src/contexts/search/engine/filters.ts (1)
buildOramaFilters(3-29)
apps/desktop2/src/routes/app/main/_layout.tsx (5)
apps/desktop2/src/contexts/shell/index.tsx (1)
ShellProvider(13-22)apps/desktop2/src/contexts/search/engine/index.tsx (2)
SearchEngineProvider(23-123)useSearchEngine(125-131)apps/desktop2/src/contexts/search/ui.tsx (1)
SearchUIProvider(184-264)apps/desktop2/src/contexts/tool.tsx (2)
ToolRegistryProvider(17-67)useToolRegistry(69-75)apps/desktop2/src/chat/tools.ts (1)
toolFactories(10-34)
apps/desktop2/src/contexts/search/engine/types.ts (1)
apps/desktop2/src/contexts/search/engine/index.tsx (3)
SearchEntityType(14-14)SearchFilters(14-14)SearchHit(14-14)
🪛 Biome (2.1.2)
apps/desktop2/src/contexts/search/engine/utils.ts
[error] 38-38: Do not shadow the global "toString" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
apps/desktop2/src/contexts/search/engine/listeners.ts
[error] 7-7: Do not shadow the global "toString" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
⏰ 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). (1)
- GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (19)
apps/desktop2/src/components/chat/body.tsx (1)
2-2: LGTM! Clean refactor to modular message components.The changes improve modularity by extracting message rendering into dedicated components (ErrorMessage, LoadingMessage, NormalMessage) while preserving all existing functionality, including the handleReload logic.
Also applies to: 8-10, 100-104
apps/desktop2/src/components/chat/message/error.tsx (1)
1-21: LGTM! Clean error message component.The implementation correctly uses shared UI primitives and properly handles the optional retry action with appropriate styling.
apps/desktop2/src/components/chat/message/loading.tsx (1)
1-24: LGTM! Clean loading message component.The implementation correctly uses shared UI primitives and provides appropriate visual feedback with the animated loader. The optional cancel-and-retry action is properly handled.
apps/desktop2/src/components/chat/message/shared.tsx (1)
6-83: LGTM! Well-structured shared UI primitives.The implementation provides clean, reusable building blocks for message rendering with:
- Proper composition via MessageContainer, MessageBubble, and ActionButton
- Correct positioning dependencies (ActionButton's absolute positioning works with MessageBubble's relative group)
- Good accessibility (aria-labels on ActionButton)
- Clean variant handling with appropriate styling for each message type
The cn usage follows coding guidelines with arrays split by logical grouping.
apps/desktop2/src/components/chat/message/normal.tsx (1)
8-8: LGTM! Clean migration to shared UI primitives.The component successfully adopts the shared building blocks while preserving all functionality, including role-based styling, timestamp display, and the reload action. The transition from raw markup to composed primitives improves consistency across message types.
Also applies to: 12-12, 24-47
apps/desktop2/src/chat/tools.ts (3)
6-8: LGTM!The
ToolDependenciesinterface provides a clean abstraction for dependency injection, enabling testability and flexibility in tool provisioning.
10-34: LGTM!The factory-based approach with dependency injection is well-structured. The tool properly handles optional filters, limits results to 5 items, and truncates content to 500 characters to prevent excessive response sizes.
36-41: LGTM!The
Toolstype correctly derives input/output types from the factory pattern, maintaining type safety throughout the tool execution flow.apps/desktop2/src/contexts/search/engine/listeners.ts (3)
9-47: LGTM!The session listener properly handles both row removal and updates. The error handling with try/catch and console logging is appropriate for keeping the index in sync with the persisted store.
49-89: LGTM!The human listener follows the same robust pattern as the session listener, with proper error handling and complete field updates.
91-120: LGTM!The organization listener maintains consistency with the other listeners, properly handling row lifecycle events.
apps/desktop2/src/contexts/search/engine/utils.ts (4)
3-13: LGTM!The
safeParseJSONfunction properly handles non-string inputs and parse errors without throwing.
15-17: LGTM!The
normalizeQueryfunction correctly collapses multiple whitespace characters into single spaces.
52-57: LGTM!The
mergeContentfunction properly filters out falsy values and joins the remaining strings.
103-113: LGTM!The
collectCellsfunction efficiently gathers multiple cell values from a TinyBase store into a single record.apps/desktop2/src/contexts/search/engine/index.tsx (2)
42-44: Verify indexing completion timing.The indexing functions use fire-and-forget
void insert(...)internally (per the indexing module), sosetIsIndexing(false)on line 68 may execute before documents are fully indexed. This could allow searches on a partially-populated index.Please confirm whether:
- This is intentional (optimistic ready state)
- Or if indexing should be awaited before marking as complete
If awaiting is needed, the indexing functions should return promises and be called with
await Promise.all([...]).
1-14: LGTM!Imports are clean with no unused dependencies, and the type re-exports appropriately expose the search API surface.
apps/desktop2/src/contexts/search/engine/types.ts (2)
4-15: Type definitions are well-structured.The Zod schemas provide runtime validation, and the type inference is clean. The
searchFiltersSchemacurrently only supportscreated_atfiltering, which aligns with the currentSEARCH_SCHEMA. If additional fields are added to the schema (per the prior comment), corresponding filter options should be added here as well.Also applies to: 27-44
46-54: LGTM!The type-level helper types correctly map Zod schemas to Orama field descriptors. Keeping them internal (not exported) is appropriate since they're implementation details.
There was a problem hiding this comment.
Actionable comments posted: 5
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
apps/desktop2/src/chat/tools.ts(1 hunks)apps/desktop2/src/components/chat/body.tsx(2 hunks)apps/desktop2/src/components/chat/message/error.tsx(1 hunks)apps/desktop2/src/components/chat/message/loading.tsx(1 hunks)apps/desktop2/src/components/chat/message/normal.tsx(2 hunks)apps/desktop2/src/components/chat/message/shared.tsx(1 hunks)apps/desktop2/src/components/chat/message/tool/search.tsx(3 hunks)apps/desktop2/src/components/main/sidebar/search/item.tsx(1 hunks)apps/desktop2/src/contexts/search/engine/content.ts(1 hunks)apps/desktop2/src/contexts/search/engine/filters.ts(1 hunks)apps/desktop2/src/contexts/search/engine/index.tsx(1 hunks)apps/desktop2/src/contexts/search/engine/indexing.ts(1 hunks)apps/desktop2/src/contexts/search/engine/listeners.ts(1 hunks)apps/desktop2/src/contexts/search/engine/types.ts(1 hunks)apps/desktop2/src/contexts/search/engine/utils.ts(1 hunks)apps/desktop2/src/contexts/search/ui.tsx(1 hunks)apps/desktop2/src/routes/app/main/_layout.tsx(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{js,ts,tsx,rs}
⚙️ CodeRabbit configuration file
**/*.{js,ts,tsx,rs}: 1. Do not add any error handling. Keep the existing one.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".
Files:
apps/desktop2/src/contexts/search/engine/filters.tsapps/desktop2/src/components/chat/message/loading.tsxapps/desktop2/src/components/chat/message/shared.tsxapps/desktop2/src/components/chat/body.tsxapps/desktop2/src/components/chat/message/error.tsxapps/desktop2/src/components/main/sidebar/search/item.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/contexts/search/ui.tsxapps/desktop2/src/contexts/search/engine/content.tsapps/desktop2/src/routes/app/main/_layout.tsxapps/desktop2/src/contexts/search/engine/utils.tsapps/desktop2/src/contexts/search/engine/indexing.tsapps/desktop2/src/contexts/search/engine/index.tsxapps/desktop2/src/contexts/search/engine/types.tsapps/desktop2/src/chat/tools.tsapps/desktop2/src/components/chat/message/normal.tsxapps/desktop2/src/contexts/search/engine/listeners.ts
apps/desktop2/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (apps/desktop2/.cursor/rules/style.mdc)
apps/desktop2/**/*.{tsx,jsx}: When there are many Tailwind classNames with conditional logic, use the cn utility imported asimport { cn } from "@hypr/ui/lib/utils"
Always pass an array to cn when composing Tailwind classNames
Split cn array entries by logical grouping when composing Tailwind classNames
Files:
apps/desktop2/src/components/chat/message/loading.tsxapps/desktop2/src/components/chat/message/shared.tsxapps/desktop2/src/components/chat/body.tsxapps/desktop2/src/components/chat/message/error.tsxapps/desktop2/src/components/main/sidebar/search/item.tsxapps/desktop2/src/components/chat/message/tool/search.tsxapps/desktop2/src/contexts/search/ui.tsxapps/desktop2/src/routes/app/main/_layout.tsxapps/desktop2/src/contexts/search/engine/index.tsxapps/desktop2/src/components/chat/message/normal.tsx
🧬 Code graph analysis (16)
apps/desktop2/src/contexts/search/engine/filters.ts (2)
apps/desktop2/src/contexts/search/engine/index.tsx (1)
SearchFilters(14-14)apps/desktop2/src/contexts/search/engine/types.ts (1)
SearchFilters(39-39)
apps/desktop2/src/components/chat/message/loading.tsx (1)
apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)
apps/desktop2/src/components/chat/message/shared.tsx (1)
packages/ui/src/lib/utils.ts (1)
cn(4-6)
apps/desktop2/src/components/chat/body.tsx (1)
apps/desktop2/src/components/chat/message/normal.tsx (1)
NormalMessage(12-48)
apps/desktop2/src/components/chat/message/error.tsx (1)
apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)
apps/desktop2/src/components/chat/message/tool/search.tsx (3)
apps/desktop2/src/components/chat/message/types.ts (1)
Part(6-6)packages/ui/src/components/ui/card.tsx (2)
Card(9-23)CardContent(80-93)apps/desktop2/src/store/zustand/tabs.ts (1)
useTabs(31-121)
apps/desktop2/src/contexts/search/ui.tsx (1)
apps/desktop2/src/contexts/search/engine/index.tsx (1)
useSearchEngine(125-131)
apps/desktop2/src/contexts/search/engine/content.ts (1)
apps/desktop2/src/contexts/search/engine/utils.ts (2)
mergeContent(52-57)flattenTranscript(59-101)
apps/desktop2/src/routes/app/main/_layout.tsx (4)
apps/desktop2/src/contexts/search/engine/index.tsx (2)
SearchEngineProvider(23-123)useSearchEngine(125-131)apps/desktop2/src/contexts/search/ui.tsx (1)
SearchUIProvider(142-222)apps/desktop2/src/contexts/tool.tsx (2)
ToolRegistryProvider(17-67)useToolRegistry(69-75)apps/desktop2/src/chat/tools.ts (1)
toolFactories(10-34)
apps/desktop2/src/contexts/search/engine/utils.ts (1)
crates/db-script/src/lib.rs (1)
transcript(10-21)
apps/desktop2/src/contexts/search/engine/indexing.ts (4)
apps/desktop2/src/contexts/search/engine/types.ts (1)
Index(25-25)apps/desktop2/src/contexts/search/engine/utils.ts (3)
collectCells(103-113)toTrimmedString(19-25)toNumber(27-36)apps/desktop2/src/contexts/search/engine/content.ts (2)
createSessionSearchableContent(3-9)createHumanSearchableContent(11-13)apps/desktop2/src/contexts/search/index.tsx (1)
indexSessions(230-259)
apps/desktop2/src/contexts/search/engine/index.tsx (6)
apps/desktop2/src/contexts/search/engine/types.ts (4)
SearchFilters(39-39)SearchHit(41-44)Index(25-25)SEARCH_SCHEMA(17-23)apps/desktop2/src/contexts/search/engine/indexing.ts (3)
indexSessions(7-31)indexHumans(33-56)indexOrganizations(58-73)apps/desktop2/src/contexts/search/engine/listeners.ts (3)
createSessionListener(9-47)createHumanListener(49-89)createOrganizationListener(91-120)apps/desktop2/src/contexts/search/engine/utils.ts (1)
normalizeQuery(15-17)apps/desktop2/src/contexts/search/engine/filters.ts (1)
buildOramaFilters(3-29)apps/desktop2/src/contexts/search/index.tsx (1)
SearchProvider(440-579)
apps/desktop2/src/contexts/search/engine/types.ts (1)
apps/desktop2/src/contexts/search/engine/index.tsx (4)
SearchEntityType(14-14)SearchDocument(14-14)SearchFilters(14-14)SearchHit(14-14)
apps/desktop2/src/chat/tools.ts (1)
apps/desktop2/src/contexts/search/engine/types.ts (3)
SearchFilters(39-39)SearchHit(41-44)searchFiltersSchema(35-37)
apps/desktop2/src/components/chat/message/normal.tsx (3)
apps/desktop2/src/chat/types.ts (1)
HyprUIMessage(9-9)apps/desktop2/src/components/chat/message/shared.tsx (3)
MessageContainer(6-23)MessageBubble(25-48)ActionButton(50-83)apps/desktop2/src/components/chat/message/types.ts (1)
Part(6-6)
apps/desktop2/src/contexts/search/engine/listeners.ts (3)
apps/desktop2/src/contexts/search/engine/types.ts (1)
Index(25-25)apps/desktop2/src/contexts/search/engine/utils.ts (5)
collectCells(103-113)toTrimmedString(19-25)toNumber(27-36)toString(38-43)toBoolean(45-50)apps/desktop2/src/contexts/search/engine/content.ts (2)
createSessionSearchableContent(3-9)createHumanSearchableContent(11-13)
🪛 Biome (2.1.2)
apps/desktop2/src/contexts/search/engine/utils.ts
[error] 38-38: Do not shadow the global "toString" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
apps/desktop2/src/contexts/search/engine/listeners.ts
[error] 7-7: Do not shadow the global "toString" property.
Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.
(lint/suspicious/noShadowRestrictedNames)
⏰ 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 (windows, windows-latest)
- GitHub Check: ci (macos, macos-14)
🔇 Additional comments (20)
apps/desktop2/src/components/chat/body.tsx (2)
2-2: LGTM!The import cleanup appropriately removes icons that are now used in the dedicated message components and adds the new modular message component imports.
Also applies to: 8-10
100-105: LGTM!The switch from
ChatBodyMessagetoNormalMessageis correct and maintains the same prop interface.apps/desktop2/src/components/chat/message/error.tsx (1)
5-21: LGTM!The
ErrorMessagecomponent is well-structured and properly uses the shared UI primitives. The conditional action button rendering and error styling are appropriate.apps/desktop2/src/components/chat/message/loading.tsx (1)
5-24: LGTM!The
LoadingMessagecomponent is cleanly implemented with appropriate loading indicators and conditional cancel functionality.apps/desktop2/src/components/chat/message/normal.tsx (2)
24-46: LGTM!The refactoring to use
MessageContainer,MessageBubble, andActionButtonprimitives is clean and consistent with the other message components. The variant selection and conditional action button logic are correct.
12-12: LGTM!The rename from
ChatBodyMessagetoNormalMessageis semantically clearer and aligns with the new component structure.apps/desktop2/src/components/chat/message/shared.tsx (3)
6-23: LGTM!The
MessageContainercomponent is cleanly implemented and properly uses thecnutility with an array as per coding guidelines.
25-48: LGTM!The
MessageBubblecomponent properly implements variant-based styling and follows the coding guidelines forcnusage with arrays.
50-83: LGTM!The
ActionButtoncomponent is well-implemented with proper accessibility (aria-label), hover-based visibility, and follows the coding guidelines forcnusage with arrays.apps/desktop2/src/contexts/search/engine/types.ts (6)
1-5: LGTM!The imports and
SearchEntityTypeenum are well-defined. The use of Zod's enum schema provides runtime validation and type safety.
7-15: LGTM!The
searchDocumentSchemais well-structured with appropriate field types. The schema provides both runtime validation and compile-time type safety through type inference.
17-23: LGTM! Excellent type safety.The
SEARCH_SCHEMAconstant withsatisfies InferOramaSchemaensures compile-time validation that the runtime Orama schema matches the Zod schema structure. This prevents schema drift between validation and indexing.
25-39: LGTM!The
Indextype and filter schemas follow standard patterns. ThenumberFilterSchemaprovides flexible range filtering with optional operators (gte, lte, gt, lt, eq), and the filter structure is easily extensible for additional fields.
41-44: LGTM!The
SearchHittype follows the standard structure for search results with relevance scores.
46-54: LGTM! Well-designed type-level utilities.The
InferOramaFieldandInferOramaSchemahelper types elegantly map Zod schemas to Orama field types at the type level, enabling compile-time validation of the runtime schema consistency.apps/desktop2/src/contexts/search/engine/utils.ts (5)
1-17: LGTM!The
safeParseJSONandnormalizeQueryfunctions are well-implemented. The safe JSON parsing with fallback and query normalization logic are correct.
19-36: LGTM!The
toTrimmedStringandtoNumberfunctions provide safe type coercion with sensible defaults.
45-57: LGTM!The
toBooleanandmergeContentfunctions are well-implemented. ThemergeContentfunction correctly combines content parts by trimming, filtering empty values, and joining with spaces.
59-101: LGTM! Thorough transcript flattening.The
flattenTranscriptfunction handles various transcript formats (string, array, object) with recursive processing. The logic correctly preferstextorcontentfields in object segments, aligning with the transcript structure patterns shown in the codebase.
103-113: Verify if a more specific type exists forpersistedStore.The
persistedStoreparameter is typed asany, which bypasses type safety. If TinyBase exports types likeStoreorPersistedStore, consider using those for better type checking.According to the retrieved learnings, TinyBase provides typed APIs and schema support. You can likely import and use a specific store type from the
tinybasepackage.Based on learnings.
No description provided.