Fallback to label name if label id not found#895
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThreads label names and a scoped logger through labeling and onboarding flows; provider labelMessage gains name-based fallback and returns resolved IDs; adds labelMessageAndSync to sync stale label IDs into Action records; refactors reply-tracker to store full label objects per conversation status. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as Onboard UI
participant Onboard as Onboarding Logic
participant AI as Label Action
participant Helper as labelMessageAndSync
participant Provider as EmailProvider
participant DB as Database (Action records)
UI->>Onboard: create/update rule (passes logger)
Onboard->>AI: resolve labelName & labelId (passes logger)
AI->>Helper: labelMessageAndSync(provider, messageId, labelId, labelName, emailAccountId)
Helper->>Provider: labelMessage(messageId, labelId, labelName)
alt Provider finds label by ID
Provider-->>Helper: { usedFallback: false, actualLabelId: id }
else ID not found & name provided
Provider-->>Helper: { usedFallback: true, actualLabelId: resolvedId }
Helper->>DB: update Action.where(labelId==old && emailAccountId==X) -> set actualLabelId
DB-->>Helper: update result
else failure
Provider-->>Helper: throw error (includes labelId & labelName)
end
Helper-->>AI: done
AI-->>Onboard: logger.info recorded
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/web/utils/actions/rule.ts(7 hunks)apps/web/utils/ai/actions.ts(1 hunks)apps/web/utils/assistant/process-assistant-email.ts(1 hunks)apps/web/utils/email/microsoft.ts(1 hunks)apps/web/utils/email/types.ts(1 hunks)apps/web/utils/reply-tracker/label-helpers.ts(7 hunks)version.txt(1 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
!{.cursor/rules/*.mdc}
📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
version.txtapps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
version.txtapps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use@/for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/actions/**/*.ts
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/utils/actions/**/*.ts: Use server actions for all mutations (create/update/delete operations)
next-safe-actionprovides centralized error handling
Use Zod schemas for validation on both client and server
UserevalidatePathin server actions for cache invalidation
apps/web/utils/actions/**/*.ts: Use server actions (withnext-safe-action) for all mutations (create/update/delete operations); do NOT use POST API routes for mutations.
UserevalidatePathin server actions to invalidate cache after mutations.
Files:
apps/web/utils/actions/rule.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}: UsecreateScopedLoggerfor logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/actions/*.ts
📄 CodeRabbit inference engine (.cursor/rules/server-actions.mdc)
apps/web/utils/actions/*.ts: Implement all server actions using thenext-safe-actionlibrary for type safety, input validation, context management, and error handling. Refer toapps/web/utils/actions/safe-action.tsfor client definitions (actionClient,actionClientUser,adminActionClient).
UseactionClientUserwhen only authenticated user context (userId) is needed.
UseactionClientwhen both authenticated user context and a specificemailAccountIdare needed. TheemailAccountIdmust be bound when calling the action from the client.
UseadminActionClientfor actions restricted to admin users.
Access necessary context (likeuserId,emailAccountId, etc.) provided by the safe action client via thectxobject in the.action()handler.
Server Actions are strictly for mutations (operations that change data, e.g., creating, updating, deleting). Do NOT use Server Actions for data fetching (GET operations). For data fetching, use dedicated GET API Routes combined with SWR Hooks.
UseSafeErrorfor expected/handled errors within actions if needed.next-safe-actionprovides centralized error handling.
Use the.metadata({ name: "actionName" })method to provide a meaningful name for monitoring. Sentry instrumentation is automatically applied viawithServerActionInstrumentationwithin the safe action clients.
If an action modifies data displayed elsewhere, userevalidatePathorrevalidateTagfromnext/cachewithin the action handler as needed.Server action files must start with
use server
Files:
apps/web/utils/actions/rule.ts
apps/web/utils/**
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/folder for reusable logic
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/actions/rule.tsapps/web/utils/assistant/process-assistant-email.tsapps/web/utils/ai/actions.tsapps/web/utils/email/microsoft.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/ai/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features
Files:
apps/web/utils/ai/actions.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments
Files:
apps/web/utils/ai/actions.ts
🧠 Learnings (6)
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use descriptive scoped loggers for each feature
Applied to files:
apps/web/utils/actions/rule.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Log inputs and outputs with appropriate log levels and include relevant context
Applied to files:
apps/web/utils/actions/rule.ts
📚 Learning: 2025-07-18T15:05:34.899Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.899Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Applied to files:
apps/web/utils/email/types.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use TypeScript types for all parameters and return values in LLM features
Applied to files:
apps/web/utils/email/types.ts
📚 Learning: 2025-07-17T04:19:57.099Z
Learnt from: edulelis
Repo: elie222/inbox-zero PR: 576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
Applied to files:
apps/web/utils/email/types.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
🧬 Code graph analysis (4)
apps/web/utils/actions/rule.ts (2)
apps/web/utils/logger.ts (1)
Logger(5-5)apps/web/app/api/outlook/webhook/logger.ts (1)
logger(3-3)
apps/web/utils/assistant/process-assistant-email.ts (2)
apps/web/utils/types.ts (1)
isDefined(8-10)apps/web/app/api/outlook/webhook/logger.ts (1)
logger(3-3)
apps/web/utils/email/microsoft.ts (1)
apps/web/app/api/outlook/webhook/logger.ts (1)
logger(3-3)
apps/web/utils/reply-tracker/label-helpers.ts (3)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
ConversationStatus(10-14)apps/web/utils/email/types.ts (1)
EmailProvider(44-237)apps/web/utils/rule/consts.ts (1)
getRuleLabel(122-124)
⏰ 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: cubic · AI code reviewer
- GitHub Check: Analyze (javascript-typescript)
There was a problem hiding this comment.
2 issues found across 7 files
Prompt for AI agents (all 2 issues)
Understand the root cause of the following 2 issues and fix them.
<file name="apps/web/utils/reply-tracker/label-helpers.ts">
<violation number="1" location="apps/web/utils/reply-tracker/label-helpers.ts:54">
`dbLabels[type]` is always a truthy object (even when `labelId` is null), so this guard never runs and we stop looking up provider labels—conflicting status labels will no longer be removed.</violation>
<violation number="2" location="apps/web/utils/reply-tracker/label-helpers.ts:123">
Because `targetLabel` is always a non-null object, this branch no longer runs when the DB lacks the label; we skip the fallback lookup/creation and fail to apply the thread status label.</violation>
</file>
React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/utils/reply-tracker/label-helpers.ts (1)
120-155: Enhance label resolution before applying.Similar to the removal logic issue, when
dbLabels[systemType]has a label name but nolabelId, the code skips the provider lookup (line 124 checks both fields) and proceeds to callprovider.labelMessagewithlabelId: ""and the label name. While the PR title indicates this fallback is intended, it's more robust to resolve the missing ID fromproviderLabelsbefore applying, ensuring consistency and reducing reliance on provider-specific empty-ID handling.Consider resolving missing fields from provider labels:
let targetLabel = dbLabels[systemType]; // If we don't have both labelId and label from DB, fetch/create it if (!targetLabel.labelId && !targetLabel.label) { const label = providerLabels.find((l) => l.name === getRuleLabel(systemType)) || (await provider.createLabel(getRuleLabel(systemType))); if (label) { targetLabel = { labelId: label.id, label: label.name, }; } } + +// If we have label name but missing ID, resolve from provider +if (!targetLabel.labelId && targetLabel.label) { + const label = providerLabels.find((l) => l.name === targetLabel.label); + if (label) { + targetLabel = { + labelId: label.id, + label: label.name, + }; + } +} // Error only if we still don't have either field after attempting to fetch/create if (!targetLabel.labelId && !targetLabel.label) { logger.error("Failed to get or create target label"); return; } return provider .labelMessage({ messageId, - labelId: targetLabel.labelId || "", + labelId: targetLabel.labelId ?? "", labelName: targetLabel.label, })Also replaced
||with??for clearer null-coalescing semantics.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/utils/reply-tracker/label-helpers.ts(7 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use@/for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/reply-tracker/label-helpers.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/utils/reply-tracker/label-helpers.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/reply-tracker/label-helpers.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}: UsecreateScopedLoggerfor logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/folder for reusable logic
Files:
apps/web/utils/reply-tracker/label-helpers.ts
apps/web/utils/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/reply-tracker/label-helpers.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/reply-tracker/label-helpers.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/utils/reply-tracker/label-helpers.ts
🧠 Learnings (7)
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Implement fallbacks for AI failures
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : System prompt should define the LLM's role and task specifications
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-20T09:03:06.318Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-20T09:03:06.318Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use proper error types and logging for failures
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.{ts,tsx} : Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
🧬 Code graph analysis (1)
apps/web/utils/reply-tracker/label-helpers.ts (3)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
ConversationStatus(10-14)apps/web/utils/email/types.ts (1)
EmailProvider(44-237)apps/web/utils/rule/consts.ts (1)
getRuleLabel(122-124)
⏰ 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). (4)
- GitHub Check: Static Code Analysis Js
- GitHub Check: cubic · AI code reviewer
- GitHub Check: Jit Security
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
apps/web/utils/reply-tracker/label-helpers.ts (4)
11-17: LGTM! Type definition supports fallback strategy.The enriched structure storing both
labelIdandlabelenables the intended fallback behavior when one field is missing.
19-46: Function signature updated correctly.The parameter name and type changes align with the new label structure. Logger initialization follows coding guidelines.
94-118: Function setup looks good.Direct fetching of
dbLabelsandproviderLabelsis appropriate for this function's usage pattern. Logger initialization follows coding guidelines.
172-206: Function correctly extracts partial label data.The logic at line 197 stores label objects when either
labelIdorlabelis present, enabling partial-data scenarios. This is correct for faithfully representing DB state, but as noted in earlier comments, the calling functions should be enhanced to resolve missing fields from provider labels before using them.
There was a problem hiding this comment.
Reviewed changes from recent commits (found 2 issues).
2 issues found across 1 file
Prompt for AI agents (all 2 issues)
Understand the root cause of the following 2 issues and fix them.
<file name="apps/web/utils/reply-tracker/label-helpers.ts">
<violation number="1" location="apps/web/utils/reply-tracker/label-helpers.ts:54">
Named labels without an ID skip provider lookup, so conflicting status labels with name-only are never resolved/removed; attempt provider resolution whenever labelId is missing</violation>
<violation number="2" location="apps/web/utils/reply-tracker/label-helpers.ts:145">
Avoid passing an empty labelId into provider.labelMessage; if the provider doesn’t support name fallback this will fail; resolve the labelId or guard the call when only a name is available</violation>
</file>
React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
apps/web/utils/reply-tracker/label-helpers.ts (3)
54-69: Critical: Labels with names but no IDs are never resolved or removed.The condition at line 55 checks
!label.labelId && !label.label, which only resolves labels when both fields are missing. When a label has alabel(name) but nolabelId(e.g., after migrations or partial saves), the provider lookup at lines 56-64 is skipped, and then line 65's check!label.labelIdcauses acontinue, so the label is never added toremoveLabelIds. This breaks the removal of conflicting status labels.Apply this fix to resolve IDs whenever they're missing:
let label = dbLabels[type as ConversationStatus]; - if (!label.labelId && !label.label) { + if (!label.labelId) { const l = providerLabels.find((l) => l.name === getRuleLabel(type)); if (!l?.id) { continue; } label = { labelId: l.id, label: l.name, }; } - if (!label.labelId) { - continue; - } - removeLabelIds.push(label.labelId); + + if (label.labelId) { + removeLabelIds.push(label.labelId); + }
122-141: Critical: Missing label ID resolution when name exists.The condition at line 125 only triggers label fetch/creation when both
labelIdandlabelare missing. IftargetLabelhas alabel(name) but nolabelId(common after migrations), the fetch/create block is skipped, and at line 146 an empty string is passed aslabelId. This breaks label application for entries with names but missing IDs.Fix by always attempting to resolve the ID when it's missing:
let targetLabel = dbLabels[systemType]; - // If we don't have both labelId and label from DB, fetch/create it - if (!targetLabel.labelId && !targetLabel.label) { + // If we don't have labelId from DB, resolve/create it + if (!targetLabel.labelId) { const label = - providerLabels.find((l) => l.name === getRuleLabel(systemType)) || + providerLabels.find((l) => + l.name === (targetLabel.label ?? getRuleLabel(systemType)) + ) || (await provider.createLabel(getRuleLabel(systemType))); if (label) { targetLabel = { labelId: label.id, label: label.name, }; } } - // Error only if we still don't have either field after attempting to fetch/create - if (!targetLabel.labelId && !targetLabel.label) { + // Error only if we still don't have labelId after attempting to fetch/create + if (!targetLabel.labelId) { logger.error("Failed to get or create target label"); return; }
143-155: Critical: Empty string passed as labelId causes provider failures.Line 146 passes
targetLabel.labelId || ""tolabelMessageAndSync, which means an empty string is sent whenlabelIdisnull. Even though providers have fallback support vialabelName, passing an empty string (rather than a valid ID or ensuring the ID is resolved first) is semantically incorrect and may cause failures depending on provider implementation.The fix above (ensuring
labelIdis always resolved before reaching this call) would prevent empty strings from being passed. Alternatively, validate before calling:+ if (!targetLabel.labelId) { + logger.error("Cannot apply label without labelId"); + return; + } + return labelMessageAndSync({ provider, messageId, - labelId: targetLabel.labelId || "", + labelId: targetLabel.labelId, labelName: targetLabel.label, emailAccountId, }).catch((error) =>
🧹 Nitpick comments (2)
apps/web/utils/gmail/label.ts (1)
251-263: Trim the label name before reuse.We already reject empty names based on
trim(), but we still pass the originalname(with possible leading/trailing whitespace) intogetLabel/createLabel. That can create labels whose stored names include stray spaces, or fail to match existing labels with normalized names. Capture the trimmed value once and use it throughout to avoid duplicating labels with superficial whitespace differences.export async function getOrCreateLabel({ gmail, name, }: { gmail: gmail_v1.Gmail; name: string; }) { - if (!name?.trim()) throw new Error("Label name cannot be empty"); - const label = await getLabel({ gmail, name }); + const trimmedName = name?.trim(); + if (!trimmedName) throw new Error("Label name cannot be empty"); + const label = await getLabel({ gmail, name: trimmedName }); if (label) return label; - const createdLabel = await createLabel({ gmail, name }); + const createdLabel = await createLabel({ gmail, name: trimmedName }); return createdLabel; }apps/web/utils/label.server.ts (1)
13-25: Consider validating input parameters.The function accepts
labelId: stringandlabelName: string | nullbut doesn't validate that at least one is meaningful. IflabelIdis an empty string andlabelNameisnull, the provider call at line 34 may fail. Consider adding a guard or documenting the expected input contract.}): Promise<void> { + if (!labelId && !labelName) { + throw new Error("Either labelId or labelName must be provided"); + } + const logger = createScopedLogger("label.server").with({
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
apps/web/utils/ai/actions.ts(3 hunks)apps/web/utils/assistant/process-assistant-email.ts(4 hunks)apps/web/utils/email/google.ts(2 hunks)apps/web/utils/email/microsoft.ts(2 hunks)apps/web/utils/email/types.ts(1 hunks)apps/web/utils/gmail/label.ts(1 hunks)apps/web/utils/label.server.ts(1 hunks)apps/web/utils/reply-tracker/label-helpers.ts(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/utils/assistant/process-assistant-email.ts
🧰 Additional context used
📓 Path-based instructions (11)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use@/for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
apps/web/utils/gmail/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/gmail-api.mdc)
Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Files:
apps/web/utils/gmail/label.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}: UsecreateScopedLoggerfor logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
apps/web/utils/**
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/folder for reusable logic
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
apps/web/utils/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
apps/web/utils/ai/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features
Files:
apps/web/utils/ai/actions.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments
Files:
apps/web/utils/ai/actions.ts
🧠 Learnings (21)
📚 Learning: 2025-07-18T15:05:34.899Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-07-18T15:05:34.899Z
Learning: Applies to apps/web/utils/gmail/**/*.ts : Keep provider-specific implementation details isolated in the appropriate utils subfolder (e.g., 'apps/web/utils/gmail/')
Applied to files:
apps/web/utils/gmail/label.tsapps/web/utils/email/types.tsapps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/email/google.tsapps/web/utils/label.server.tsapps/web/utils/email/microsoft.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Define clear interfaces for complex input/output structures in LLM features
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : System prompt should define the LLM's role and task specifications
Applied to files:
apps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/label.server.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Implement fallbacks for AI failures
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-20T09:03:06.318Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/ultracite.mdc:0-0
Timestamp: 2025-07-20T09:03:06.318Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Don't use unnecessary labels.
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/{ai,llms}/**/*.{ts,tsx} : Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments
Applied to files:
apps/web/utils/reply-tracker/label-helpers.tsapps/web/utils/ai/actions.tsapps/web/utils/label.server.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use proper error types and logging for failures
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : User prompt should contain the actual data and context
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-08T13:14:07.449Z
Learnt from: elie222
Repo: elie222/inbox-zero PR: 537
File: apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx:30-34
Timestamp: 2025-07-08T13:14:07.449Z
Learning: The clean onboarding page in apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx is intentionally Gmail-specific and should show an error for non-Google email accounts rather than attempting to support multiple providers.
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Keep system prompts and user prompts separate
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Format prompt data consistently across similar functions
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Remove excessive whitespace and truncate long inputs in prompts
Applied to files:
apps/web/utils/reply-tracker/label-helpers.ts
📚 Learning: 2025-07-18T17:27:58.249Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.249Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific `emailAccountId` are needed. The `emailAccountId` must be bound when calling the action from the client.
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Place main LLM feature implementations under apps/web/utils/ai/
Applied to files:
apps/web/utils/ai/actions.tsapps/web/utils/label.server.ts
📚 Learning: 2025-07-18T17:27:58.249Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-07-18T17:27:58.249Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `adminActionClient` for actions restricted to admin users.
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use TypeScript types for all parameters and return values in LLM features
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-18T15:04:30.467Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-18T15:04:30.467Z
Learning: Applies to apps/web/app/api/**/route.ts : Use `withEmailAccount` for email-account-level operations
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-19T17:50:28.270Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-19T17:50:28.270Z
Learning: The `utils` folder also contains core app logic such as Next.js Server Actions and Gmail API requests.
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-07-17T04:19:57.099Z
Learnt from: edulelis
Repo: elie222/inbox-zero PR: 576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
Applied to files:
apps/web/utils/ai/actions.ts
📚 Learning: 2025-09-17T22:05:28.646Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-09-17T22:05:28.646Z
Learning: Applies to apps/web/utils/ai/**/*.{ts,tsx} : Use descriptive scoped loggers for each feature
Applied to files:
apps/web/utils/label.server.ts
🧬 Code graph analysis (6)
apps/web/utils/gmail/label.ts (2)
apps/web/utils/outlook/label.ts (3)
getOrCreateLabel(145-157)getLabel(130-143)createLabel(79-119)apps/web/utils/email/google.ts (1)
createLabel(466-479)
apps/web/utils/reply-tracker/label-helpers.ts (4)
apps/web/utils/reply-tracker/conversation-status-config.ts (1)
ConversationStatus(10-14)apps/web/utils/email/types.ts (1)
EmailProvider(44-237)apps/web/utils/rule/consts.ts (1)
getRuleLabel(122-124)apps/web/utils/label.server.ts (1)
labelMessageAndSync(13-72)
apps/web/utils/email/google.ts (2)
apps/web/utils/email/microsoft.ts (1)
labelMessage(334-384)apps/web/utils/gmail/label.ts (2)
labelMessage(129-145)getOrCreateLabel(251-263)
apps/web/utils/ai/actions.ts (1)
apps/web/utils/label.server.ts (1)
labelMessageAndSync(13-72)
apps/web/utils/label.server.ts (2)
apps/web/utils/email/types.ts (1)
EmailProvider(44-237)apps/web/utils/logger.ts (1)
createScopedLogger(17-80)
apps/web/utils/email/microsoft.ts (1)
apps/web/app/api/outlook/webhook/logger.ts (1)
logger(3-3)
⏰ 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: Static Code Analysis Js
- GitHub Check: cubic · AI code reviewer
- GitHub Check: Jit Security
🔇 Additional comments (9)
apps/web/utils/ai/actions.ts (1)
108-114: Nice integration with the sync helper.Routing label execution through
labelMessageAndSync(and threadingemailAccountId) ensures stale IDs heal automatically while preserving the lazy-migration path. Clean upgrade.apps/web/utils/email/types.ts (1)
95-99: Contract update aligns with fallback metadata.Extending the signature to carry
labelNameand return fallback details keeps the provider interface in sync with the new healing flow.apps/web/utils/email/google.ts (1)
270-319: Fallback flow covers stale Gmail IDs.Catching the “not found” error, resolving/creating by name, and returning
usedFallbackplusactualLabelIdgives labelMessageAndSync everything it needs to repair persisted actions without hiding unexpected exceptions. Nicely done.apps/web/utils/email/microsoft.ts (1)
334-384: Parity with Outlook fallback looks solid.The ID→name fallback keeps Outlook labeling resilient and the returned metadata matches the shared contract, so downstream sync logic can behave consistently.
apps/web/utils/label.server.ts (3)
1-3: LGTM: Imports follow best practices.Clean imports using
import typefor types, proper path aliases (@/utils), and correct Prisma import pattern.
26-32: LGTM: Proper logger initialization.Correctly uses
createScopedLoggerat the function level with.with()to add context, as per coding guidelines.
34-71: LGTM: Fallback handling is well-implemented.The function correctly detects when a label ID fallback occurred, logs the stale ID detection, and updates all affected Actions in the database. The intentional error catching without rethrowing (line 64-70) ensures the labeling operation succeeds even if the DB sync fails, which is appropriate.
apps/web/utils/reply-tracker/label-helpers.ts (2)
12-18: LGTM: Type definition supports the new label structure.The
LabelIdstype appropriately models label data with bothlabelIdandlabelfields, allowing for partial information where either field may be null.
173-207: LGTM: Label fetching correctly restructured.The renamed
getLabelsFromDbfunction properly initializes all status types with null values and populates them from the database, correctly handling cases where eitherlabelIdorlabelmay be present.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/web/utils/reply-tracker/label-helpers.test.ts (1)
19-33: Consider assertinglabelMessagereturn values.The mock for
labelMessage(line 21) returnsundefined, but per the AI summary, the implementation now returns additional information (usedFallbackandactualLabelId). IfapplyThreadStatusLabeluses these return values, consider updating the mock to return realistic values and adding assertions to verify the function handles the response correctly.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/utils/reply-tracker/label-helpers.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use@/for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
!{.cursor/rules/*.mdc}
📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)
Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)
**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
**/*.{ts,tsx}: UsecreateScopedLoggerfor logging in backend TypeScript files
Typically add the logger initialization at the top of the file when usingcreateScopedLogger
Only use.with()on a logger instance within a specific function, not for a global loggerImport Prisma in the project using
import prisma from "@/utils/prisma";
**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.test.{ts,js}
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
Include security tests in your test suites to verify authentication, authorization, and error handling.
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
apps/web/utils/**
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Create utility functions in
utils/folder for reusable logic
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
apps/web/utils/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useelements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
!pages/_document.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.{test,spec}.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{test,spec}.{js,jsx,ts,tsx}: Don't use export or module.exports in test files.
Don't use focused tests.
Don't use disabled tests.
Make sure the assertion function, like expect, is placed inside an it() function call.
Don't nest describe() blocks too deeply in test files.
Don't use focused tests.
Don't use disabled tests.
Don't use export or module.exports in test files.
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)
**/*.test.{ts,tsx}: Use Vitest (vitest) as the testing framework
Colocate tests next to the file under test (e.g., dir/format.ts with dir/format.test.ts)
In tests, mock theserver-onlymodule withvi.mock("server-only", () => ({}));
When testing code that uses Prisma, mock it withvi.mock("@/utils/prisma")and use the mock from@/utils/__mocks__/prisma
Use provided helpers for mocks: import{ getEmail, getEmailAccount, getRule }from@/__tests__/helpers
Each test should be independent
Use descriptive test names
Mock external dependencies in tests
Clean up mocks between tests (e.g.,vi.clearAllMocks()inbeforeEach)
Avoid testing implementation details; focus on observable behavior
Do not mock the Logger
Files:
apps/web/utils/reply-tracker/label-helpers.test.ts
🧠 Learnings (2)
📚 Learning: 2025-10-02T23:23:48.064Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-10-02T23:23:48.064Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Prefer existing helpers from @/__tests__/helpers.ts (getEmailAccount, getEmail, getRule, getMockMessage, getMockExecutedRule) over custom helpers
Applied to files:
apps/web/utils/reply-tracker/label-helpers.test.ts
📚 Learning: 2025-09-20T18:24:34.280Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-09-20T18:24:34.280Z
Learning: Applies to **/*.test.{ts,tsx} : Use provided helpers for mocks: import `{ getEmail, getEmailAccount, getRule }` from `@/__tests__/helpers`
Applied to files:
apps/web/utils/reply-tracker/label-helpers.test.ts
⏰ 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: cubic · AI code reviewer
- GitHub Check: test
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores