Skip to content

Conversation

@duckduckhero
Copy link
Contributor

@duckduckhero duckduckhero commented Aug 13, 2025

  • initial auto tagging
  • some minor responsive ui fixes

Summary by cubic

Added automatic tag generation for notes, suggesting relevant tags based on note content and user history. Improved responsive UI for tag chips and transcript view.

  • New Features

  • Notes now get up to two suggested tags assigned automatically after title generation.

  • Tag suggestions use note content, existing tags, and historical tags.

  • Bug Fixes

  • Tag chip display is more consistent on narrow screens.

  • Transcript header styling is improved for empty states.

@coderabbitai
Copy link

coderabbitai bot commented Aug 13, 2025

📝 Walkthrough

Walkthrough

Implements automatic tag generation after title creation in the editor flow, adds new tag-generation utilities and templates, updates UI to display tag counts when space-constrained, and conditionally renders a header border in the transcript view. Introduces a QueryClient parameter to refresh session tag queries after assigning up to two generated tags.

Changes

Cohort / File(s) Summary of changes
Editor enhance flow & auto-tag wiring
apps/desktop/src/components/editor-area/index.tsx
Extends generateTitleDirect to accept QueryClient; after title generation, invokes autoTagGeneration, upserts up to two tags (reusing existing IDs), assigns them to the session, and invalidates session-tags query; integrates useQueryClient into EditorArea enhance onSuccess.
Tag generation utilities
apps/desktop/src/utils/tag-generation.ts
Prefers enhanced_memo_html, enriches prompts with existing/formal/historical tags, calls model via generateText with providerOptions, validates output via zod schema, adds robust error handling, and introduces autoTagGeneration(sessionId).
Templating for auto-tag generation
crates/template/assets/auto_generate_tags.*.jinja, crates/template/src/lib.rs
Adds system/user Jinja templates for auto-tag generation; registers new PredefinedTemplate variants, constants, and mappings to include the templates in the engine.
Tag chip display adjustments
apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx
For narrow layouts with tags, label now shows total tag count; removes previous truncation branch; non-narrow behavior unchanged.
Transcript header styling
apps/desktop/src/components/right-panel/views/transcript-view.tsx
Applies bottom border to header only when showEmptyMessage is false; no structural changes.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant EditorArea
  participant generateTitleDirect
  participant TagGen as autoTagGeneration
  participant Store as Tag/Session Store
  participant QC as QueryClient

  User->>EditorArea: Enhance note
  EditorArea->>generateTitleDirect: enhancedContent, sessionId, sessions, queryClient
  generateTitleDirect->>TagGen: sessionId
  TagGen->>Store: Fetch session, tags, history
  TagGen-->>generateTitleDirect: Suggested tags [up to 5]
  generateTitleDirect->>Store: Upsert/reuse tags (max 2) and assign to session
  generateTitleDirect->>QC: Invalidate session-tags query
  generateTitleDirect-->>EditorArea: Title (and tagging complete)
  EditorArea-->>User: UI refreshed (tags updated)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • hotfix: tag generation #994 — Updates and refactors tag-generation logic in apps/desktop/src/utils/tag-generation.ts, overlapping with the new autoTagGeneration and parsing/error handling.
  • Feature chat (Beta version)  #1184 — Modifies generateTitleDirect in apps/desktop/src/components/editor-area/index.tsx; this PR also changes that function’s signature and post-title behavior.
  • Transcript editor styling #873 — Adjusts header/layout classes in apps/desktop/src/components/right-panel/views/transcript-view.tsx, overlapping with the conditional border change.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch auto-tagging

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic analysis

1 issue found across 7 files • Review in cubic

React with 👍 or 👎 to teach cubic. You can also tag @cubic-dev-ai to give feedback, ask questions, or re-run the review.

Copy link

@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: 3

🔭 Outside diff range comments (1)
apps/desktop/src/utils/tag-generation.ts (1)

79-148: Code duplication between generateTagsForSession and autoTagGeneration.

The two functions are nearly identical, differing only in the template names used. This violates the DRY principle and will make maintenance harder.

Consider extracting the common logic into a shared function:

-export async function generateTagsForSession(sessionId: string): Promise<string[]> {
+async function generateTagsWithTemplate(
+  sessionId: string,
+  systemTemplate: string,
+  userTemplate: string
+): Promise<string[]> {
   try {
     const { type: connectionType } = await connectorCommands.getLlmConnection();
 
     const config = await dbCommands.getConfig();
     const session = await dbCommands.getSession({ id: sessionId });
     if (!session) {
       throw new Error("Session not found");
     }
 
     const historicalTags = await dbCommands.listAllTags();
     const currentTags = await dbCommands.listSessionTags(sessionId);
 
     const extractHashtags = (text: string): string[] => {
       const hashtagRegex = /#(\w+)/g;
       return Array.from(text.matchAll(hashtagRegex), match => match[1]);
     };
 
     const existingHashtags = extractHashtags(session.raw_memo_html);
 
     const systemPrompt = await templateCommands.render(
-      "suggest_tags.system",
+      systemTemplate,
       { config, type: connectionType },
     );
 
     let contentToUse = session.enhanced_memo_html ?? session.raw_memo_html;
 
     const userPrompt = await templateCommands.render(
-      "suggest_tags.user",
+      userTemplate,
       {
         title: session.title,
         content: contentToUse,
         existing_hashtags: existingHashtags,
         formal_tags: currentTags.map(t => t.name),
         historical_tags: historicalTags.slice(0, 20).map(t => t.name),
       },
     );
 
     const provider = await modelProvider();
     const model = provider.languageModel("defaultModel");
 
     const result = await generateText({
       model,
       messages: [
         { role: "system", content: systemPrompt },
         { role: "user", content: userPrompt },
       ],
       providerOptions: {
         [localProviderName]: {
           metadata: {
             grammar: {
               task: "tags",
             } satisfies Grammar,
           },
         },
       },
     });
 
     const schema = z.preprocess(
       (val) => (typeof val === "string" ? JSON.parse(val) : val),
       z.array(z.string().min(1)).min(1).max(5),
     );
 
     const parsed = schema.safeParse(result.text);
     return parsed.success ? parsed.data : [];
   } catch (error) {
     console.error("Tag generation failed:", error);
     return [];
   }
 }
 
+export async function generateTagsForSession(sessionId: string): Promise<string[]> {
+  return generateTagsWithTemplate(sessionId, "suggest_tags.system", "suggest_tags.user");
+}
+
 export async function autoTagGeneration(sessionId: string): Promise<string[]> {
-  try {
-    const { type: connectionType } = await connectorCommands.getLlmConnection();
-
-    const config = await dbCommands.getConfig();
-    const session = await dbCommands.getSession({ id: sessionId });
-    if (!session) {
-      throw new Error("Session not found");
-    }
-
-    const historicalTags = await dbCommands.listAllTags();
-    const currentTags = await dbCommands.listSessionTags(sessionId);
-
-    const extractHashtags = (text: string): string[] => {
-      const hashtagRegex = /#(\w+)/g;
-      return Array.from(text.matchAll(hashtagRegex), match => match[1]);
-    };
-
-    const existingHashtags = extractHashtags(session.raw_memo_html);
-
-    const systemPrompt = await templateCommands.render(
-      "auto_generate_tags.system",
-      { config, type: connectionType },
-    );
-
-    let contentToUse = session.enhanced_memo_html ?? session.raw_memo_html;
-
-    const userPrompt = await templateCommands.render(
-      "auto_generate_tags.user",
-      {
-        title: session.title,
-        content: contentToUse,
-        existing_hashtags: existingHashtags,
-        formal_tags: currentTags.map(t => t.name),
-        historical_tags: historicalTags.slice(0, 20).map(t => t.name),
-      },
-    );
-
-    const provider = await modelProvider();
-    const model = provider.languageModel("defaultModel");
-
-    const result = await generateText({
-      model,
-      messages: [
-        { role: "system", content: systemPrompt },
-        { role: "user", content: userPrompt },
-      ],
-      providerOptions: {
-        [localProviderName]: {
-          metadata: {
-            grammar: {
-              task: "tags",
-            } satisfies Grammar,
-          },
-        },
-      },
-    });
-
-    const schema = z.preprocess(
-      (val) => (typeof val === "string" ? JSON.parse(val) : val),
-      z.array(z.string().min(1)).min(1).max(5),
-    );
-
-    const parsed = schema.safeParse(result.text);
-    return parsed.success ? parsed.data : [];
-  } catch (error) {
-    console.error("Tag generation failed:", error);
-    return [];
-  }
+  return generateTagsWithTemplate(sessionId, "auto_generate_tags.system", "auto_generate_tags.user");
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f980320 and ac1630c.

📒 Files selected for processing (7)
  • apps/desktop/src/components/editor-area/index.tsx (5 hunks)
  • apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx (1 hunks)
  • apps/desktop/src/components/right-panel/views/transcript-view.tsx (1 hunks)
  • apps/desktop/src/utils/tag-generation.ts (1 hunks)
  • crates/template/assets/auto_generate_tags.system.jinja (1 hunks)
  • crates/template/assets/auto_generate_tags.user.jinja (1 hunks)
  • crates/template/src/lib.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,ts,tsx,rs}

⚙️ CodeRabbit Configuration File

**/*.{js,ts,tsx,rs}: 1. No error handling.
2. No unused imports, variables, or functions.
3. For comments, keep it minimal. It should be about "Why", not "What".

Files:

  • apps/desktop/src/components/right-panel/views/transcript-view.tsx
  • apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx
  • apps/desktop/src/utils/tag-generation.ts
  • apps/desktop/src/components/editor-area/index.tsx
  • crates/template/src/lib.rs
⏰ 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). (3)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: ci (macos, macos-latest)
  • GitHub Check: ci (windows, windows-latest)
🔇 Additional comments (13)
apps/desktop/src/components/right-panel/views/transcript-view.tsx (1)

151-155: The dynamic className approach is correct and improves the UI consistency.

The conditional border styling based on showEmptyMessage is a good pattern for responsive UI design.

apps/desktop/src/components/editor-area/note-header/chips/tag-chip.tsx (1)

44-47: Good simplification of the narrow display logic.

Showing just the count when the space is constrained is a clean approach that matches the behavior of other chips in the UI.

crates/template/assets/auto_generate_tags.user.jinja (1)

1-30: Template structure is well-organized and follows Jinja best practices.

The conditional rendering for existing hashtags, formal tags, and historical tags prevents empty sections. The formatting with comma separators is clean and consistent.

crates/template/assets/auto_generate_tags.system.jinja (1)

1-24: Comprehensive system prompt with clear guidelines.

The prompt effectively guides the model to generate relevant tags by prioritizing historical tags, excluding already-present tags, and providing sensible defaults. The instructions are clear and should produce consistent results.

apps/desktop/src/components/editor-area/index.tsx (5)

1-1: Typed QueryClient import is appropriate

Importing QueryClient as a type-only import keeps the runtime bundle lean and satisfies TS typing needs.


11-11: New autoTagGeneration import is used

Import is utilized in generateTitleDirect; no unused import issues.


81-86: Confirm crypto.randomUUID availability in your runtime

Ensure crypto.randomUUID exists in your Electron/TS target. If not, fallback to Node’s crypto or a UUID lib.

If needed, you can adapt with one of the following:

  • Node: import { randomUUID } from "crypto" and use randomUUID().
  • Lib: import { v4 as uuid } from "uuid" and use uuid().

147-147: Good: useQueryClient instance to pass into title/tag flow

Using the shared QueryClient allows targeted invalidation after tag assignment.


31-36: Signature change verified: all call sites updated

A search for generateTitleDirect( across the codebase returned only its definition and the single invocation in apps/desktop/src/components/editor-area/index.tsx at line 155, which correctly passes queryClient. No other callers found—no action needed.

crates/template/src/lib.rs (4)

47-50: Enum variants for auto-generate-tags are well-defined

New PredefinedTemplate variants align with desired serialized names.


73-78: From mapping updated correctly

New variants are included in the Template::from mapping; no missing arms.


130-139: Templates registered in environment

Both auto-generate-tags templates are added to the Jinja environment; consistent with other registrations.


90-93: Asset constants paths verified

Both include_str! paths in crates/template/src/lib.rs (lines 90–93) point to existing files:

  • crates/template/assets/auto_generate_tags.system.jinja
  • crates/template/assets/auto_generate_tags.user.jinja

No further action required.

@duckduckhero duckduckhero merged commit d0236eb into main Aug 13, 2025
8 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Aug 13, 2025
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.

2 participants