Skip to content

Search tool from tool registry#1566

Merged
yujonglee merged 8 commits intomainfrom
search-from-tool-registary
Oct 14, 2025
Merged

Search tool from tool registry#1566
yujonglee merged 8 commits intomainfrom
search-from-tool-registary

Conversation

@yujonglee
Copy link
Contributor

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Replaces 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

Cohort / File(s) Summary
Tool system & transport
apps/desktop2/src/chat/tools.ts, apps/desktop2/src/chat/transport.ts, apps/desktop2/src/contexts/tool.tsx, apps/desktop2/src/components/chat/session.tsx, apps/desktop2/src/routes/app/main/_layout.tsx
Introduces ToolRegistry (provider/hook), converts tools to factory pattern with ToolDependencies/toolFactories, injects ToolRegistry into CustomChatTransport (constructor), replaces local getTools with registry.getForTransport, and wires registration in app layout.
Search engine (Orama) core
apps/desktop2/src/contexts/search/engine/*
apps/desktop2/src/contexts/search/engine/types.ts, utils.ts, content.ts, filters.ts, indexing.ts, listeners.ts, index.tsx
New Orama-based search engine modules: types/schema, utilities, content builders, filter builder, indexing functions, row listeners, and SearchEngineProvider + useSearchEngine hook exposing search() and indexing state.
Search UI layer
apps/desktop2/src/contexts/search/ui.tsx
New SearchUIProvider and useSearch hook implementing query state, grouping/highlighting, thresholds, and exposing SearchResult/SearchGroup types; re-exports some engine types.
Removed legacy search context
apps/desktop2/src/contexts/search/index.tsx (deleted)
Deletes previous monolithic search context and its exports (SearchProvider, useSearch, types, indexing/search logic).
Search consumers & imports updated
apps/desktop2/src/components/main/body/search.tsx, apps/desktop2/src/components/main/sidebar/index.tsx, apps/desktop2/src/components/main/sidebar/search/*
Redirects imports from contexts/searchcontexts/search/ui, updates SearchResult typing, removes org lookup and subtitle in HumanSearchResultItem; UI behavior preserved.
Chat message UI refactor
apps/desktop2/src/components/chat/body.tsx, apps/desktop2/src/components/chat/message/shared.tsx, apps/desktop2/src/components/chat/message/normal.tsx, apps/desktop2/src/components/chat/message/loading.tsx, apps/desktop2/src/components/chat/message/error.tsx
Adds MessageContainer, MessageBubble, ActionButton; extracts LoadingMessage and ErrorMessage components; renames ChatBodyMessage→NormalMessage and updates usage/imports and icons.
Tool result UI
apps/desktop2/src/components/chat/message/tool/search.tsx
Replaces raw JSON output with carousel of Card items, adds RenderSession component to fetch session rows and open tabs, keeps error path and disclosure.
Search engine helpers
apps/desktop2/src/contexts/search/engine/utils.ts, content.ts, filters.ts
Adds safe JSON parsing, normalization, coercion utilities, content builders, and buildOramaFilters for translating UI filters to Orama format.
Indexing & listeners
apps/desktop2/src/contexts/search/engine/indexing.ts, apps/desktop2/src/contexts/search/engine/listeners.ts
Implements indexSessions/indexHumans/indexOrganizations and row listeners to insert/update/remove documents in Orama index from persisted store.

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
Loading
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
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR description field is empty and contains only a placeholder noting that no description was provided, so it does not describe any part of the changeset and leaves reviewers without context about the scope or rationale of the changes. Please add a summary describing the key changes, motivations, and relevant context to help reviewers understand the purpose and impact of this pull request.
Docstring Coverage ⚠️ Warning Docstring coverage is 2.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly indicates that the search tool is now provided via the tool registry and captures the core refactoring of the changeset in a concise and specific way. It directly relates to the main change of migrating the searchSessions tool into a registry-driven system without unnecessary detail or noise.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e7777a and 11c2724.

📒 Files selected for processing (3)
  • apps/desktop2/src/components/chat/message/tool/search.tsx (3 hunks)
  • apps/desktop2/src/contexts/search/engine/indexing.ts (1 hunks)
  • apps/desktop2/src/contexts/search/engine/listeners.ts (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 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: Replace any on search results with a concrete type
The results.map((result: any, …) callback weakens type safety. Define an interface matching your result shape (e.g. { id: string; title?: string; /* … */ }) and replace any with that type.

apps/desktop2/src/chat/tools.ts (4)

3-5: Consider stricter typing for search results.

The search function returns Promise<any[]>, which loses type safety. Consider defining an explicit result type (e.g., SearchHit with document, 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 ToolDependencies or 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 SearchHit interface matching { document: { id, title, content, created_at } }.
  • Replace hit: any (and update deps.search return type to SearchHit[]) 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

📥 Commits

Reviewing files that changed from the base of the PR and between 67c5c93 and be3b979.

📒 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 as import { 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.tsx
  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/sidebar/search/group.tsx
  • apps/desktop2/src/contexts/tool.tsx
  • apps/desktop2/src/routes/app/main/_layout.tsx
  • apps/desktop2/src/components/chat/session.tsx
  • apps/desktop2/src/contexts/search/engine.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/components/main/sidebar/search/index.tsx
  • apps/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.tsx
  • apps/desktop2/src/components/main/sidebar/index.tsx
  • apps/desktop2/src/components/main/sidebar/search/group.tsx
  • apps/desktop2/src/chat/transport.ts
  • apps/desktop2/src/contexts/tool.tsx
  • apps/desktop2/src/routes/app/main/_layout.tsx
  • apps/desktop2/src/chat/tools.ts
  • apps/desktop2/src/components/chat/session.tsx
  • apps/desktop2/src/contexts/search/engine.tsx
  • apps/desktop2/src/components/main/body/search.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/components/main/sidebar/search/index.tsx
  • apps/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:

  1. Navigation buttons are fully visible and clickable
  2. No visual clipping or overlap occurs
  3. 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.useRow can return undefined if the row is missing. Update rendering to guard the session itself, e.g.:

const title = session?.title ?? "Untitled";

or early-return when !session before accessing title.
apps/desktop2/src/components/chat/message/tool/search.tsx:91-98

apps/desktop2/src/components/main/sidebar/search/index.tsx (1)

4-4: LGTM! Import path updated correctly.

The import path change from contexts/search to contexts/search/ui aligns 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/ui module.

apps/desktop2/src/components/chat/session.tsx (2)

30-31: LGTM! Registry integration implemented correctly.

The integration with useToolRegistry enables the dependency-injected tool system. The transport is correctly memoized with registry as a dependency, ensuring it recreates when the registry changes.


30-31: Transport won’t be recreated unexpectedly. The registry object is memoized over stable callbacks and never changes reference, so transport will 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 supports type: "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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
apps/desktop2/src/contexts/search/engine/utils.ts (1)

19-50: LGTM, but consider renaming toString.

The type conversion utilities are well-implemented with proper type guards and fallback values. However, the toString function name shadows the global Object.prototype.toString property, 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.ts and listeners.ts accordingly.

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

📥 Commits

Reviewing files that changed from the base of the PR and between be3b979 and 7d84471.

📒 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 as import { 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.tsx
  • apps/desktop2/src/components/chat/message/shared.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/components/chat/message/normal.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/components/chat/message/error.tsx
  • apps/desktop2/src/contexts/search/engine/index.tsx
  • apps/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.tsx
  • apps/desktop2/src/contexts/search/engine/filters.ts
  • apps/desktop2/src/components/chat/message/shared.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/contexts/search/engine/content.ts
  • apps/desktop2/src/contexts/search/engine/utils.ts
  • apps/desktop2/src/chat/tools.ts
  • apps/desktop2/src/components/chat/message/normal.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/contexts/search/engine/listeners.ts
  • apps/desktop2/src/components/chat/message/error.tsx
  • apps/desktop2/src/contexts/search/engine/indexing.ts
  • apps/desktop2/src/contexts/search/engine/index.tsx
  • apps/desktop2/src/routes/app/main/_layout.tsx
  • apps/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 ToolDependencies interface 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 Tools type 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 safeParseJSON function properly handles non-string inputs and parse errors without throwing.


15-17: LGTM!

The normalizeQuery function correctly collapses multiple whitespace characters into single spaces.


52-57: LGTM!

The mergeContent function properly filters out falsy values and joins the remaining strings.


103-113: LGTM!

The collectCells function 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), so setIsIndexing(false) on line 68 may execute before documents are fully indexed. This could allow searches on a partially-populated index.

Please confirm whether:

  1. This is intentional (optimistic ready state)
  2. 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 searchFiltersSchema currently only supports created_at filtering, which aligns with the current SEARCH_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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be3b979 and 0e7777a.

📒 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.ts
  • apps/desktop2/src/components/chat/message/loading.tsx
  • apps/desktop2/src/components/chat/message/shared.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/components/chat/message/error.tsx
  • apps/desktop2/src/components/main/sidebar/search/item.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/contexts/search/ui.tsx
  • apps/desktop2/src/contexts/search/engine/content.ts
  • apps/desktop2/src/routes/app/main/_layout.tsx
  • apps/desktop2/src/contexts/search/engine/utils.ts
  • apps/desktop2/src/contexts/search/engine/indexing.ts
  • apps/desktop2/src/contexts/search/engine/index.tsx
  • apps/desktop2/src/contexts/search/engine/types.ts
  • apps/desktop2/src/chat/tools.ts
  • apps/desktop2/src/components/chat/message/normal.tsx
  • apps/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 as import { 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.tsx
  • apps/desktop2/src/components/chat/message/shared.tsx
  • apps/desktop2/src/components/chat/body.tsx
  • apps/desktop2/src/components/chat/message/error.tsx
  • apps/desktop2/src/components/main/sidebar/search/item.tsx
  • apps/desktop2/src/components/chat/message/tool/search.tsx
  • apps/desktop2/src/contexts/search/ui.tsx
  • apps/desktop2/src/routes/app/main/_layout.tsx
  • apps/desktop2/src/contexts/search/engine/index.tsx
  • apps/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 ChatBodyMessage to NormalMessage is correct and maintains the same prop interface.

apps/desktop2/src/components/chat/message/error.tsx (1)

5-21: LGTM!

The ErrorMessage component 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 LoadingMessage component 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, and ActionButton primitives 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 ChatBodyMessage to NormalMessage is semantically clearer and aligns with the new component structure.

apps/desktop2/src/components/chat/message/shared.tsx (3)

6-23: LGTM!

The MessageContainer component is cleanly implemented and properly uses the cn utility with an array as per coding guidelines.


25-48: LGTM!

The MessageBubble component properly implements variant-based styling and follows the coding guidelines for cn usage with arrays.


50-83: LGTM!

The ActionButton component is well-implemented with proper accessibility (aria-label), hover-based visibility, and follows the coding guidelines for cn usage with arrays.

apps/desktop2/src/contexts/search/engine/types.ts (6)

1-5: LGTM!

The imports and SearchEntityType enum are well-defined. The use of Zod's enum schema provides runtime validation and type safety.


7-15: LGTM!

The searchDocumentSchema is 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_SCHEMA constant with satisfies InferOramaSchema ensures 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 Index type and filter schemas follow standard patterns. The numberFilterSchema provides 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 SearchHit type follows the standard structure for search results with relevance scores.


46-54: LGTM! Well-designed type-level utilities.

The InferOramaField and InferOramaSchema helper 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 safeParseJSON and normalizeQuery functions are well-implemented. The safe JSON parsing with fallback and query normalization logic are correct.


19-36: LGTM!

The toTrimmedString and toNumber functions provide safe type coercion with sensible defaults.


45-57: LGTM!

The toBoolean and mergeContent functions are well-implemented. The mergeContent function correctly combines content parts by trimming, filtering empty values, and joining with spaces.


59-101: LGTM! Thorough transcript flattening.

The flattenTranscript function handles various transcript formats (string, array, object) with recursive processing. The logic correctly prefers text or content fields in object segments, aligning with the transcript structure patterns shown in the codebase.


103-113: Verify if a more specific type exists for persistedStore.

The persistedStore parameter is typed as any, which bypasses type safety. If TinyBase exports types like Store or PersistedStore, 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 tinybase package.

Based on learnings.

@yujonglee yujonglee merged commit 51f6bd0 into main Oct 14, 2025
3 of 4 checks passed
@ComputelessComputer ComputelessComputer deleted the search-from-tool-registary branch December 14, 2025 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant