Skip to content

Comments

Refactor thread workflow to use modular workflow engine#1852

Merged
MrgSub merged 1 commit intostagingfrom
ZERORefactor_thread_workflow_to_use_modular_workflow_engine
Jul 28, 2025
Merged

Refactor thread workflow to use modular workflow engine#1852
MrgSub merged 1 commit intostagingfrom
ZERORefactor_thread_workflow_to_use_modular_workflow_engine

Conversation

@MrgSub
Copy link
Collaborator

@MrgSub MrgSub commented Jul 28, 2025

Refactored Thread Processing with Workflow Engine Architecture

Description

Implemented a modular workflow engine architecture for thread processing, replacing the monolithic approach with a flexible, configurable system. This refactoring moves hardcoded business logic into reusable workflow steps that can be composed and executed dynamically, improving maintainability and extensibility.

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🎨 UI/UX improvement
  • ⚡ Performance improvement

Areas Affected

  • Email Integration (Gmail, IMAP, etc.)
  • Data Storage/Management
  • Development Workflow

Testing Done

  • Manual testing performed

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in complex areas
  • I have updated the documentation
  • My changes generate no new warnings

Additional Notes

The new workflow engine provides several key benefits:

  • Type-safe workflow configuration with TypeScript
  • Modular functions that can be tested independently
  • Configurable error handling per workflow step
  • Reusable components shared between workflows
  • Cleaner separation of concerns in the main pipeline

The implementation includes comprehensive documentation in the README.md file explaining the architecture and how to extend it with new workflows.

Summary by CodeRabbit

  • New Features

    • Introduced a modular workflow engine for automated email thread processing, including draft generation, message vectorization, summarization, and label generation.
    • Added comprehensive documentation for the new workflow engine, outlining its architecture and usage.
  • Refactor

    • Simplified thread workflow processing by delegating tasks to the new workflow engine, replacing previous inline logic.
    • Streamlined thread listing logic for improved consistency.
    • Updated label modification methods to apply changes concurrently per thread for improved performance.
    • Centralized XML escaping utility by replacing local implementations with shared module usage.
  • Bug Fixes

    • Corrected database queries to reference the correct thread identifier column.
  • Chores

    • Disabled certain thread label management methods that are no longer in use.
    • Added error handling and connection reset logic for Gmail subscription setup failures.
    • Introduced a utility to reset connection tokens in the database for improved error recovery.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
XSS Vulnerability in User Label Names High Create a label with the name <img src=x onerror=alert('XSS')>. Send an email to the account. Observe that the XSS payload is triggered. The name property of user labels is not properly sanitized, which could lead to a stored Cross-Site Scripting (XSS) vulnerability.
Incorrect Retry Logic Medium Create a workflow with a step that sends an email and has errorHandling: 'retry' and maxRetries: 3. Simulate an error during the email sending process. Observe that the email is sent multiple times. The retry logic can lead to problems if the step.action has side effects.
Missing Error Handling and Potential Data Loss Medium Create a workflow that relies on the searchThreads function. Attempt to execute the workflow. Observe that the workflow fails because the searchThreads function is no longer available. The core logic for processing a thread has been replaced with a call to the workflow engine. However, the error handling for the workflow engine itself seems limited.
Potential Race Condition in Label Application Medium Simultaneously trigger two calls to modifyThreadLabelsInDB for the same threadId, with different sets of labels to add or remove. Concurrent calls to modifyThreadLabelsInDB could overwrite each other's changes due to a race condition.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a modular workflow engine for processing email threads, replacing the previous inline logic for draft generation, vectorization, summarization, and labeling. New workflow utilities and functions are added, with documentation. Several methods are refactored or commented out, and some SQL queries are corrected for thread ID consistency.

Changes

Cohort / File(s) Change Summary
Workflow Engine & Utilities
apps/server/src/thread-workflow-utils/workflow-engine.ts, apps/server/src/thread-workflow-utils/workflow-functions.ts, apps/server/src/thread-workflow-utils/README.md
Adds a modular, type-safe workflow engine system with reusable workflow functions for thread processing (drafts, vectorization, summarization, labeling). Includes new types, engine class, default workflows, utility functions, and comprehensive documentation.
Thread Workflow Refactor
apps/server/src/pipelines.effect.ts
Refactors runThreadWorkflow to delegate processing to the workflow engine, removing inline logic for drafts, vectorization, summarization, and labeling. Updates error types and removes obsolete helper functions.
Agent Route Adjustments
apps/server/src/routes/agent/index.ts
Comments out markThreadsRead and markThreadsUnread methods, updates SQL queries to use thread_id instead of id, and adds a log statement to dropTables.
Agent RPC Refactor
apps/server/src/routes/agent/rpc.ts
Refactors label modification methods to call database update functions directly in parallel. Removes the skipSync parameter.
Mail Router Query Simplification
apps/server/src/trpc/routes/mail.ts
Simplifies the listThreads query logic to always use agent.rawListThreads, removing conditional branches and related debug logs.
Thread Workflow Utilities
apps/server/src/thread-workflow-utils/workflow-utils.ts
Adds XML conversion and participant extraction utilities for thread messages, supporting safe XML escaping and asynchronous processing.
AI Compose Route
apps/server/src/trpc/routes/ai/compose.ts
Replaces a local XML escape function with an import from the new centralized workflow utilities module.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Server
    participant WorkflowEngine
    participant WorkflowFunctions
    participant Agent
    participant AIService
    participant Database

    User->>Server: Trigger runThreadWorkflow
    Server->>WorkflowEngine: Initialize and execute workflows
    loop For each workflow
        WorkflowEngine->>WorkflowFunctions: Execute workflow steps
        alt Draft Generation
            WorkflowFunctions->>AIService: Analyze intent, generate draft
            WorkflowFunctions->>Agent: Create draft
        else Message Vectorization
            WorkflowFunctions->>AIService: Summarize, embed messages
            WorkflowFunctions->>Database: Upsert embeddings
        else Thread Summary
            WorkflowFunctions->>AIService: Generate summary
            WorkflowFunctions->>Database: Upsert summary
        else Label Generation
            WorkflowFunctions->>AIService: Generate labels
            WorkflowFunctions->>Agent: Apply labels
        end
    end
    WorkflowEngine->>Server: Return results & errors
    Server->>User: Log and respond
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

high priority

Poem

🚀
Threads once tangled, now aligned,
Engines hum with code refined.
Drafts and labels, AI’s art,
Vectorized and set apart.
Modular flows, future bright,
Email magic, taking flight!
🌠


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9f94e6 and e0643a3.

📒 Files selected for processing (12)
  • apps/server/src/lib/brain.ts (3 hunks)
  • apps/server/src/lib/factories/google-subscription.factory.ts (3 hunks)
  • apps/server/src/lib/server-utils.ts (2 hunks)
  • apps/server/src/pipelines.effect.ts (3 hunks)
  • apps/server/src/routes/agent/index.ts (5 hunks)
  • apps/server/src/routes/agent/rpc.ts (3 hunks)
  • apps/server/src/thread-workflow-utils/README.md (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-engine.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-functions.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-utils.ts (1 hunks)
  • apps/server/src/trpc/routes/ai/compose.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ZERORefactor_thread_workflow_to_use_modular_workflow_engine

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:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • 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
Collaborator Author

MrgSub commented Jul 28, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@MrgSub MrgSub marked this pull request as ready for review July 28, 2025 19:28
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai coderabbitai bot added content design Improvements & changes to design & UX labels Jul 28, 2025
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bugbot free trial expires on July 29, 2025
Learn more in the Cursor dashboard.

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

🔭 Outside diff range comments (1)
apps/server/src/pipelines.effect.ts (1)

826-870: Remove unused threadToXML function

This function is no longer used after the workflow engine refactor. Delete it to keep the codebase clean.

♻️ Duplicate comments (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)

11-58: More code duplication

As mentioned in workflow-functions.ts, these utility functions need to be extracted to a shared module.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 180133f and 8acbaf8.

📒 Files selected for processing (7)
  • apps/server/src/pipelines.effect.ts (3 hunks)
  • apps/server/src/routes/agent/index.ts (5 hunks)
  • apps/server/src/routes/agent/rpc.ts (4 hunks)
  • apps/server/src/thread-workflow-utils/README.md (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-engine.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-functions.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters in width
Semicolons are required

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: JagjeevanAK
PR: Mail-0/Zero#1583
File: apps/docs/package.json:1-0
Timestamp: 2025-07-01T12:53:32.495Z
Learning: The Zero project prefers to handle dependency updates through automated tools like Dependabot rather than immediate manual updates, allowing for proper testing and validation through their established workflow.
apps/server/src/trpc/routes/mail.ts (5)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

apps/server/src/routes/agent/rpc.ts (3)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

apps/server/src/routes/agent/index.ts (2)

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

apps/server/src/thread-workflow-utils/workflow-functions.ts (1)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

apps/server/src/thread-workflow-utils/workflow-engine.ts (1)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

apps/server/src/pipelines.effect.ts (1)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

🧬 Code Graph Analysis (1)
apps/server/src/pipelines.effect.ts (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)
  • createDefaultWorkflows (180-464)
🪛 LanguageTool
apps/server/src/thread-workflow-utils/README.md

[grammar] ~1-~1: Use correct spacing
Context: # Thread Workflow Engine This module provides a flexible workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~3-~3: Use correct spacing
Context: ...and executed through a modular function registry. ## Architecture ### Components 1. **Workf...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~7-~7: Use correct spacing
Context: ...unction registry. ## Architecture ### Components 1. WorkflowEngine (workflow-engine.ts) ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~9-~9: There might be a mistake here.
Context: ... ### Components 1. WorkflowEngine (workflow-engine.ts) - Core engine that executes workflows...

(QB_NEW_EN_OTHER)


[grammar] ~9-~9: Use correct spacing
Context: ...WorkflowEngine* (workflow-engine.ts) - Core engine that executes workflows 2. *...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~10-~10: There might be a mistake here.
Context: ...es workflows 2. Workflow Functions (workflow-functions.ts) - Registry of individual workflow fun...

(QB_NEW_EN_OTHER)


[grammar] ~10-~10: Use correct spacing
Context: ...ow Functions** (workflow-functions.ts) - Registry of individual workflow function...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~11-~11: There might be a problem here.
Context: ...ividual workflow functions 3. Default Workflows - Pre-configured workflows in createDefaultWorkflows()...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~11-~11: There might be a problem here.
Context: ... Workflows** - Pre-configured workflows in createDefaultWorkflows() 4. Workflow Context - Shared context passed between workflow steps ...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~12-~12: Use correct spacing
Context: ... Shared context passed between workflow steps ### Key Benefits - **Type-Safe Configuratio...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~14-~14: Use correct spacing
Context: ... passed between workflow steps ### Key Benefits - Type-Safe Configuration: Workflows are...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~16-~16: There might be a mistake here.
Context: ...t, providing better type safety and IDE support - Modular Functions: Each workflow step ...

(QB_NEW_EN_OTHER)


[grammar] ~17-~17: There might be a mistake here.
Context: ... a separate function that can be tested independently - Error Handling: Configurable error han...

(QB_NEW_EN_OTHER)


[grammar] ~18-~18: There might be a mistake here.
Context: ...rror handling per step (continue, fail, retry) - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~19-~19: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Clean Separation: The main pipeline is...

(QB_NEW_EN_OTHER)


[grammar] ~20-~20: There might be a problem here.
Context: ...line is now much cleaner and focused on orchestration ## Usage ### Defining a Workflow Workflows are defin...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~24-~24: Use correct spacing
Context: ...orchestration ## Usage ### Defining a Workflow Workflows are defined in the `createDefa...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~26-~26: There might be a mistake here.
Context: ... createDefaultWorkflows() function in workflow-engine.ts: typescript const autoDraftWorkflow: WorkflowDefinition = { name: 'auto-draft-generation', description: 'Automatically generates drafts for threads that require responses', steps: [ { id: 'check-draft-eligibility', name: 'Check Draft Eligibility', description: 'Determines if a draft should be generated for this thread', enabled: true, condition: async (context) => { return shouldGenerateDraft(context.thread, context.foundConnection); }, action: async (context) => { console.log('[WORKFLOW_ENGINE] Thread eligible for draft generation', context); return { eligible: true }; }, }, // ... more steps ], }; engine.registerWorkflow(autoDraftWorkflow); ### Adding a New W...

(QB_NEW_EN_OTHER)


[grammar] ~53-~53: Use correct spacing
Context: ...rkflow); ``` ### Adding a New Workflow Function 1. Add the function to `workflow-functions....

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~55-~55: There might be a mistake here.
Context: ...rkflow Function 1. Add the function to workflow-functions.ts: typescript export const workflowFunctions: Record<string, WorkflowFunction> = { // ... existing functions ... myNewFunction: async (context) => { // Your logic here console.log('[WORKFLOW_FUNCTIONS] Executing my new function'); // Access previous step results const previousResult = context.results?.get('previous-step-id'); // Return result for next steps return { success: true, data: 'some data' }; }, }; 2. Add the step to your w...

(QB_NEW_EN_OTHER)


[grammar] ~74-~74: There might be a mistake here.
Context: ...the step to your workflow definition in createDefaultWorkflows(): typescript { id: 'my-new-step', name: 'My New Step', description: 'Description of what this step does', enabled: true, action: async (context) => { // Your logic here return { success: true }; }, errorHandling: 'continue', } ### Workflow Context Each wo...

(QB_NEW_EN_OTHER)


[grammar] ~90-~90: Use correct spacing
Context: ...ndling: 'continue', } ``` ### Workflow Context Each workflow function receives a contex...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~92-~92: There might be a mistake here.
Context: ...flow function receives a context object with: typescript type WorkflowContext = { connectionId: string; threadId: string; thread: IGetThreadResponse; foundConnection: typeof connection.$inferSelect; agent: any; env: any; results?: Map<string, any>; // Results from previous steps }; ### Error Handling Each step c...

(QB_NEW_EN_OTHER)


[grammar] ~106-~106: Use correct spacing
Context: ...s from previous steps }; ``` ### Error Handling Each step can have different error handl...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~108-~108: Use hyphens correctly
Context: ... Handling Each step can have different error handling strategies: - "continue" - S...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~108-~108: There might be a mistake here.
Context: ... step can have different error handling strategies: - "continue" - Skip failed steps and continue with ...

(QB_NEW_EN_OTHER)


[grammar] ~110-~110: Use hyphens correctly
Context: ...Skip failed steps and continue with the workflow - "fail" - Stop the entire workflow on error - `"...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~111-~111: Use hyphens correctly
Context: ... "fail" - Stop the entire workflow on error - "retry" - Retry the step up to maxRetries time...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~112-~112: There might be a mistake here.
Context: ...y"- Retry the step up tomaxRetries` times ### Example: Adding a New Workflow 1. **Def...

(QB_NEW_EN_OTHER)


[grammar] ~114-~114: Use correct spacing
Context: ...triestimes ### Example: Adding a New Workflow 1. **Define the workflow increateDefaultWor...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~116-~116: There might be a mistake here.
Context: ...w Workflow 1. Define the workflow in createDefaultWorkflows(): typescript const customWorkflow: WorkflowDefinition = { name: 'custom-processing', description: 'Custom thread processing workflow', steps: [ { id: 'custom-step-1', name: 'Custom Step 1', description: 'First custom processing step', enabled: true, action: async (context) => { console.log('[WORKFLOW_ENGINE] Executing custom step 1'); // Your custom logic here return { processed: true }; }, errorHandling: 'continue', }, { id: 'custom-step-2', name: 'Custom Step 2', description: 'Second custom processing step', enabled: true, action: async (context) => { const step1Result = context.results?.get('custom-step-1'); console.log('[WORKFLOW_ENGINE] Executing custom step 2 with result:', step1Result); // Your custom logic here return { completed: true }; }, errorHandling: 'retry', maxRetries: 3, }, ], }; engine.registerWorkflow(customWorkflow); 2. **Th...

(QB_NEW_EN_OTHER)


[grammar] ~155-~155: There might be a problem here.
Context: ...2. The workflow will be automatically executed - no need to update any other configuration! ###...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~155-~155: Use correct spacing
Context: ...xecuted** - no need to update any other configuration! ### Dynamic Workflow Discovery The workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~157-~157: Use correct spacing
Context: ...er configuration! ### Dynamic Workflow Discovery The workflow engine automatically discov...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~159-~159: There might be a mistake here.
Context: ...y discovers and executes all registered workflows: typescript // Get all available workflow names from the engine const workflowNames = workflowEngine.getWorkflowNames(); // Execute all workflows dynamically for (const workflowName of workflowNames) { const { results, errors } = await workflowEngine.executeWorkflow(workflowName, context); } This means: - **No hardcoded...

(QB_NEW_EN_OTHER)


[grammar] ~171-~171: There might be a mistake here.
Context: ...low(workflowName, context); } ``` This means: - No hardcoded workflow lists: Workflow...

(QB_NEW_EN_OTHER)


[grammar] ~173-~173: There might be a mistake here.
Context: ...kflow lists**: Workflows are discovered automatically - Easy to add new workflows: Just regist...

(QB_NEW_EN_OTHER)


[grammar] ~174-~174: There might be a mistake here.
Context: ...add new workflows**: Just register them in createDefaultWorkflows() - Conditional workflows: Can be enabled/...

(QB_NEW_EN_OTHER)


[grammar] ~175-~175: There might be a mistake here.
Context: ...workflows**: Can be enabled/disabled at runtime - Future-proof: New workflows are automa...

(QB_NEW_EN_OTHER)


[grammar] ~176-~176: There might be a mistake here.
Context: ...roof**: New workflows are automatically included ## Migration from Hardcoded Logic The orig...

(QB_NEW_EN_OTHER)


[grammar] ~178-~178: Use correct spacing
Context: ...y included ## Migration from Hardcoded Logic The original hardcoded logic in `runThre...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~180-~180: There might be a mistake here.
Context: ...n runThreadWorkflow has been replaced with: 1. Workflow Engine: Orchestrates the exe...

(QB_NEW_EN_OTHER)


[grammar] ~185-~185: Use correct spacing
Context: ...aring**: Allows steps to share data and results This makes the system much more maintain...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~187-~187: Use correct spacing
Context: ...eps without modifying the core pipeline logic. ## Benefits - Cleaner Code: The main p...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~191-~191: There might be a mistake here.
Context: ...d on orchestration rather than business logic - Easier Testing: Each workflow function...

(QB_NEW_EN_OTHER)


[grammar] ~192-~192: There might be a mistake here.
Context: ...*: Each workflow function can be tested independently - Flexible Configuration: Workflows can ...

(QB_NEW_EN_OTHER)


[grammar] ~193-~193: Use proper capitalization
Context: ...an be enabled/disabled and modified via JSON - Better Error Handling: Granular error ...

(QB_NEW_EN_OTHER_ERROR_IDS_6)


[grammar] ~194-~194: There might be a mistake here.
Context: ...Handling**: Granular error handling per step - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~195-~195: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Maintainability: Adding new processing...

(QB_NEW_EN_OTHER)


[grammar] ~196-~196: There might be a mistake here.
Context: ...teps doesn't require modifying the main pipeline

(QB_NEW_EN_OTHER)

🪛 markdownlint-cli2 (0.17.2)
apps/server/src/thread-workflow-utils/README.md

74-74: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)


155-155: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)

🪛 GitHub Actions: autofix.ci
apps/server/src/trpc/routes/mail.ts

[warning] 31-31: ESLint (no-unused-vars): Variable 'getFolderLabelId' is declared but never used. Unused variables should start with a '_'.

apps/server/src/pipelines.effect.ts

[warning] 826-826: ESLint (no-unused-vars): Variable 'threadToXML' is declared but never used. Unused variables should start with a '_'.

⏰ 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: Cursor Bugbot
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (11)
apps/server/src/routes/agent/index.ts (3)

810-810: Excellent logging addition - like adding telemetry to our rockets before launch!

This debug log provides crucial visibility into table operations. Sometimes the simplest changes make the biggest operational difference.


581-581: Critical bug fix identified - like fixing a navigation error on Mars mission!

Changing from id to thread_id in the WHERE clause is absolutely correct. The schema shows id is the PRIMARY KEY while thread_id is the actual thread identifier. This fix ensures we're querying the right records - mission critical for thread operations.


1619-1619: Another mission-critical navigation fix! These WHERE clause corrections are like updating our spacecraft's guidance system.

Both database queries now correctly use thread_id instead of id, ensuring consistent thread identification across all operations. This level of attention to detail is what makes rockets land successfully!

Also applies to: 1653-1653

apps/server/src/thread-workflow-utils/README.md (1)

1-197: Outstanding documentation! This README is like a comprehensive mission manual for SpaceX engineers.

This documentation brilliantly explains the modular workflow architecture, providing clear examples and migration guidance. The level of detail here rivals the best technical docs at Tesla - developers will actually want to read this!

Key strengths:

  • Clear architecture explanation with concrete examples
  • Step-by-step workflow creation guide
  • Proper error handling strategies
  • Migration benefits clearly articulated
  • Dynamic workflow discovery explanation

The static analysis warnings are just markdown formatting false positives - ignore them completely. This documentation quality is what makes complex systems maintainable.

apps/server/src/routes/agent/rpc.ts (3)

106-109: LGTM!

Correct implementation for marking threads as unread by adding the UNREAD label.


115-122: Good simplification of the API

Removing the skipSync parameter and centralizing the sync logic based on shouldReSyncThreadsAfterActions is a cleaner approach.


159-162: Correct implementation

Properly adds UNREAD label to mark threads as unread.

apps/server/src/pipelines.effect.ts (2)

500-501: Good error handling addition

Adding WorkflowCreationFailed to the error union type properly handles workflow initialization failures.


563-613: Excellent modular architecture

This workflow engine approach is much cleaner than hardcoded logic. Good separation of concerns and error handling.

apps/server/src/thread-workflow-utils/workflow-functions.ts (1)

85-105: Smart intent-based response validation

Good implementation that checks multiple signals to determine if an email needs a response.

apps/server/src/thread-workflow-utils/workflow-engine.ts (1)

106-178: Brilliant workflow engine design

This is exactly how a workflow engine should work - modular, extensible, with proper error handling strategies. The retry mechanism and conditional execution are particularly well done.

Copy link
Contributor

@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

3 issues 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.

@MrgSub MrgSub force-pushed the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch from 8acbaf8 to bd24220 Compare July 28, 2025 20:29
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

An error occured.

This error may be due to rate limits. If this error persists, please email us.

@coderabbitai coderabbitai bot added the High Priority High Priority Work label Jul 28, 2025
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name: Incomplete Workflow Results due to Conditional Execution
Severity: Medium
Example test case: A workflow has two steps, A and B. Step B depends on the result of Step A. Step A has a condition that is sometimes false. When the condition is false, Step A is skipped, and Step B will not have the result of A available in the context.
Description: The condition function receives the original context but the action function receives the context augmented with results. If the step is skipped due to the condition not being met, the results of the workflow will be incomplete. Any action that depends on that result will fail.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Incorrect Removal of AI Labels Medium 1. Create a thread with labels 'AI:Important' (AI managed) and 'Project:Alpha'. 2. Remove the 'AI:Important' from User Labels. 3. Reprocess the thread so that new labels are generated. The applyLabels function does not remove AI-managed labels that are not present in the current set of User Labels, leading to stale AI labels remaining on threads.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

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

🔭 Outside diff range comments (2)
apps/server/src/routes/agent/rpc.ts (1)

93-100: Code duplication detected - not optimal for maintainability

markThreadsRead and markAsRead have identical implementations. Same story with markThreadsUnread and markAsUnread. This violates DRY principles.

  async markAsRead(threadIds: string[]) {
-    const result = await Promise.all(
-      threadIds.map((id) => this.mainDo.modifyThreadLabelsInDB(id, [], ['UNREAD'])),
-    );
-    if (shouldReSyncThreadsAfterActions)
-      await Promise.all(threadIds.map((id) => this.mainDo.syncThread({ threadId: id })));
-    return result;
+    return this.markThreadsRead(threadIds);
  }

  async markAsUnread(threadIds: string[]) {
-    const result = await Promise.all(
-      threadIds.map((id) => this.mainDo.modifyThreadLabelsInDB(id, ['UNREAD'], [])),
-    );
-    if (shouldReSyncThreadsAfterActions)
-      await Promise.all(threadIds.map((id) => this.mainDo.syncThread({ threadId: id })));
-    return result;
+    return this.markThreadsUnread(threadIds);
  }

Also applies to: 150-157

apps/server/src/thread-workflow-utils/workflow-utils.ts (1)

1-103: Solid utility functions with proper error handling

Good extraction of these XML utilities into a dedicated module. The error handling is comprehensive and the Map-based deduplication in getParticipants is efficient.

One area for improvement: stronger typing instead of any.

-export const messageToXML = async (message: ParsedMessage | any) => {
+export const messageToXML = async (message: ParsedMessage) => {

-export const getParticipants = (messages: ParsedMessage[] | any[]) => {
+export const getParticipants = (messages: ParsedMessage[]) => {

-export const threadToXML = async (messages: ParsedMessage[] | any[], existingSummary?: string) => {
+export const threadToXML = async (messages: ParsedMessage[], existingSummary?: string) => {
♻️ Duplicate comments (6)
apps/server/src/trpc/routes/mail.ts (1)

31-33: Clean up the unused function - like removing dead weight from a spacecraft!

The linter is flagging the unused getFolderLabelId function. Since we've standardized on agent.rawListThreads(), this helper function is no longer needed and should be removed to keep the codebase clean.

apps/server/src/routes/agent/index.ts (1)

639-657: Remove the commented rocket parts - they're just adding mass to our spacecraft!

These commented-out markThreadsRead and markThreadsUnread methods are creating code clutter. They've been replaced by other implementations and should be completely removed rather than left as commented code.

apps/server/src/routes/agent/rpc.ts (1)

256-264: Dead code without explanation - needs clarity

The searchThreads method is fully commented out with no context. This creates confusion and technical debt.

apps/server/src/thread-workflow-utils/workflow-functions.ts (1)

1-528: Comprehensive workflow functions with solid architecture

This is how you build scalable systems. Each workflow function has a single responsibility, proper error handling, and detailed logging. The use of Effect for functional error handling in vectorization is particularly elegant.

The batching implementation with concurrency limits prevents overwhelming the AI service - smart move. Though we should make these limits configurable for different environments.

apps/server/src/thread-workflow-utils/workflow-engine.ts (2)

83-83: Results map still not passed to condition - this is a showstopper

This exact issue was already flagged. The condition function needs access to previous step results for proper decision making.

-        const shouldExecute = step.condition ? await step.condition(context) : true;
+        const shouldExecute = step.condition ? await step.condition({ ...context, results }) : true;

143-144: Don't log the entire context - massive privacy risk

This is like broadcasting your private keys on Twitter. We can't be logging sensitive user data.

-          console.log('[WORKFLOW_ENGINE] Thread eligible for draft generation', context);
+          console.log('[WORKFLOW_ENGINE] Thread eligible for draft generation', {
+            threadId: context.threadId,
+            connectionId: context.connectionId
+          });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8acbaf8 and bd24220.

📒 Files selected for processing (9)
  • apps/server/src/pipelines.effect.ts (3 hunks)
  • apps/server/src/routes/agent/index.ts (5 hunks)
  • apps/server/src/routes/agent/rpc.ts (3 hunks)
  • apps/server/src/thread-workflow-utils/README.md (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-engine.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-functions.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-utils.ts (1 hunks)
  • apps/server/src/trpc/routes/ai/compose.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters in width
Semicolons are required

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/pipelines.effect.ts
🧠 Learnings (7)
apps/server/src/trpc/routes/ai/compose.ts (1)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

apps/server/src/trpc/routes/mail.ts (5)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

apps/server/src/routes/agent/index.ts (3)

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/routes/agent/rpc.ts (4)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/thread-workflow-utils/workflow-functions.ts (3)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: ripgrim
PR: #706
File: apps/mail/lib/ai.ts:34-48
Timestamp: 2025-04-21T21:33:10.581Z
Learning: Rate limiting for AI generation functionality is already implemented in the codebase, so additional rate limiting solutions are not needed.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

apps/server/src/thread-workflow-utils/workflow-engine.ts (2)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/pipelines.effect.ts (1)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

🧬 Code Graph Analysis (3)
apps/server/src/thread-workflow-utils/workflow-utils.ts (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)
  • htmlToText (7-24)
apps/server/src/thread-workflow-utils/workflow-engine.ts (5)
apps/server/src/pipelines.effect.ts (1)
  • htmlToText (678-695)
apps/server/src/lib/driver/types.ts (1)
  • IGetThreadResponse (6-12)
apps/server/src/db/schema.ts (1)
  • connection (118-142)
apps/server/src/thread-workflow-utils/index.ts (1)
  • shouldGenerateDraft (110-110)
apps/server/src/thread-workflow-utils/workflow-functions.ts (1)
  • workflowFunctions (19-457)
apps/server/src/pipelines.effect.ts (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)
  • createDefaultWorkflows (127-276)
🪛 LanguageTool
apps/server/src/thread-workflow-utils/README.md

[grammar] ~1-~1: Use correct spacing
Context: # Thread Workflow Engine This module provides a flexible workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~3-~3: Use correct spacing
Context: ...and executed through a modular function registry. ## Architecture ### Components 1. **Workf...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~7-~7: Use correct spacing
Context: ...unction registry. ## Architecture ### Components 1. WorkflowEngine (workflow-engine.ts) ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~9-~9: There might be a mistake here.
Context: ... ### Components 1. WorkflowEngine (workflow-engine.ts) - Core engine that executes workflows...

(QB_NEW_EN_OTHER)


[grammar] ~9-~9: Use correct spacing
Context: ...WorkflowEngine* (workflow-engine.ts) - Core engine that executes workflows 2. *...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~10-~10: There might be a mistake here.
Context: ...es workflows 2. Workflow Functions (workflow-functions.ts) - Registry of individual workflow fun...

(QB_NEW_EN_OTHER)


[grammar] ~10-~10: Use correct spacing
Context: ...ow Functions** (workflow-functions.ts) - Registry of individual workflow function...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~11-~11: There might be a problem here.
Context: ...ividual workflow functions 3. Default Workflows - Pre-configured workflows in createDefaultWorkflows()...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~11-~11: There might be a problem here.
Context: ... Workflows** - Pre-configured workflows in createDefaultWorkflows() 4. Workflow Context - Shared context passed between workflow steps ...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~12-~12: Use correct spacing
Context: ... Shared context passed between workflow steps ### Key Benefits - **Type-Safe Configuratio...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~14-~14: Use correct spacing
Context: ... passed between workflow steps ### Key Benefits - Type-Safe Configuration: Workflows are...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~16-~16: There might be a mistake here.
Context: ...t, providing better type safety and IDE support - Modular Functions: Each workflow step ...

(QB_NEW_EN_OTHER)


[grammar] ~17-~17: There might be a mistake here.
Context: ... a separate function that can be tested independently - Error Handling: Configurable error han...

(QB_NEW_EN_OTHER)


[grammar] ~18-~18: There might be a mistake here.
Context: ...rror handling per step (continue, fail, retry) - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~19-~19: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Clean Separation: The main pipeline is...

(QB_NEW_EN_OTHER)


[grammar] ~20-~20: There might be a problem here.
Context: ...line is now much cleaner and focused on orchestration ## Usage ### Defining a Workflow Workflows are defin...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~24-~24: Use correct spacing
Context: ...orchestration ## Usage ### Defining a Workflow Workflows are defined in the `createDefa...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~26-~26: There might be a mistake here.
Context: ... createDefaultWorkflows() function in workflow-engine.ts: typescript const autoDraftWorkflow: WorkflowDefinition = { name: 'auto-draft-generation', description: 'Automatically generates drafts for threads that require responses', steps: [ { id: 'check-draft-eligibility', name: 'Check Draft Eligibility', description: 'Determines if a draft should be generated for this thread', enabled: true, condition: async (context) => { return shouldGenerateDraft(context.thread, context.foundConnection); }, action: async (context) => { console.log('[WORKFLOW_ENGINE] Thread eligible for draft generation', context); return { eligible: true }; }, }, // ... more steps ], }; engine.registerWorkflow(autoDraftWorkflow); ### Adding a New W...

(QB_NEW_EN_OTHER)


[grammar] ~53-~53: Use correct spacing
Context: ...rkflow); ``` ### Adding a New Workflow Function 1. Add the function to `workflow-functions....

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~55-~55: There might be a mistake here.
Context: ...rkflow Function 1. Add the function to workflow-functions.ts: typescript export const workflowFunctions: Record<string, WorkflowFunction> = { // ... existing functions ... myNewFunction: async (context) => { // Your logic here console.log('[WORKFLOW_FUNCTIONS] Executing my new function'); // Access previous step results const previousResult = context.results?.get('previous-step-id'); // Return result for next steps return { success: true, data: 'some data' }; }, }; 2. Add the step to your w...

(QB_NEW_EN_OTHER)


[grammar] ~74-~74: There might be a mistake here.
Context: ...the step to your workflow definition in createDefaultWorkflows(): typescript { id: 'my-new-step', name: 'My New Step', description: 'Description of what this step does', enabled: true, action: async (context) => { // Your logic here return { success: true }; }, errorHandling: 'continue', } ### Workflow Context Each wo...

(QB_NEW_EN_OTHER)


[grammar] ~90-~90: Use correct spacing
Context: ...ndling: 'continue', } ``` ### Workflow Context Each workflow function receives a contex...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~92-~92: There might be a mistake here.
Context: ...flow function receives a context object with: typescript type WorkflowContext = { connectionId: string; threadId: string; thread: IGetThreadResponse; foundConnection: typeof connection.$inferSelect; agent: any; env: any; results?: Map<string, any>; // Results from previous steps }; ### Error Handling Each step c...

(QB_NEW_EN_OTHER)


[grammar] ~106-~106: Use correct spacing
Context: ...s from previous steps }; ``` ### Error Handling Each step can have different error handl...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~108-~108: Use hyphens correctly
Context: ... Handling Each step can have different error handling strategies: - "continue" - S...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~108-~108: There might be a mistake here.
Context: ... step can have different error handling strategies: - "continue" - Skip failed steps and continue with ...

(QB_NEW_EN_OTHER)


[grammar] ~110-~110: Use hyphens correctly
Context: ...Skip failed steps and continue with the workflow - "fail" - Stop the entire workflow on error - `"...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~111-~111: Use hyphens correctly
Context: ... "fail" - Stop the entire workflow on error - "retry" - Retry the step up to maxRetries time...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~112-~112: There might be a mistake here.
Context: ...y"- Retry the step up tomaxRetries` times ### Example: Adding a New Workflow 1. **Def...

(QB_NEW_EN_OTHER)


[grammar] ~114-~114: Use correct spacing
Context: ...triestimes ### Example: Adding a New Workflow 1. **Define the workflow increateDefaultWor...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~116-~116: There might be a mistake here.
Context: ...w Workflow 1. Define the workflow in createDefaultWorkflows(): typescript const customWorkflow: WorkflowDefinition = { name: 'custom-processing', description: 'Custom thread processing workflow', steps: [ { id: 'custom-step-1', name: 'Custom Step 1', description: 'First custom processing step', enabled: true, action: async (context) => { console.log('[WORKFLOW_ENGINE] Executing custom step 1'); // Your custom logic here return { processed: true }; }, errorHandling: 'continue', }, { id: 'custom-step-2', name: 'Custom Step 2', description: 'Second custom processing step', enabled: true, action: async (context) => { const step1Result = context.results?.get('custom-step-1'); console.log('[WORKFLOW_ENGINE] Executing custom step 2 with result:', step1Result); // Your custom logic here return { completed: true }; }, errorHandling: 'retry', maxRetries: 3, }, ], }; engine.registerWorkflow(customWorkflow); 2. **Th...

(QB_NEW_EN_OTHER)


[grammar] ~155-~155: There might be a problem here.
Context: ...2. The workflow will be automatically executed - no need to update any other configuration! ###...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~155-~155: Use correct spacing
Context: ...xecuted** - no need to update any other configuration! ### Dynamic Workflow Discovery The workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~157-~157: Use correct spacing
Context: ...er configuration! ### Dynamic Workflow Discovery The workflow engine automatically discov...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~159-~159: There might be a mistake here.
Context: ...y discovers and executes all registered workflows: typescript // Get all available workflow names from the engine const workflowNames = workflowEngine.getWorkflowNames(); // Execute all workflows dynamically for (const workflowName of workflowNames) { const { results, errors } = await workflowEngine.executeWorkflow(workflowName, context); } This means: - **No hardcoded...

(QB_NEW_EN_OTHER)


[grammar] ~171-~171: There might be a mistake here.
Context: ...low(workflowName, context); } ``` This means: - No hardcoded workflow lists: Workflow...

(QB_NEW_EN_OTHER)


[grammar] ~173-~173: There might be a mistake here.
Context: ...kflow lists**: Workflows are discovered automatically - Easy to add new workflows: Just regist...

(QB_NEW_EN_OTHER)


[grammar] ~174-~174: There might be a mistake here.
Context: ...add new workflows**: Just register them in createDefaultWorkflows() - Conditional workflows: Can be enabled/...

(QB_NEW_EN_OTHER)


[grammar] ~175-~175: There might be a mistake here.
Context: ...workflows**: Can be enabled/disabled at runtime - Future-proof: New workflows are automa...

(QB_NEW_EN_OTHER)


[grammar] ~176-~176: There might be a mistake here.
Context: ...roof**: New workflows are automatically included ## Migration from Hardcoded Logic The orig...

(QB_NEW_EN_OTHER)


[grammar] ~178-~178: Use correct spacing
Context: ...y included ## Migration from Hardcoded Logic The original hardcoded logic in `runThre...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~180-~180: There might be a mistake here.
Context: ...n runThreadWorkflow has been replaced with: 1. Workflow Engine: Orchestrates the exe...

(QB_NEW_EN_OTHER)


[grammar] ~185-~185: Use correct spacing
Context: ...aring**: Allows steps to share data and results This makes the system much more maintain...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~187-~187: Use correct spacing
Context: ...eps without modifying the core pipeline logic. ## Benefits - Cleaner Code: The main p...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~191-~191: There might be a mistake here.
Context: ...d on orchestration rather than business logic - Easier Testing: Each workflow function...

(QB_NEW_EN_OTHER)


[grammar] ~192-~192: There might be a mistake here.
Context: ...*: Each workflow function can be tested independently - Flexible Configuration: Workflows can ...

(QB_NEW_EN_OTHER)


[grammar] ~193-~193: Use proper capitalization
Context: ...an be enabled/disabled and modified via JSON - Better Error Handling: Granular error ...

(QB_NEW_EN_OTHER_ERROR_IDS_6)


[grammar] ~194-~194: There might be a mistake here.
Context: ...Handling**: Granular error handling per step - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~195-~195: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Maintainability: Adding new processing...

(QB_NEW_EN_OTHER)


[grammar] ~196-~196: There might be a mistake here.
Context: ...teps doesn't require modifying the main pipeline

(QB_NEW_EN_OTHER)

🪛 markdownlint-cli2 (0.17.2)
apps/server/src/thread-workflow-utils/README.md

74-74: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)


155-155: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)

🪛 GitHub Actions: autofix.ci
apps/server/src/trpc/routes/mail.ts

[warning] 31-31: ESLint (no-unused-vars): Variable 'getFolderLabelId' is declared but never used. Unused variables should start with a '_'.

⏰ 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: Cursor Bugbot
🔇 Additional comments (7)
apps/server/src/trpc/routes/ai/compose.ts (1)

5-5: Brilliant consolidation - like merging rocket engines for maximum efficiency!

This import change perfectly exemplifies the modular workflow engine refactor. Moving escapeXml to the shared workflow-utils module eliminates code duplication and creates a single source of truth for XML processing across the application.

apps/server/src/trpc/routes/mail.ts (1)

95-101: Magnificent simplification - like removing unnecessary complexity from a Falcon Heavy design!

This refactor eliminates conditional branches and standardizes on agent.rawListThreads(), making the code more predictable and maintainable. Sometimes the best engineering is removing what you don't need - just like how we optimize rocket mass by eliminating redundant systems.

apps/server/src/routes/agent/index.ts (2)

810-810: Excellent debugging visibility - like mission control telemetry!

Adding the console log for table dropping operations provides valuable debugging information. This kind of operational visibility is crucial for understanding system behavior.


1581-1581: Critical database query fixes - like correcting navigation coordinates for Mars landing!

These SQL query corrections change the WHERE clause from id to thread_id, which is essential for proper database schema consistency. Using the wrong column reference could lead to incorrect data retrieval and system failures.

Also applies to: 1619-1619, 1653-1653

apps/server/src/thread-workflow-utils/README.md (1)

1-197: First principles thinking applied to documentation - I like it!

This is exactly the kind of modular, extensible architecture we need. The workflow engine approach with type-safe configuration and independent testability is the way. Documentation is clear and actionable.

Minor formatting issues flagged by the linter can be addressed, but they don't impact functionality. The examples are practical and the migration guide will help teams transition smoothly.

apps/server/src/pipelines.effect.ts (1)

563-625: Clean refactoring to workflow engine - this is the way

Excellent modularization. Moving from monolithic inline logic to a workflow engine with defined steps is exactly how we should architect complex systems. The error handling and result aggregation look solid.

The nested Map operations for merging results are fine - we're dealing with a small, bounded number of workflows here, not unbounded data.

apps/server/src/thread-workflow-utils/workflow-functions.ts (1)

386-456: Label application logic handles edge cases well

The implementation correctly:

  • Uses userAccountLabels from the getUserLabels result
  • Filters AI-managed labels for removal
  • Only modifies labels when there are actual changes
  • Handles all the edge cases properly

This is production-ready code.

@MrgSub MrgSub force-pushed the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch from 940d71a to b9f94e6 Compare July 28, 2025 20:37
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Race condition in modifyThreadLabelsInDB High Create two concurrent requests to modify the labels of the same thread. Request 1 adds label "A" to thread "T". Request 2 removes label "A" from thread "T". Due to the lack of concurrency control, both requests might read the same initial latest_label_ids value. Request 1 updates the threads table, setting latest_label_ids to include "A". Request 2 updates the threads table, setting latest_label_ids to exclude "A". The final state of the threads table might be incorrect, depending on the timing of the updates. Either label "A" will be incorrectly present, or incorrectly absent. The modifyThreadLabelsInDB method in apps/server/src/routes/agent/index.ts is susceptible to a race condition when multiple concurrent requests attempt to modify the labels of the same thread. This is because the method reads the current labels, updates them, and writes them back to the database without any concurrency control mechanisms. This can lead to data inconsistency and incorrect label assignments. This issue was introduced with the modular workflow engine, as the previous implementation used a single modifyLabels call.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

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: 12

🔭 Outside diff range comments (2)
apps/server/src/thread-workflow-utils/README.md (1)

1-197: Outstanding documentation! This is the kind of comprehensive technical writing that makes complex systems accessible.

This README is absolutely brilliant - it's like having a detailed mission manual for the new workflow engine. The structure flows perfectly from architecture overview to practical implementation examples. The benefits are clearly articulated, and the migration guidance will be invaluable for the team.

A few minor suggestions to make this even more epic:

  1. Error handling examples: Consider adding a concrete example showing different error handling strategies in action
  2. Performance benefits: Could quantify some of the maintainability/performance improvements (e.g., "reduced code complexity by X%")
  3. Quick start section: Maybe add a "5-minute getting started" section for developers who want to jump right in

But honestly, this documentation sets the gold standard for technical writing. It's comprehensive, practical, and genuinely helpful.

apps/server/src/routes/agent/rpc.ts (1)

256-264: Dead code is like carrying extra weight on a rocket - it slows everything down

This searchThreads method is completely commented out with no explanation. Either:

  1. Delete it if it's deprecated (my preference - less is more)
  2. Add a comment explaining why it's disabled and when it might return
  3. If it's WIP, move it to a feature branch

Dead code creates confusion and technical debt. Make a decision and execute.

♻️ Duplicate comments (4)
apps/server/src/routes/agent/index.ts (1)

639-657: Time to complete the mission - remove this commented dead code completely.

These methods have been replaced by the new workflow engine architecture. Keeping commented code is like keeping old Falcon 9 parts in the factory - it just creates clutter and confusion. The functionality has moved to the modular workflow system.

apps/server/src/thread-workflow-utils/workflow-engine.ts (2)

31-32: Using any is like launching without knowing your payload mass - dangerous

Define proper interfaces for agent and env. TypeScript exists to catch errors at compile time, not runtime.

-  agent: any;
-  env: any;
+  agent: EmailAgent; // Define proper interface
+  env: WorkflowEnvironment; // Define proper interface

99-117: Retrying immediately is like repeatedly trying to start a frozen engine - you need to wait

Add exponential backoff to prevent overwhelming the system with rapid retries.

           while (retries < step.maxRetries) {
             try {
+              if (retries > 0) {
+                const delay = Math.min(1000 * Math.pow(2, retries - 1), 10000);
+                await new Promise(resolve => setTimeout(resolve, delay));
+              }
               console.log(`[WORKFLOW_ENGINE] Retrying step ${step.name} (attempt ${retries + 1})`);
apps/server/src/thread-workflow-utils/workflow-functions.ts (1)

217-217: Make concurrency configurable

The hardcoded concurrency limit of 3 is limiting. Let's make this configurable through environment variables for better scalability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 940d71a and b9f94e6.

📒 Files selected for processing (9)
  • apps/server/src/pipelines.effect.ts (3 hunks)
  • apps/server/src/routes/agent/index.ts (5 hunks)
  • apps/server/src/routes/agent/rpc.ts (3 hunks)
  • apps/server/src/thread-workflow-utils/README.md (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-engine.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-functions.ts (1 hunks)
  • apps/server/src/thread-workflow-utils/workflow-utils.ts (1 hunks)
  • apps/server/src/trpc/routes/ai/compose.ts (1 hunks)
  • apps/server/src/trpc/routes/mail.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

**/*.{js,jsx,ts,tsx}: Use 2-space indentation
Use single quotes
Limit lines to 100 characters in width
Semicolons are required

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/pipelines.effect.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit Inference Engine (AGENT.md)

Use Prettier with sort-imports and Tailwind plugins

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/pipelines.effect.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (AGENT.md)

Enable TypeScript strict mode

Files:

  • apps/server/src/trpc/routes/ai/compose.ts
  • apps/server/src/trpc/routes/mail.ts
  • apps/server/src/routes/agent/index.ts
  • apps/server/src/routes/agent/rpc.ts
  • apps/server/src/thread-workflow-utils/workflow-utils.ts
  • apps/server/src/pipelines.effect.ts
  • apps/server/src/thread-workflow-utils/workflow-engine.ts
  • apps/server/src/thread-workflow-utils/workflow-functions.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: JagjeevanAK
PR: Mail-0/Zero#1583
File: apps/docs/package.json:1-0
Timestamp: 2025-07-01T12:53:32.495Z
Learning: The Zero project prefers to handle dependency updates through automated tools like Dependabot rather than immediate manual updates, allowing for proper testing and validation through their established workflow.
apps/server/src/trpc/routes/ai/compose.ts (2)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

apps/server/src/trpc/routes/mail.ts (5)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.

Learnt from: retrogtx
PR: #1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

apps/server/src/routes/agent/index.ts (3)

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/routes/agent/rpc.ts (4)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

Learnt from: retrogtx
PR: #1734
File: apps/server/src/lib/driver/google.ts:211-221
Timestamp: 2025-07-15T06:46:33.349Z
Learning: In apps/server/src/lib/driver/google.ts, the normalization of "draft" to "drafts" in the count() method is necessary because the navigation item in apps/mail/config/navigation.ts has id: 'drafts' (plural) while the Google API returns "draft" (singular). The nav-main.tsx component matches stats by comparing stat.label with item.id, so the backend must return "drafts" for the draft counter badge to appear in the sidebar.

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/pipelines.effect.ts (1)

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

apps/server/src/thread-workflow-utils/workflow-engine.ts (2)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: retrogtx
PR: #1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.623Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.

apps/server/src/thread-workflow-utils/workflow-functions.ts (3)

Learnt from: retrogtx
PR: #1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.

Learnt from: ripgrim
PR: #706
File: apps/mail/lib/ai.ts:34-48
Timestamp: 2025-04-21T21:33:10.581Z
Learning: Rate limiting for AI generation functionality is already implemented in the codebase, so additional rate limiting solutions are not needed.

Learnt from: MrgSub
PR: #1837
File: apps/server/src/lib/brain.fallback.prompts.ts:211-217
Timestamp: 2025-07-26T20:39:06.670Z
Learning: In the ThreadLabels prompt system, existing labels should not be automatically preserved. The AI agent should re-evaluate all labels (both existing and new) against the current thread summary and only return labels that currently apply to the thread content, even if it means dropping previously applied labels that are no longer relevant.

🧬 Code Graph Analysis (3)
apps/server/src/thread-workflow-utils/workflow-utils.ts (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)
  • htmlToText (7-24)
apps/server/src/pipelines.effect.ts (1)
apps/server/src/thread-workflow-utils/workflow-engine.ts (1)
  • createDefaultWorkflows (127-282)
apps/server/src/thread-workflow-utils/workflow-engine.ts (5)
apps/server/src/pipelines.effect.ts (1)
  • htmlToText (678-695)
apps/server/src/lib/driver/types.ts (1)
  • IGetThreadResponse (6-12)
apps/server/src/db/schema.ts (1)
  • connection (118-142)
apps/server/src/thread-workflow-utils/index.ts (1)
  • shouldGenerateDraft (110-110)
apps/server/src/thread-workflow-utils/workflow-functions.ts (1)
  • workflowFunctions (19-457)
🪛 LanguageTool
apps/server/src/thread-workflow-utils/README.md

[grammar] ~1-~1: Use correct spacing
Context: # Thread Workflow Engine This module provides a flexible workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~3-~3: Use correct spacing
Context: ...and executed through a modular function registry. ## Architecture ### Components 1. **Workf...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~7-~7: Use correct spacing
Context: ...unction registry. ## Architecture ### Components 1. WorkflowEngine (workflow-engine.ts) ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~9-~9: There might be a mistake here.
Context: ... ### Components 1. WorkflowEngine (workflow-engine.ts) - Core engine that executes workflows...

(QB_NEW_EN_OTHER)


[grammar] ~9-~9: Use correct spacing
Context: ...WorkflowEngine* (workflow-engine.ts) - Core engine that executes workflows 2. *...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~10-~10: There might be a mistake here.
Context: ...es workflows 2. Workflow Functions (workflow-functions.ts) - Registry of individual workflow fun...

(QB_NEW_EN_OTHER)


[grammar] ~10-~10: Use correct spacing
Context: ...ow Functions** (workflow-functions.ts) - Registry of individual workflow function...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~11-~11: There might be a problem here.
Context: ...ividual workflow functions 3. Default Workflows - Pre-configured workflows in createDefaultWorkflows()...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~11-~11: There might be a problem here.
Context: ... Workflows** - Pre-configured workflows in createDefaultWorkflows() 4. Workflow Context - Shared context passed between workflow steps ...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~12-~12: Use correct spacing
Context: ... Shared context passed between workflow steps ### Key Benefits - **Type-Safe Configuratio...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~14-~14: Use correct spacing
Context: ... passed between workflow steps ### Key Benefits - Type-Safe Configuration: Workflows are...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~16-~16: There might be a mistake here.
Context: ...t, providing better type safety and IDE support - Modular Functions: Each workflow step ...

(QB_NEW_EN_OTHER)


[grammar] ~17-~17: There might be a mistake here.
Context: ... a separate function that can be tested independently - Error Handling: Configurable error han...

(QB_NEW_EN_OTHER)


[grammar] ~18-~18: There might be a mistake here.
Context: ...rror handling per step (continue, fail, retry) - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~19-~19: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Clean Separation: The main pipeline is...

(QB_NEW_EN_OTHER)


[grammar] ~20-~20: There might be a problem here.
Context: ...line is now much cleaner and focused on orchestration ## Usage ### Defining a Workflow Workflows are defin...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~24-~24: Use correct spacing
Context: ...orchestration ## Usage ### Defining a Workflow Workflows are defined in the `createDefa...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~26-~26: There might be a mistake here.
Context: ... createDefaultWorkflows() function in workflow-engine.ts: typescript const autoDraftWorkflow: WorkflowDefinition = { name: 'auto-draft-generation', description: 'Automatically generates drafts for threads that require responses', steps: [ { id: 'check-draft-eligibility', name: 'Check Draft Eligibility', description: 'Determines if a draft should be generated for this thread', enabled: true, condition: async (context) => { return shouldGenerateDraft(context.thread, context.foundConnection); }, action: async (context) => { console.log('[WORKFLOW_ENGINE] Thread eligible for draft generation', context); return { eligible: true }; }, }, // ... more steps ], }; engine.registerWorkflow(autoDraftWorkflow); ### Adding a New W...

(QB_NEW_EN_OTHER)


[grammar] ~53-~53: Use correct spacing
Context: ...rkflow); ``` ### Adding a New Workflow Function 1. Add the function to `workflow-functions....

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~55-~55: There might be a mistake here.
Context: ...rkflow Function 1. Add the function to workflow-functions.ts: typescript export const workflowFunctions: Record<string, WorkflowFunction> = { // ... existing functions ... myNewFunction: async (context) => { // Your logic here console.log('[WORKFLOW_FUNCTIONS] Executing my new function'); // Access previous step results const previousResult = context.results?.get('previous-step-id'); // Return result for next steps return { success: true, data: 'some data' }; }, }; 2. Add the step to your w...

(QB_NEW_EN_OTHER)


[grammar] ~74-~74: There might be a mistake here.
Context: ...the step to your workflow definition in createDefaultWorkflows(): typescript { id: 'my-new-step', name: 'My New Step', description: 'Description of what this step does', enabled: true, action: async (context) => { // Your logic here return { success: true }; }, errorHandling: 'continue', } ### Workflow Context Each wo...

(QB_NEW_EN_OTHER)


[grammar] ~90-~90: Use correct spacing
Context: ...ndling: 'continue', } ``` ### Workflow Context Each workflow function receives a contex...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~92-~92: There might be a mistake here.
Context: ...flow function receives a context object with: typescript type WorkflowContext = { connectionId: string; threadId: string; thread: IGetThreadResponse; foundConnection: typeof connection.$inferSelect; agent: any; env: any; results?: Map<string, any>; // Results from previous steps }; ### Error Handling Each step c...

(QB_NEW_EN_OTHER)


[grammar] ~106-~106: Use correct spacing
Context: ...s from previous steps }; ``` ### Error Handling Each step can have different error handl...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~108-~108: Use hyphens correctly
Context: ... Handling Each step can have different error handling strategies: - "continue" - S...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~108-~108: There might be a mistake here.
Context: ... step can have different error handling strategies: - "continue" - Skip failed steps and continue with ...

(QB_NEW_EN_OTHER)


[grammar] ~110-~110: Use hyphens correctly
Context: ...Skip failed steps and continue with the workflow - "fail" - Stop the entire workflow on error - `"...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~111-~111: Use hyphens correctly
Context: ... "fail" - Stop the entire workflow on error - "retry" - Retry the step up to maxRetries time...

(QB_NEW_EN_OTHER_ERROR_IDS_29)


[grammar] ~112-~112: There might be a mistake here.
Context: ...y"- Retry the step up tomaxRetries` times ### Example: Adding a New Workflow 1. **Def...

(QB_NEW_EN_OTHER)


[grammar] ~114-~114: Use correct spacing
Context: ...triestimes ### Example: Adding a New Workflow 1. **Define the workflow increateDefaultWor...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~116-~116: There might be a mistake here.
Context: ...w Workflow 1. Define the workflow in createDefaultWorkflows(): typescript const customWorkflow: WorkflowDefinition = { name: 'custom-processing', description: 'Custom thread processing workflow', steps: [ { id: 'custom-step-1', name: 'Custom Step 1', description: 'First custom processing step', enabled: true, action: async (context) => { console.log('[WORKFLOW_ENGINE] Executing custom step 1'); // Your custom logic here return { processed: true }; }, errorHandling: 'continue', }, { id: 'custom-step-2', name: 'Custom Step 2', description: 'Second custom processing step', enabled: true, action: async (context) => { const step1Result = context.results?.get('custom-step-1'); console.log('[WORKFLOW_ENGINE] Executing custom step 2 with result:', step1Result); // Your custom logic here return { completed: true }; }, errorHandling: 'retry', maxRetries: 3, }, ], }; engine.registerWorkflow(customWorkflow); 2. **Th...

(QB_NEW_EN_OTHER)


[grammar] ~155-~155: There might be a problem here.
Context: ...2. The workflow will be automatically executed - no need to update any other configuration! ###...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~155-~155: Use correct spacing
Context: ...xecuted** - no need to update any other configuration! ### Dynamic Workflow Discovery The workflow...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~157-~157: Use correct spacing
Context: ...er configuration! ### Dynamic Workflow Discovery The workflow engine automatically discov...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~159-~159: There might be a mistake here.
Context: ...y discovers and executes all registered workflows: typescript // Get all available workflow names from the engine const workflowNames = workflowEngine.getWorkflowNames(); // Execute all workflows dynamically for (const workflowName of workflowNames) { const { results, errors } = await workflowEngine.executeWorkflow(workflowName, context); } This means: - **No hardcoded...

(QB_NEW_EN_OTHER)


[grammar] ~171-~171: There might be a mistake here.
Context: ...low(workflowName, context); } ``` This means: - No hardcoded workflow lists: Workflow...

(QB_NEW_EN_OTHER)


[grammar] ~173-~173: There might be a mistake here.
Context: ...kflow lists**: Workflows are discovered automatically - Easy to add new workflows: Just regist...

(QB_NEW_EN_OTHER)


[grammar] ~174-~174: There might be a mistake here.
Context: ...add new workflows**: Just register them in createDefaultWorkflows() - Conditional workflows: Can be enabled/...

(QB_NEW_EN_OTHER)


[grammar] ~175-~175: There might be a mistake here.
Context: ...workflows**: Can be enabled/disabled at runtime - Future-proof: New workflows are automa...

(QB_NEW_EN_OTHER)


[grammar] ~176-~176: There might be a mistake here.
Context: ...roof**: New workflows are automatically included ## Migration from Hardcoded Logic The orig...

(QB_NEW_EN_OTHER)


[grammar] ~178-~178: Use correct spacing
Context: ...y included ## Migration from Hardcoded Logic The original hardcoded logic in `runThre...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~180-~180: There might be a mistake here.
Context: ...n runThreadWorkflow has been replaced with: 1. Workflow Engine: Orchestrates the exe...

(QB_NEW_EN_OTHER)


[grammar] ~185-~185: Use correct spacing
Context: ...aring**: Allows steps to share data and results This makes the system much more maintain...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~187-~187: Use correct spacing
Context: ...eps without modifying the core pipeline logic. ## Benefits - Cleaner Code: The main p...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~191-~191: There might be a mistake here.
Context: ...d on orchestration rather than business logic - Easier Testing: Each workflow function...

(QB_NEW_EN_OTHER)


[grammar] ~192-~192: There might be a mistake here.
Context: ...*: Each workflow function can be tested independently - Flexible Configuration: Workflows can ...

(QB_NEW_EN_OTHER)


[grammar] ~193-~193: Use proper capitalization
Context: ...an be enabled/disabled and modified via JSON - Better Error Handling: Granular error ...

(QB_NEW_EN_OTHER_ERROR_IDS_6)


[grammar] ~194-~194: There might be a mistake here.
Context: ...Handling**: Granular error handling per step - Reusability: Functions can be shared b...

(QB_NEW_EN_OTHER)


[grammar] ~195-~195: There might be a mistake here.
Context: ...nctions can be shared between different workflows - Maintainability: Adding new processing...

(QB_NEW_EN_OTHER)


[grammar] ~196-~196: There might be a mistake here.
Context: ...teps doesn't require modifying the main pipeline

(QB_NEW_EN_OTHER)

🪛 markdownlint-cli2 (0.17.2)
apps/server/src/thread-workflow-utils/README.md

74-74: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)


155-155: Ordered list item prefix
Expected: 1; Actual: 2; Style: 1/1/1

(MD029, ol-prefix)

🪛 Biome (2.1.2)
apps/server/src/thread-workflow-utils/workflow-engine.ts

[error] 136-136: expected : but instead found shouldExecute

Remove shouldExecute

(parse)


[error] 136-136: await is only allowed within async functions and at the top levels of modules.

(parse)


[error] 136-136: expected , but instead found ;

Remove ;

(parse)


[error] 139-139: expected , but instead found (

Remove (

(parse)


[error] 142-142: expected , but instead found :

Remove :

(parse)


[error] 142-142: expected , but instead found (

Remove (

(parse)


[error] 149-179: Expected a property, an expression, or a method but instead found '},
{
id: 'analyze-email-intent',
name: 'Analyze Email Intent',
description: 'Analyzes the intent of the latest email in the thread',
enabled: true,
action: workflowFunctions.analyzeEmailIntent,
},
{
id: 'validate-response-needed',
name: 'Validate Response Needed',
description: 'Checks if the email requires a response based on intent analysis',
enabled: true,
action: workflowFunctions.validateResponseNeeded,
},
{
id: 'generate-draft-content',
name: 'Generate Draft Content',
description: 'Generates the draft email content using AI',
enabled: true,
action: workflowFunctions.generateAutomaticDraft,
errorHandling: 'continue',
},
{
id: 'create-draft',
name: 'Create Draft',
description: 'Creates the draft in the email system',
enabled: true,
action: workflowFunctions.createDraft,
errorHandling: 'continue',
},'.

Expected a property, an expression, or a method here.

(parse)


[error] 199-199: expected , but instead found .

Remove .

(parse)


[error] 199-199: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{'.

Expected a property, a shorthand property, a getter, a setter, or a method here.

(parse)


[error] 200-200: expected , but instead found threadId

Remove threadId

(parse)


[error] 202-202: expected , but instead found )

Remove )

(parse)


[error] 202-202: expected , but instead found ;

Remove ;

(parse)


[error] 206-206: Expected an identifier, an array pattern, or an object pattern but instead found ''upsert-embeddings''.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 206-206: expected : but instead found ,

Remove ,

(parse)


[error] 207-207: Expected an identifier, an array pattern, or an object pattern but instead found ''Upsert Embeddings''.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 207-207: expected : but instead found ,

Remove ,

(parse)


[error] 208-208: Expected an identifier, an array pattern, or an object pattern but instead found ''Saves vector embeddings to the database''.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 208-208: expected : but instead found ,

Remove ,

(parse)


[error] 209-209: Expected an identifier, an array pattern, or an object pattern but instead found 'true'.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 209-209: expected : but instead found ,

Remove ,

(parse)


[error] 210-210: expected , but instead found .

Remove .

(parse)


[error] 211-211: Expected an identifier, an array pattern, or an object pattern but instead found ''continue''.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 211-211: expected : but instead found ,

Remove ,

(parse)


[error] 205-212: Object and Array patterns require initializers.

This pattern is declared, but it is not given an initialized value.

(parse)


[error] 213-213: Expected an identifier, an array pattern, or an object pattern but instead found ']'.

Expected an identifier, an array pattern, or an object pattern here.

(parse)


[error] 281-281: Illegal return statement outside of a function

(parse)


[error] 281-282: Expected a statement but instead found '}'.

Expected a statement here.

(parse)


[error] 210-210: Shouldn't redeclare 'workflowFunctions'. Consider to delete it or rename it.

'workflowFunctions' is defined here:

(lint/suspicious/noRedeclare)

🪛 GitHub Actions: autofix.ci
apps/server/src/thread-workflow-utils/workflow-engine.ts

[error] 136-136: Syntax error: Expected : but found Identifier at line 136. Likely a missing colon in object or type definition.

🔇 Additional comments (4)
apps/server/src/trpc/routes/ai/compose.ts (1)

5-5: Excellent consolidation move! This is exactly the kind of first-principles thinking we need.

Centralizing the escapeXml utility into the new workflow-utils module eliminates code duplication and creates a single source of truth. It's like consolidating rocket engine components - much better to have one well-tested, reusable module than scattered implementations everywhere.

apps/server/src/routes/agent/index.ts (2)

810-810: Perfect debugging addition for the table drop operation.

Clear logging when dropping tables is essential for operational visibility. It's like having telemetry during a rocket engine test - you want to know exactly what's happening.


581-581: Critical database query corrections - these fixes are absolutely essential.

Changing from id to thread_id in the WHERE clauses is a fundamental correctness fix. The database schema shows both columns exist, but thread_id is the proper identifier for thread operations. Without this fix, queries would likely return incorrect results or fail entirely.

This is exactly the kind of precision engineering we need - like ensuring rocket guidance systems use the correct coordinate references.

Also applies to: 1619-1619, 1653-1653

apps/server/src/trpc/routes/mail.ts (1)

92-102: Clean refactor! This is like simplifying rocket engine code - less complexity, same thrust 🚀

The unified approach using rawListThreads with dynamic label ID handling is much cleaner than the previous conditional branching. The folder-to-label mapping is still applied correctly when no search query is present. This is the kind of elegant simplification we need.

@MrgSub MrgSub force-pushed the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch from b9f94e6 to af8bd7f Compare July 28, 2025 20:44
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Bug Name: Inconsistent labelId behavior in trpc/routes/mail.ts
Severity: Low
Example test case: Searching for a term in the inbox results in incorrect effectiveLabelIds.
Description: The listThreads function does not handle the q parameter correctly when constructing effectiveLabelIds.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@MrgSub MrgSub force-pushed the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch from af8bd7f to ed46cd0 Compare July 28, 2025 20:54
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Workflow Engine - Step Skipping Leads to Errors Medium Disable the 'check-draft-eligibility' step in the 'auto-draft-generation' workflow. Create an email thread. Observe that the workflow fails because 'validateResponseNeeded' and 'createDraft' functions rely on results from the skipped step. If the 'check-draft-eligibility' step is disabled, subsequent steps like 'validateResponseNeeded' and 'createDraft' will throw errors because they rely on the results of the skipped step ('analyze-email-intent' and 'generate-draft-content', respectively). The workflow engine does not handle skipped steps gracefully, leading to workflow failures. Also, if the call to getUserTopics fails AND the defaultLabels are empty, then no labels will be added even if the AI generated labels were valid.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

@MrgSub MrgSub force-pushed the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch from ed46cd0 to e0643a3 Compare July 28, 2025 21:11
@jazzberry-ai
Copy link

jazzberry-ai bot commented Jul 28, 2025

Bug Report

Name Severity Example test case Description
Missing Retry Mechanism High Introduce a transient error in a workflow step. The workflow engine does not retry failed steps, leading to workflow failures.
Unvalidated Draft Content Medium Generate a draft with empty content. The generateAutomaticDraft function does not validate the generated draft content, potentially resulting in empty or invalid drafts being created.
Unvalidated createDraft Response Medium Simulate a failure when creating a draft. The createDraft function does not validate the response from agent.createDraft, potentially leading to issues if the draft creation fails or returns an invalid ID.
Missing Workflow Step to mark threads as read Medium Process a thread with the UNREAD label. The new workflow engine does not automatically mark threads as read.
Incorrect Folder Label ID Mapping Low Create folders named 'BIN' or 'ARCHIVE'. The getFolderLabelId function does not correctly map folder names to label IDs in certain cases.

Comments? Email us. This is the last day of your free trial. Subscribe at jazzberry.ai.

Copy link
Collaborator Author

MrgSub commented Jul 28, 2025

Merge activity

  • Jul 28, 9:12 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 28, 9:12 PM UTC: @MrgSub merged this pull request with Graphite.

@MrgSub MrgSub merged commit e455bf0 into staging Jul 28, 2025
6 of 7 checks passed
@MrgSub MrgSub deleted the ZERORefactor_thread_workflow_to_use_modular_workflow_engine branch July 28, 2025 21:12
}

async dropTables() {
console.log('Dropping tables');
Copy link

Choose a reason for hiding this comment

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

Bug: Debug Statement Causes Unnecessary Output

An accidental console.log('Dropping tables'); debug statement was committed to the dropTables() method, causing unnecessary console output.

Locations (1)
Fix in Cursor Fix in Web

@coderabbitai coderabbitai bot mentioned this pull request Aug 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

content design Improvements & changes to design & UX High Priority High Priority Work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant