Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implements lifecycle hooks #79

Merged
merged 11 commits into from
Feb 1, 2025
Merged

feat: implements lifecycle hooks #79

merged 11 commits into from
Feb 1, 2025

Conversation

ponderingdemocritus
Copy link
Contributor

@ponderingdemocritus ponderingdemocritus commented Jan 31, 2025

Implements hook system inside orchestrator allowing for greater dynamic injection of anything

Renamed room -> conversation for clarity

Summary by CodeRabbit

Release Notes

Overview

This release introduces a significant architectural shift from room-based to conversation-based management across the platform, enhancing context handling and interaction tracking.

New Features

  • Introduced ConversationManager to replace RoomManager
  • Enhanced conversation tracking and memory management
  • Improved lifecycle management for content processing
  • Added structured output format for certain actions

Key Changes

  • Renamed core entities from "Room" to "Conversation"
  • Updated method signatures across multiple components
  • Refined content processing and memory storage mechanisms

Improvements

  • More precise content handling
  • Better context preservation
  • Streamlined interaction tracking

Breaking Changes

  • Replaced RoomManager with ConversationManager
  • Modified method signatures involving room-related operations
  • Updated type definitions for conversations and memories

Compatibility

Existing integrations will require updates to use new conversation-based methods and types.

Copy link

vercel bot commented Jan 31, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
daydreams ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 1, 2025 11:19pm

Copy link
Contributor

coderabbitai bot commented Jan 31, 2025

Warning

Rate limit exceeded

@ponderingdemocritus has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 51 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 8a6b421 and 199bf7d.

📒 Files selected for processing (6)
  • packages/core/src/core/db/mongo-db.ts (5 hunks)
  • packages/core/src/core/life-cycle.ts (1 hunks)
  • packages/core/src/core/memory.ts (3 hunks)
  • packages/core/src/core/orchestrator.ts (8 hunks)
  • packages/core/src/core/types/index.ts (7 hunks)
  • packages/core/src/core/vector-db.ts (12 hunks)

Walkthrough

This pull request represents a comprehensive refactoring of the codebase from a room-based management system to a conversation-based approach. The changes span multiple files across the project, systematically replacing references to "Room" and "RoomManager" with "Conversation" and "ConversationManager". This transformation affects core classes, interfaces, type definitions, and example implementations, indicating a fundamental shift in how the system conceptualizes and manages interactions.

Changes

File Change Summary
examples/* Updated import paths and replaced RoomManager with ConversationManager in various example files. Modified output handlers to return structured objects instead of strings.
packages/core/src/core/conversation-manager.ts New implementation of ConversationManager with comprehensive conversation management methods.
packages/core/src/core/conversation.ts Refactored Room class to Conversation class.
packages/core/src/core/types/index.ts Updated interfaces to use conversationId instead of roomId.
packages/core/src/core/vector-db.ts Renamed methods to support conversation-based operations.
packages/core/src/core/memory.ts Updated methods to operate on conversations instead of rooms.
packages/core/src/core/orchestrator.ts Refactored to utilize FlowLifecycle and removed room-based logic.
packages/core/src/core/life-cycle.ts Introduced makeFlowLifecycle function and FlowLifecycle interface for lifecycle management.
packages/core/src/core/schedule-service.ts Replaced roomManager with conversationManager in IOrchestratorContext.
packages/core/src/core/__tests__/vector-db.test.ts Updated test cases to reflect changes from room to conversation operations.
packages/core/src/core/db/mongo-db.ts Modified chat management methods to align with the new conversation model.
packages/core/src/core/io/discord.ts Updated message handling logic to accommodate new data structures for conversations.

Possibly related PRs

  • feat: processor refactor #45: The changes in the main PR, which involve replacing RoomManager with ConversationManager and modifying message processing logic, are related to the retrieved PR that also updates the processing logic by replacing a generic Processor with MessageProcessor, indicating a shared focus on enhancing message handling and processing structures.
  • feat: llm clients #30: The changes in the main PR, which involve replacing RoomManager with ConversationManager and modifying related message processing logic, are directly related to the changes in the retrieved PR that also modifies the example-twitter.ts file, specifically in how the LLMClient and Processor are configured and utilized, indicating a broader shift in conversation management.

Poem

🐰 A Rabbit's Ode to Conversations

From rooms of old to chats anew,
We've hopped and changed our coding view.
Conversations bloom where rooms once stood,
A refactor done, and done quite good!

Hop hop hooray! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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
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: 1

🧹 Nitpick comments (18)
examples/example-server.ts (3)

24-26: Initializing MongoDb with a descriptive variable name.
Naming kvDb clarifies its usage for key-value or scheduling tasks. Consider adding error handling to confirm a successful connection.

 const kvDb = new MongoDb(
     "mongodb://localhost:27017",
     "myApp",
     "scheduled_tasks"
 );
+// Optional: handle potential connection errors as needed.

30-30: Consider wrapping DB connection in a try/catch block.
While a direct await call might suffice in dev environments, error handling can enhance reliability in production.

 try {
   await kvDb.connect();
   console.log(chalk.green("✅ Scheduled task database connected"));
+} catch (error) {
+  console.error("Unable to connect to MongoDb", error);
+  process.exit(1);
 }

217-217: Potentially large query result.
getOrchestratorsByUserId can return large datasets. Consider adding pagination or limiting the response size to improve performance.

 const histories = await kvDb.getOrchestratorsByUserId(userId);
+// Optionally, implement pagination to avoid large responses:
+// const histories = await kvDb.getOrchestratorsByUserId(userId, { limit: 50, skip: offset });
examples/example-twitter.ts (2)

175-175: Posting to Twitter via tweet handler.
Implementation is straightforward. Potential streaming/failure handling can be considered.


212-212: Replying to tweets.
Simple approach to handle replies. Ensure you handle potential error cases from Twitter.

 return twitter.createTweetOutput().handler(tweetData);
+// Consider multi-try approach or backoff if rate limits or network issues occur.
packages/core/src/core/life-cycle.ts (1)

38-56: onTasksScheduled.
Looping over tasks and creating them in the DB is correct. Potentially consider parallel scheduling if needed at high scales.

packages/core/src/core/conversation-manager.ts (4)

10-21: Consider consolidating repeated vectorDb checks.
Multiple methods throw an Error if this.vectorDb is missing. You might introduce a helper method (e.g., assertVectorDb()) to reduce duplication and improve maintainability.

+ private assertVectorDb() {
+   if (!this.vectorDb) {
+     throw new Error("VectorDB is required for conversation operations");
+   }
+ }

public async getConversation(conversationId: string): Promise<Conversation | undefined> {
+   this.assertVectorDb();
    ...
}

258-261: Revisit hacky approach to platform extraction.
Currently, platform and platformId are inferred via conversationId.split('_') plus a manual suffix. This may break if your naming convention evolves.


108-144: Wrap error creation with additional context.
When the vector DB collection creation fails, consider providing more details (e.g., user origin or function parameters). This could aid debugging and triaging.


293-314: Confirm user input validation in findSimilarMemoriesInConversation.
Before calling the vector DB, you might add checks for empty or invalid content. This can help avoid unnecessary or misleading searches.

packages/core/src/core/orchestrator.ts (3)

Line range hint 72-83: Assess concurrency for the subscribed input.
The current approach immediately calls runAutonomousFlow on streaming data. Verify that multiple inputs won't overwhelm the orchestrator.


Line range hint 206-217: Avoid overshadowing the return type.
dispatchToInput returns unknown or an array of processed results from runAutonomousFlow. Consider typing this more strictly to aid debugging and usage.


435-436: Reconsider the hardcoded 5-second delay.
Using setTimeout with 5000ms in processContent might degrade performance and block quick responses. If it’s for rate-limiting or demonstration, document it clearly or remove it.

packages/core/src/core/vector-db.ts (2)

259-261: Replace the hack for deriving platform information.
Currently, platformId: conversationId.split('_')[0] + "_platform" can break if the conversation ID format changes. Introduce a more robust approach or rely on existing metadata.


1632-1637: Check for concurrency pitfalls in “hasProcessedContent”.
If multiple processes attempt to mark or check content simultaneously, you might face race conditions. Consider using a lock or stronger guarantee.

packages/core/src/core/conversation.ts (2)

67-71: Consider adding a comment explaining the deterministic memory ID generation.

The code would benefit from a brief comment explaining why deterministic IDs are important for memories.

-        // Create deterministic memory ID based on Conversation ID and content
+        // Create deterministic memory ID based on Conversation ID and content
+        // This ensures consistent memory IDs across system restarts and helps prevent duplicates

Line range hint 75-82: Consider adding validation for memory content.

The memory creation logic should validate that the content is not empty or just whitespace.

         const memory: Memory = {
             id: memoryId,
             conversationId: this.id,
+            content: content.trim(),
-            content,
             timestamp: new Date(),
             metadata,
         };
+
+        if (!memory.content) {
+            throw new Error("Memory content cannot be empty");
+        }
packages/core/src/core/consciousness.ts (1)

Line range hint 232-259: Consider adding pagination support for memory retrieval.

The getRecentMemories method could benefit from pagination support for better scalability.

     private getRecentMemories(
         conversations: Conversation[],
-        limit: number = 10
+        limit: number = 10,
+        offset: number = 0
     ): Array<{ content: string; conversationId: string }> {
         // ... existing code ...
         return allMemories
             .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())
-            .slice(0, limit)
+            .slice(offset, offset + limit)
             .map(({ content, conversationId }) => ({
                 content,
                 conversationId,
             }));
     }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8452385 and a386074.

📒 Files selected for processing (18)
  • examples/example-api.ts (1 hunks)
  • examples/example-basic.ts (2 hunks)
  • examples/example-discord.ts (5 hunks)
  • examples/example-goal.ts (2 hunks)
  • examples/example-server.ts (7 hunks)
  • examples/example-twitter.ts (8 hunks)
  • packages/core/src/core/__tests__/vector-db.test.ts (1 hunks)
  • packages/core/src/core/consciousness.ts (5 hunks)
  • packages/core/src/core/conversation-manager.ts (1 hunks)
  • packages/core/src/core/conversation.ts (7 hunks)
  • packages/core/src/core/index.ts (2 hunks)
  • packages/core/src/core/life-cycle.ts (1 hunks)
  • packages/core/src/core/memory.ts (2 hunks)
  • packages/core/src/core/orchestrator.ts (12 hunks)
  • packages/core/src/core/room-manager.ts (0 hunks)
  • packages/core/src/core/schedule-service.ts (1 hunks)
  • packages/core/src/core/types/index.ts (7 hunks)
  • packages/core/src/core/vector-db.ts (12 hunks)
💤 Files with no reviewable changes (1)
  • packages/core/src/core/room-manager.ts
✅ Files skipped from review due to trivial changes (1)
  • examples/example-api.ts
🔇 Additional comments (62)
examples/example-server.ts (8)

15-15: Confirmed import path for ConversationManager.
It aligns with the move to a conversation-based architecture and appears correct.


22-22: Verified import for makeFlowLifecycle.
Migrating to a lifecycle approach is consistent with the new conversation-based design.


33-33: Verify data deletion is intentional.
Calling deleteAll() removes all records, which might be useful for development but risky for production.

Do you want to confirm or conditionally disable this in non-dev environments?


54-54: Instantiation of ConversationManager.
This is consistent with the new conversation-based approach. No issues found.


74-74: Lifecycle function usage looks good.
Passing the DB and conversation manager into makeFlowLifecycle is coherent with the new architecture.


104-107: Returning structured response in the output handler.
The return shape with { userId, message } is clear and consistent with typical DTO patterns.


164-164: Dispatching message content with structured payload.
Using { content: userMessage } helps maintain a clear schema for orchestrator dispatch.


246-246: Fetching single orchestrator by ID.
This call is straightforward, with no apparent issues.

examples/example-twitter.ts (17)

13-13: Importing ConversationManager.
Transition from room-based to conversation-based architecture is clear.


28-28: Importing makeFlowLifecycle.
No issues found; it matches the new lifecycle system.


39-40: Purging the vector DB for a fresh session.
Ensure this is done only in a controlled environment to avoid unintended data loss in production.


42-43: Switch from RoomManager to ConversationManager.
This is in line with the new conversation-based flow. No apparent issues.


47-47: Model updated to 'anthropic/claude-3-5-sonnet-latest'.
Ensure the model is accessible and adequately tested for your use case.


58-61: Adding MessageProcessor as an array to MasterProcessor.
This array approach can facilitate adding multiple processors in the future. Good for extensibility.


63-64: Renaming Database to kvDb.
Consistent naming across files.


70-75: Connect and delete all records.
Similar caution as in example-server.ts: verify that clearing data is safe in your environment.


80-80: makeFlowLifecycle integrated with Orchestrator.
Setup is coherent with the new lifecycle approach.


88-97: SchedulerService initialization.
Passing in the orchestrator, DB, and conversation manager ensures modular and flexible scheduling.


104-104: Starting the scheduler.
No issues identified. Good to see asynchronous tasks are managed in a dedicated service.


118-118: Consciousness creation with conversationManager.
Good approach to unify conversation context with the “thinking” process.


134-136: Returning an empty array if there are no mentions.
This gracefully halts further processing, avoiding null checks.


142-142: Mapping mention data to conversation-friendly structure.
Looks well aligned with conversation-based flow.


161-161: Returning an empty array when no thought is generated.
This is consistent with the approach in mention handling. Safe for future expansions.


194-196: Scheduling mention checks every minute.
The frequency is more robust than the previously shorter interval. Ensure rate limits are respected.


197-203: Scheduling thought generation every 5 minutes.
Adequate interval for reflection tasks. No concerns found.

packages/core/src/core/life-cycle.ts (12)

1-8: File introduction and imports.
This file sets the foundation for a lifecycle-based approach. No immediate issues detected in the import statements.


9-20: makeFlowLifecycle initialization and return structure.
Well-structured function returning a FlowLifecycle. The signature is clear and fosters extensibility.


22-36: onFlowStep logic.
Adds new messages to orchestrator if the ID is valid. Straightforward and aligned with conversation-based flow.


58-71: onOutputDispatched.
Mirrors onFlowStep for output messages. No immediate issues found.


73-90: onActionDispatched.
Storing both input and result for the dispatched actions is beneficial for debugging or auditing.


92-111: onContentProcessed.
Ensures unique content is only processed once. This fosters idempotent checks. Implementation looks solid.


112-122: onConversationCreated.
Ensures conversation existence or creation. Straightforward approach for conversation initialization.


124-135: onConversationUpdated.
Currently marks content processed; possibly extend or log updates later.


137-147: onMemoryAdded.
Adds new memory with metadata. Straightforward approach.


149-165: onMemoriesRequested.
Retrieves both vector-based memories and chat history. Combining them in a single response is efficient for conversation context.


167-175: onCheckContentProcessed.
Returns a boolean to indicate whether content was processed. Handy for ensuring no duplicate handling.


179-295: FlowLifecycle interface definition.
Provides a comprehensive set of optional lifecycle hooks. The interface is well-organized and fosters easy customization.

packages/core/src/core/conversation-manager.ts (3)

88-91: Verify usage of "main" as a default platformId.
When platform is "consciousness", you override the platformId to "main". Ensure this doesn’t conflict with other potential conversations or cause collisions.

Would you like a shell script to search for "main" usage across the codebase to confirm there are no conflicts?


115-129: Evaluate storing userId as metadata.
Potentially, userId might be considered sensitive or personally identifiable information (PII). Verify compliance with privacy requirements if storing userId unencrypted.


233-251: Clarify logic in ensureConversation.
The method tries to retrieve by platform ID and name, then creates if missing. Confirm that platformId and name usage won’t conflict or cause accidental overwrites with other user’s data.

packages/core/src/core/orchestrator.ts (1)

119-120: 🛠️ Refactor suggestion

Remove unused generic type parameter <T>.
The method signature still contains <T>, but you’re strictly using ProcessableContent. Consider removing [T] to avoid confusion.

- public async dispatchToOutput<T>(
+ public async dispatchToOutput(
    name: string,
    request: AgentRequest,
    data: ProcessableContent
  ): Promise<unknown> {

Likely invalid or redundant comment.

packages/core/src/core/vector-db.ts (2)

194-197: Clarify the choice of "global" namespace.
When generating an ID for the main “memories” collection, you're passing "global" to createDeterministicMemoryId. Ensure this won't create collisions if you unify conversation-based logic later.


489-497: Avoid name collisions in listConversations.
Filtering by startsWith("conversation_") might create collisions if another collection starts with the same prefix. Consider using a more structured naming or a unique convention.

packages/core/src/core/index.ts (1)

2-3: LGTM! Import and export changes align with the conversation-based refactoring.

The changes correctly introduce the new conversation-related entities while maintaining alphabetical ordering.

Also applies to: 35-36

packages/core/src/core/memory.ts (1)

2-2: LGTM! Memory management interface successfully refactored for conversations.

The changes consistently replace room-related terminology with conversation-related terminology while maintaining proper typing and clear method names.

Also applies to: 65-83

packages/core/src/core/schedule-service.ts (1)

4-4: LGTM! Orchestrator context updated to use conversation management.

The changes correctly integrate conversation management into the scheduler service while maintaining proper typing.

Also applies to: 10-10

examples/example-discord.ts (3)

40-41: Verify the LLM model version.

The model has been updated to use anthropic/claude-3-5-sonnet-latest. Please ensure this is the intended version and that it's compatible with your requirements.


50-52: LGTM! Improved processor initialization.

The code has been simplified by directly instantiating and adding the MessageProcessor, making it more readable and maintainable.


69-69: LGTM! Successfully integrated lifecycle management.

The change properly integrates the new lifecycle hooks system using makeFlowLifecycle, aligning with the PR's objective of implementing lifecycle hooks.

packages/core/src/core/conversation.ts (1)

Line range hint 1-37: LGTM! Well-structured class implementation.

The Conversation class is well-designed with clear separation of concerns, proper type definitions, and comprehensive documentation.

examples/example-basic.ts (2)

91-93: LGTM! Standardized output format.

The change to return an object with a content property aligns with the standardized output format.


128-130: LGTM! Consistent output format.

The GraphQL output handler follows the same standardized format.

packages/core/src/core/consciousness.ts (1)

10-10: LGTM! Clear constant naming.

The constant name CONVERSATION_ID better reflects its purpose.

packages/core/src/core/__tests__/vector-db.test.ts (1)

146-156: LGTM! Tests updated to reflect new terminology.

The test cases have been properly updated to use "conversation" terminology and maintain the same test coverage.

packages/core/src/core/types/index.ts (6)

331-331: LGTM! Consistent with the room to conversation renaming.

The conversationId property is correctly marked as optional with ?, maintaining backward compatibility.


Line range hint 348-355: LGTM! Interface renamed to follow new terminology.

The ConversationMetadata interface maintains the same structure while using the new terminology.


359-359: LGTM! Consistent with the room to conversation renaming.

The conversationId property is correctly marked as required, ensuring proper conversation association for memories.


377-379: LGTM! Method signatures updated consistently.

The VectorDB interface methods have been renamed from room-based to conversation-based terminology while maintaining the same parameter types and structure.

Also applies to: 383-385


555-555: LGTM! Return types updated to use the new ProcessableContent interface.

The execute methods in both InputIOHandler and OutputIOHandler now return Promise<ProcessableContent | ProcessableContent[]> instead of Promise<unknown>, providing better type safety.

Also applies to: 583-583


617-625: LGTM! New interface for processable content.

The ProcessableContent interface provides a flexible structure for content that can be processed, with optional conversationId and contentId properties.

Let's verify that all handlers are updated to use this new interface:

✅ Verification successful

ProcessableContent interface is properly integrated

The verification shows that the ProcessableContent interface is correctly integrated into the core processing flow. The handlers are designed to be implemented as runtime objects rather than classes, with the interface being used appropriately in the orchestrator and type definitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all handler implementations to ensure they're updated to use ProcessableContent
rg -A 5 "implements (Input|Output)IOHandler"

Length of output: 46


Script:

#!/bin/bash
# First, let's find the handler interfaces definitions
echo "=== Searching for handler interface definitions ==="
rg -g "*.ts" "interface.*Handler"

echo -e "\n=== Searching for ProcessableContent usage ==="
rg -g "*.ts" "ProcessableContent"

echo -e "\n=== Using AST to find class implementations ==="
ast-grep --pattern 'class $_ implements $_Handler'

Length of output: 1678


Script:

#!/bin/bash
# Search for execute method implementations
echo "=== Searching for execute method implementations ==="
ast-grep --pattern 'execute($$$) {
  $$$
}'

# Try finding handler classes with a different pattern
echo -e "\n=== Searching for handler class definitions ==="
rg -g "*.ts" "class.*Handler"

# Get the content of BaseIOHandler to understand the interface structure
echo -e "\n=== BaseIOHandler interface definition ==="
rg -A 10 "interface BaseIOHandler" packages/core/src/core/types/index.ts

Length of output: 734

examples/example-goal.ts (2)

109-115: LGTM! Return value updated to match ProcessableContent interface.

The EXECUTE_TRANSACTION handler now correctly returns an object with a content property containing the transaction result.


150-152: LGTM! Return value updated to match ProcessableContent interface.

The GRAPHQL_FETCH handler now correctly returns an object with a content property containing the query result.

Comment on lines +527 to +535
this.logger.error(
"ChromaVectorDB.deleteConversation",
"Deletion failed",
{
error:
error instanceof Error ? error.message : String(error),
conversationId,
}
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle partial failures during conversation deletion.
If partial data remains in the DB or if concurrency issues arise, ensure transactions or retries. Current error handling logs but doesn't retry or confirm re-deletion.

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

🧹 Nitpick comments (3)
packages/core/src/core/orchestrator.ts (3)

Line range hint 72-83: Consider enhancing request simulation.

The fake request object could be enriched with additional context from the handler or subscription data.

Consider this enhancement:

-const fakeRequest: AgentRequest = { headers: {} };
+const fakeRequest: AgentRequest = {
+    headers: {
+        'x-source': handler.name,
+        'x-timestamp': new Date().toISOString(),
+        // Add any relevant metadata from handler
+        ...(handler.metadata && { 'x-metadata': JSON.stringify(handler.metadata) })
+    }
+};

273-282: Enhance error handling in lifecycle hooks.

While the lifecycle hooks implementation is solid, consider adding error handling and retries for hook failures.

Consider wrapping hook calls with error handling:

+private async safeExecuteHook<T>(
+    hookName: string,
+    hook: (...args: any[]) => Promise<T>,
+    ...args: any[]
+): Promise<T | undefined> {
+    try {
+        return await hook(...args);
+    } catch (error) {
+        this.logger.error(
+            "Orchestrator.safeExecuteHook",
+            `Error executing ${hookName}`,
+            { error, args }
+        );
+        return undefined;
+    }
+}

-if (this.flowLifecycle?.onFlowStart) {
-    const maybeId = await this.flowLifecycle.onFlowStart(
-        userId,
-        sourceName,
-        initialData
-    );
+if (this.flowLifecycle?.onFlowStart) {
+    const maybeId = await this.safeExecuteHook(
+        'onFlowStart',
+        this.flowLifecycle.onFlowStart.bind(this.flowLifecycle),
+        userId,
+        sourceName,
+        initialData
+    );

Also applies to: 289-325, 347-365, 373-389


Line range hint 459-565: Enhance documentation for conversation-based processing.

The transition from room to conversation-based processing is well implemented, but could benefit from additional documentation.

Consider adding these documentation improvements:

 /**
  * Process a single item:
  *  - Retrieves prior memories from its conversation
  *  - Passes it to the main (or "master") processor
  *  - Saves result to memory & marks processed if relevant
+ *
+ * @param content - The content to process, must include conversationId for context management
+ * @param source - The source of the content (e.g., handler name)
+ * @param userId - Optional user identifier for conversation management
+ * @returns ProcessedResult containing suggested outputs and actions, or null if already processed
+ *
+ * @example
+ * ```typescript
+ * const result = await processContentItem({
+ *   conversationId: 'conv-123',
+ *   contentId: 'msg-456',
+ *   content: 'Hello, world!'
+ * }, 'discord', 'user-789');
+ * ```
  */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a386074 and 19a6d0c.

📒 Files selected for processing (1)
  • packages/core/src/core/orchestrator.ts (12 hunks)
🔇 Additional comments (2)
packages/core/src/core/orchestrator.ts (2)

3-8: LGTM! Improved modularity with lifecycle hooks.

The transition to FlowLifecycle and ProcessableContent types enhances type safety and provides better separation of concerns.

Also applies to: 12-13, 34-36


119-119: LGTM! Enhanced type safety in dispatch methods.

The transition from generic type T to ProcessableContent provides better type guarantees across all dispatch methods.

Also applies to: 163-163, 206-206

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

🧹 Nitpick comments (1)
packages/core/src/core/orchestrator.ts (1)

531-553: Consider enhancing error handling in memory operations.

The memory operations could benefit from try-catch blocks to handle potential failures gracefully.

         if (
             content.conversationId &&
             result &&
             content.contentId &&
             this.flowLifecycle?.onMemoryAdded &&
             this.flowLifecycle?.onConversationUpdated
         ) {
+            try {
                 await this.flowLifecycle.onMemoryAdded(
                     content.conversationId,
                     JSON.stringify(result.content),
                     source,
                     {
                         ...result.metadata,
                         ...result.enrichedContext,
                     }
                 );
                 await this.flowLifecycle.onConversationUpdated(
                     content.contentId,
                     content.conversationId,
                     JSON.stringify(result.content),
                     source,
                     result.metadata
                 );
+            } catch (error) {
+                this.logger.error(
+                    "Orchestrator.processContentItem",
+                    "Failed to update memory/conversation",
+                    { error, conversationId: content.conversationId }
+                );
+                // Consider whether to throw or handle gracefully
+                throw error;
+            }
         }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 19a6d0c and 2292723.

📒 Files selected for processing (1)
  • packages/core/src/core/orchestrator.ts (13 hunks)
🔇 Additional comments (4)
packages/core/src/core/orchestrator.ts (4)

3-8: LGTM! Clean transition to lifecycle-based architecture.

The changes effectively implement the lifecycle hooks system while maintaining clean dependency management through proper type imports.

Also applies to: 12-13, 34-36


119-119: LGTM! Enhanced type safety in dispatch methods.

Replacing generic type T with ProcessableContent improves type safety and ensures consistent content structure across all dispatch operations.

Also applies to: 163-163, 206-206


243-249: LGTM! Well-structured lifecycle hook integration.

The implementation properly integrates lifecycle hooks at key points (flow start, steps, task scheduling, output/action dispatch) while maintaining clean error boundaries.

Also applies to: 268-277, 284-291, 309-321, 343-360, 368-384


447-450: LGTM! Robust conversation-based memory management.

The implementation properly handles conversation context and memory management with appropriate lifecycle hooks.

Also applies to: 457-510

Comment on lines 424 to 425
// Example delay: remove if not needed
await new Promise((resolve) => setTimeout(resolve, 5000));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove hardcoded delay in content processing.

The 5-second delay appears to be a development artifact and should be removed for production.

-                // Example delay: remove if not needed
-                await new Promise((resolve) => setTimeout(resolve, 5000));

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

🧹 Nitpick comments (3)
packages/core/src/core/life-cycle.ts (1)

1-8: Rename the file to match the comment header.

The file is named life-cycle.ts but the comment header indicates MyFlowLifecycle.ts. This inconsistency should be resolved by either:

  1. Removing the comment header, or
  2. Renaming the file to match the TypeScript naming convention: my-flow-lifecycle.ts
packages/core/src/core/db/mongo-db.ts (1)

217-217: Use Logger class instead of console.log for consistency.

The added debug statements should use the existing Logger class for consistent logging across the codebase.

Replace the console.log statements with Logger:

-        console.log("addMessage", orchestratorId, role, name, data);
+        this.logger.debug("MongoDb.addMessage", "Adding message", { orchestratorId, role, name, data });

-        console.log("getMessages", orchestratorId, doc);
+        this.logger.debug("MongoDb.getMessages", "Retrieved messages", { orchestratorId, doc });

Also applies to: 245-245

packages/core/src/core/orchestrator.ts (1)

536-564: Add error handling for memory operations.

The memory and conversation updates should include error handling to ensure data consistency.

Consider wrapping the operations in try-catch:

 if (content.conversationId && content.contentId) {
+    try {
         await this.flowLifecycle.onMemoryAdded(
             content.conversationId,
             JSON.stringify(result.content),
             source,
             {
                 ...result.metadata,
                 ...result.enrichedContext,
             }
         );

         await this.flowLifecycle.onConversationUpdated(
             content.contentId,
             content.conversationId,
             JSON.stringify(result.content),
             source,
             result.metadata
         );
+    } catch (error) {
+        this.logger.error(
+            "Orchestrator.processContentItem",
+            "Failed to update memory/conversation",
+            { error, contentId: content.contentId, conversationId: content.conversationId }
+        );
+        throw error;
+    }
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2292723 and d8b1973.

📒 Files selected for processing (5)
  • packages/core/src/core/db/mongo-db.ts (2 hunks)
  • packages/core/src/core/io/discord.ts (1 hunks)
  • packages/core/src/core/life-cycle.ts (1 hunks)
  • packages/core/src/core/memory.ts (3 hunks)
  • packages/core/src/core/orchestrator.ts (11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/core/memory.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/core/src/core/orchestrator.ts

[error] 370-374: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (6)
packages/core/src/core/life-cycle.ts (1)

196-308: Well-structured interface with comprehensive documentation.

The FlowLifecycle interface is well-designed with:

  • Clear JSDoc comments explaining each hook's purpose
  • Consistent parameter naming and typing
  • Appropriate use of optional parameters
packages/core/src/core/io/discord.ts (1)

97-98: LGTM! Clean transition from room to conversation model.

The changes correctly map Discord's message and channel IDs to the new conversation-based model:

  • message.id → contentId for unique message identification
  • channel.id → conversationId for conversation context
packages/core/src/core/orchestrator.ts (4)

3-8: LGTM! Clean transition to lifecycle-based architecture.

The changes effectively:

  • Remove room-based management
  • Introduce lifecycle hooks for better modularity
  • Add proper type definitions for ProcessableContent

Also applies to: 12-13, 35-35


259-278: LGTM! Well-structured flow management with lifecycle hooks.

The implementation effectively:

  • Manages flow state through lifecycle hooks
  • Handles queue initialization cleanly
  • Provides proper flow start and step handling

Also applies to: 287-293


437-438: Remove hardcoded delay in content processing.

The 5-second delay appears to be a development artifact and should be removed for production.

-                // Example delay: remove if not needed
-                await new Promise((resolve) => setTimeout(resolve, 5000));

466-468: LGTM! Robust content processing with proper type safety.

The changes effectively:

  • Add proper type safety with ProcessableContent
  • Implement clean conversation-based processing
  • Handle memories and chat history appropriately

Also applies to: 470-473, 475-481, 494-499

Comment on lines 92 to 110
async onContentProcessed(
contentId: string,
conversationId: string,
content: string,
metadata?: Record<string, unknown>
): Promise<void> {
const hasProcessed =
await conversationManager.hasProcessedContentInConversation(
contentId,
conversationId
);
if (hasProcessed) {
return;
}
await conversationManager.markContentAsProcessed(
contentId,
conversationId
);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix parameter type mismatch in onContentProcessed.

The implementation doesn't match the interface definition:

  • Implementation: contentId: string, conversationId: string, content: string, metadata?: Record<string, unknown>
  • Interface: userId: string, conversationId: string, content: string, metadata?: Record<string, unknown>

This mismatch will cause TypeScript compilation errors.

-        async onContentProcessed(
-            contentId: string,
+        async onContentProcessed(
+            userId: string,
             conversationId: string,
             content: string,
             metadata?: Record<string, unknown>
         ): Promise<void> {
             const hasProcessed =
                 await conversationManager.hasProcessedContentInConversation(
-                    contentId,
+                    userId,
                     conversationId
                 );
             if (hasProcessed) {
                 return;
             }
             await conversationManager.markContentAsProcessed(
-                contentId,
+                userId,
                 conversationId
             );
         }

Also applies to: 255-260

Comment on lines 112 to 122
async onConversationCreated(
userId: string,
conversationId: string,
source: string
): Promise<Conversation> {
return await conversationManager.ensureConversation(
conversationId,
source,
userId
);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing metadata parameter to onConversationCreated.

The implementation is missing the optional metadata parameter defined in the interface.

         async onConversationCreated(
             userId: string,
             conversationId: string,
-            source: string
+            source: string,
+            metadata?: Record<string, unknown>
         ): Promise<Conversation> {
             return await conversationManager.ensureConversation(
                 conversationId,
                 source,
-                userId
+                userId,
+                metadata
             );
         }

Also applies to: 265-270

Comment on lines 159 to 178
async onMemoriesRequested(
conversationId: string,
limit?: number
): Promise<{ memories: Memory[]; chatHistory: OrchestratorMessage[] }> {
console.log("onMemoriesRequested", conversationId, limit);
// get vector based memories
// todo, we could base this on a userID so the agent has memories across conversations
const memories =
await conversationManager.getMemoriesFromConversation(
conversationId,
limit
);
// TODO: get history from db
const chatHistory =
await orchestratorDb.getMessages(conversationId);

console.log("chatHistory", memories, chatHistory);

return { memories, chatHistory };
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove debug logs and implement TODO items.

The method contains:

  1. Debug console.log statements that should be removed
  2. TODO comments indicating incomplete implementation
         async onMemoriesRequested(
             conversationId: string,
             limit?: number
         ): Promise<{ memories: Memory[]; chatHistory: OrchestratorMessage[] }> {
-            console.log("onMemoriesRequested", conversationId, limit);
             // get vector based memories
-            // todo, we could base this on a userID so the agent has memories across conversations
             const memories =
                 await conversationManager.getMemoriesFromConversation(
                     conversationId,
                     limit
                 );
-            // TODO: get history from db
             const chatHistory =
                 await orchestratorDb.getMessages(conversationId);

-            console.log("chatHistory", memories, chatHistory);

             return { memories, chatHistory };
         }

Would you like me to help implement the user-based memory retrieval mentioned in the TODO comment?

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async onMemoriesRequested(
conversationId: string,
limit?: number
): Promise<{ memories: Memory[]; chatHistory: OrchestratorMessage[] }> {
console.log("onMemoriesRequested", conversationId, limit);
// get vector based memories
// todo, we could base this on a userID so the agent has memories across conversations
const memories =
await conversationManager.getMemoriesFromConversation(
conversationId,
limit
);
// TODO: get history from db
const chatHistory =
await orchestratorDb.getMessages(conversationId);
console.log("chatHistory", memories, chatHistory);
return { memories, chatHistory };
},
async onMemoriesRequested(
conversationId: string,
limit?: number
): Promise<{ memories: Memory[]; chatHistory: OrchestratorMessage[] }> {
const memories =
await conversationManager.getMemoriesFromConversation(
conversationId,
limit
);
const chatHistory =
await orchestratorDb.getMessages(conversationId);
return { memories, chatHistory };
}

Comment on lines 337 to 408
} else if (handler.role === HandlerRole.ACTION) {
// e.g. fetch data from an external API
const actionResult = await this.dispatchToAction(
output.name,
request,
output.data
);

this.logger.debug(
"Orchestrator.runAutonomousFlow",
"Dispatched action",
{
name: output.name,
data: output.data,
if (this.flowLifecycle?.onFlowStep) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.OUTPUT,
output.name,
output.data
);
}
);

if (orchestratorId) {
await this.orchestratorDb.addMessage(
orchestratorId,
HandlerRole.ACTION,
if (this.flowLifecycle?.onOutputDispatched) {
await this.flowLifecycle.onOutputDispatched(
orchestratorId,
userId,
output.name,
output.data
);
}
break;

case HandlerRole.ACTION:
const actionResult = await this.dispatchToAction(
output.name,
{
input: output.data,
result: actionResult,
}
request,
output.data
);
}

// If the action returns new data, queue it up
if (actionResult) {
if (Array.isArray(actionResult)) {
for (const item of actionResult) {
if (
this.flowLifecycle?.onFlowStep &&
this.flowLifecycle?.onActionDispatched
) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.ACTION,
output.name,
{ input: output.data, result: actionResult }
);
await this.flowLifecycle.onActionDispatched(
orchestratorId,
userId,
output.name,
output.data,
actionResult
);
}

// Queue any new data returned from the action
if (actionResult) {
const newItems = Array.isArray(actionResult)
? actionResult
: [actionResult];
for (const item of newItems) {
queue.push({
data: item,
source: output.name,
});
}
} else {
queue.push({
data: actionResult,
source: output.name,
});
}
}
} else {
this.logger.warn(
"Orchestrator.runAutonomousFlow",
"Suggested output has an unrecognized role",
handler.role
);
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix switch statement declaration scope.

The actionResult declaration in the switch statement can leak to other cases. This was flagged by static analysis.

Wrap the case in a block to prevent variable leakage:

 case HandlerRole.ACTION: {
     const actionResult = await this.dispatchToAction(
         output.name,
         request,
         output.data
     );

     if (
         this.flowLifecycle?.onFlowStep &&
         this.flowLifecycle?.onActionDispatched
     ) {
         await this.flowLifecycle.onFlowStep(
             orchestratorId,
             userId,
             HandlerRole.ACTION,
             output.name,
             { input: output.data, result: actionResult }
         );
         await this.flowLifecycle.onActionDispatched(
             orchestratorId,
             userId,
             output.name,
             output.data,
             actionResult
         );
     }

     if (actionResult) {
         const newItems = Array.isArray(actionResult)
             ? actionResult
             : [actionResult];
         for (const item of newItems) {
             queue.push({
                 data: item,
                 source: output.name,
             });
         }
     }
     break;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
switch (handler.role) {
case HandlerRole.OUTPUT:
outputs.push({
name: output.name,
data: output.data,
}
);
if (orchestratorId) {
await this.orchestratorDb.addMessage(
orchestratorId,
HandlerRole.OUTPUT,
});
await this.dispatchToOutput(
output.name,
request,
output.data
);
}
} else if (handler.role === HandlerRole.ACTION) {
// e.g. fetch data from an external API
const actionResult = await this.dispatchToAction(
output.name,
request,
output.data
);
this.logger.debug(
"Orchestrator.runAutonomousFlow",
"Dispatched action",
{
name: output.name,
data: output.data,
if (this.flowLifecycle?.onFlowStep) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.OUTPUT,
output.name,
output.data
);
}
);
if (orchestratorId) {
await this.orchestratorDb.addMessage(
orchestratorId,
HandlerRole.ACTION,
if (this.flowLifecycle?.onOutputDispatched) {
await this.flowLifecycle.onOutputDispatched(
orchestratorId,
userId,
output.name,
output.data
);
}
break;
case HandlerRole.ACTION:
const actionResult = await this.dispatchToAction(
output.name,
{
input: output.data,
result: actionResult,
}
request,
output.data
);
}
// If the action returns new data, queue it up
if (actionResult) {
if (Array.isArray(actionResult)) {
for (const item of actionResult) {
if (
this.flowLifecycle?.onFlowStep &&
this.flowLifecycle?.onActionDispatched
) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.ACTION,
output.name,
{ input: output.data, result: actionResult }
);
await this.flowLifecycle.onActionDispatched(
orchestratorId,
userId,
output.name,
output.data,
actionResult
);
}
// Queue any new data returned from the action
if (actionResult) {
const newItems = Array.isArray(actionResult)
? actionResult
: [actionResult];
for (const item of newItems) {
queue.push({
data: item,
source: output.name,
});
}
} else {
queue.push({
data: actionResult,
source: output.name,
});
}
}
} else {
this.logger.warn(
"Orchestrator.runAutonomousFlow",
"Suggested output has an unrecognized role",
handler.role
);
break;
switch (handler.role) {
case HandlerRole.OUTPUT:
outputs.push({
name: output.name,
data: output.data,
});
await this.dispatchToOutput(
output.name,
request,
output.data
);
if (this.flowLifecycle?.onFlowStep) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.OUTPUT,
output.name,
output.data
);
}
if (this.flowLifecycle?.onOutputDispatched) {
await this.flowLifecycle.onOutputDispatched(
orchestratorId,
userId,
output.name,
output.data
);
}
break;
case HandlerRole.ACTION: {
const actionResult = await this.dispatchToAction(
output.name,
request,
output.data
);
if (
this.flowLifecycle?.onFlowStep &&
this.flowLifecycle?.onActionDispatched
) {
await this.flowLifecycle.onFlowStep(
orchestratorId,
userId,
HandlerRole.ACTION,
output.name,
{ input: output.data, result: actionResult }
);
await this.flowLifecycle.onActionDispatched(
orchestratorId,
userId,
output.name,
output.data,
actionResult
);
}
// Queue any new data returned from the action
if (actionResult) {
const newItems = Array.isArray(actionResult)
? actionResult
: [actionResult];
for (const item of newItems) {
queue.push({
data: item,
source: output.name,
});
}
}
break;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 370-374: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

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

♻️ Duplicate comments (4)
packages/core/src/core/life-cycle.ts (3)

86-104: ⚠️ Potential issue

Fix parameter type mismatch in onContentProcessed.

The implementation doesn't match the interface definition:

  • Implementation: contentId: string, threadId: string, content: string, metadata?: Record<string, unknown>
  • Interface: userId: string, threadId: string, content: string, metadata?: Record<string, unknown>

Apply this diff to fix the parameter type mismatch:

-        async onContentProcessed(
-            contentId: string,
+        async onContentProcessed(
+            userId: string,
             threadId: string,
             content: string,
             metadata?: Record<string, unknown>
         ): Promise<void> {
             const hasProcessed =
                 await conversationManager.hasProcessedContentInConversation(
-                    contentId,
+                    userId,
                     threadId
                 );
             if (hasProcessed) {
                 return;
             }
             await conversationManager.markContentAsProcessed(
-                contentId,
+                userId,
                 threadId
             );
         }

106-116: ⚠️ Potential issue

Add missing metadata parameter to onConversationCreated.

The implementation is missing the optional metadata parameter defined in the interface.

Apply this diff to fix the missing parameter:

         async onConversationCreated(
             userId: string,
             threadId: string,
-            source: string
+            source: string,
+            metadata?: Record<string, unknown>
         ): Promise<Conversation> {
             return await conversationManager.ensureConversation(
                 threadId,
                 source,
-                userId
+                userId,
+                metadata
             );
         }

153-166: 🛠️ Refactor suggestion

Remove debug logs and implement TODO items.

The method contains a TODO comment indicating incomplete implementation.

Would you like me to help implement the user-based memory retrieval mentioned in the TODO comment?

packages/core/src/core/orchestrator.ts (1)

394-395: ⚠️ Potential issue

Remove hardcoded delay in content processing.

The 5-second delay appears to be a development artifact and should be removed for production.

-                // Example delay: remove if not needed
-                await new Promise((resolve) => setTimeout(resolve, 5000));
🧹 Nitpick comments (6)
packages/core/src/core/memory.ts (1)

43-49: Consider adding validation for messageId format.

The ChatMessage interface looks good, but consider adding platform-specific validation for messageId formats.

examples/example-discord.ts (1)

37-37: Consider adding error handling for ConversationManager initialization.

While the transition to ConversationManager is good, consider adding error handling for initialization failures.

-    const conversationManager = new ConversationManager(vectorDb);
+    try {
+        const conversationManager = new ConversationManager(vectorDb);
+    } catch (error) {
+        console.error(chalk.red("Failed to initialize ConversationManager:"), error);
+        process.exit(1);
+    }

Also applies to: 50-52

packages/core/src/core/io/discord.ts (1)

146-149: Consider adding type guard for MessageData casting.

The type casting could be safer with a type guard.

-                return (await this.sendMessage(
-                    data as MessageData
-                )) as unknown as ProcessableContent;
+                if (this.isMessageData(data)) {
+                    return await this.sendMessage(data) as unknown as ProcessableContent;
+                }
+                throw new Error('Invalid message data format');

+    private isMessageData(data: unknown): data is MessageData {
+        return typeof data === 'object' && data !== null && 'content' in data;
+    }
examples/example-server.ts (1)

24-33: Consider using environment variables for database configuration.

The database connection details are hardcoded. Consider using environment variables for better configurability.

+const DB_HOST = process.env.DB_HOST || 'localhost';
+const DB_PORT = process.env.DB_PORT || '27017';
+const DB_NAME = process.env.DB_NAME || 'myApp';
+const DB_COLLECTION = process.env.DB_COLLECTION || 'scheduled_tasks';

-const kvDb = new MongoDb(
-    "mongodb://localhost:27017",
-    "myApp",
-    "scheduled_tasks"
-);
+const kvDb = new MongoDb(
+    `mongodb://${DB_HOST}:${DB_PORT}`,
+    DB_NAME,
+    DB_COLLECTION
+);
packages/core/src/core/types/index.ts (2)

620-629: Add JSDoc comments for each field in ProcessableContent.

While the interface is well-structured, adding JSDoc comments for each field would improve code maintainability.

 /**
  * Base interface for any content that can be processed
+ * @interface ProcessableContent
  */
 export interface ProcessableContent {
+    /** Unique identifier for the content */
     contentId: string;
+    /** Identifier of the user who created/owns the content */
     userId: string;
+    /** Identifier of the platform where the content originated */
     platformId: string;
+    /** Identifier of the conversation thread */
     threadId: string;
+    /** The actual content data */
     data: unknown;
 }

631-648: Add JSDoc comments for Chat and ChatMessage interfaces.

While the interfaces are well-structured, adding JSDoc comments would improve code maintainability.

+/**
+ * Represents a chat conversation between users or agents
+ * @interface Chat
+ */
 export interface Chat {
     _id?: string;
     userId: string; // the user the agent is interacting with  could be an agent or a human
     platformId: string; // e.g., "twitter", "telegram"
     threadId: string; // platform-specific thread/conversation ID
     createdAt: Date;
     updatedAt: Date;
     messages: ChatMessage[];
     metadata?: Record<string, any>; // Platform-specific data
 }

+/**
+ * Represents a single message within a chat conversation
+ * @interface ChatMessage
+ */
 export interface ChatMessage {
+    /** The role of the message sender (input/output/action) */
     role: HandlerRole;
+    /** Name identifier of the sender */
     name: string;
+    /** The message content */
     data: unknown;
+    /** When the message was sent */
     timestamp: Date;
+    /** Platform-specific message identifier */
     messageId?: string; // Platform-specific message ID if available
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d8b1973 and b698401.

📒 Files selected for processing (10)
  • examples/example-api.ts (7 hunks)
  • examples/example-discord.ts (6 hunks)
  • examples/example-server.ts (7 hunks)
  • examples/example-twitter.ts (8 hunks)
  • packages/core/src/core/db/mongo-db.ts (6 hunks)
  • packages/core/src/core/io/discord.ts (4 hunks)
  • packages/core/src/core/life-cycle.ts (1 hunks)
  • packages/core/src/core/memory.ts (3 hunks)
  • packages/core/src/core/orchestrator.ts (11 hunks)
  • packages/core/src/core/types/index.ts (7 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/core/src/core/orchestrator.ts

[error] 335-338: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (24)
packages/core/src/core/memory.ts (3)

32-41: Well-structured Chat interface with comprehensive platform support.

The new Chat interface effectively captures platform-specific details and metadata, promoting better integration with various messaging platforms.


89-107: LGTM: Consistent renaming from room to conversation.

The MemoryManager interface methods have been consistently renamed from room to conversation-based naming.


58-70: Verify data type consistency across platform integrations.

The new chat-related methods in OrchestratorDb use more specific types (unknown vs any) and include platform-specific identifiers. Ensure all platform integrations conform to these types.

✅ Verification successful

Verification of Data Type Consistency

Based on our investigation across the codebase, the chat-related methods and platform integrations are using the intended types. In particular:

  • In packages/core/src/core/memory.ts, the signatures consistently use platformId: string, threadId: string, and distinguish between metadata?: Record<string, any> and data: unknown.
  • The type definitions in packages/core/src/core/types/index.ts and other files (such as mongo-db.ts, conversation-manager.ts, and orchestrator.ts) align with these definitions.
  • Example integrations (e.g., in the examples/ directory) confirm that required identifiers for platform-specific operations are passed as strings, and the message payload is handled as the unknown type.

There are no inconsistencies or mismatches in data types between the core memory module and platform integrations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for platform-specific message handling
rg -A 5 "platformId|threadId" --type typescript

Length of output: 84


Script:

#!/bin/bash
# Improved search for platform-specific message handling in TypeScript files.
rg -A 5 'platformId|threadId' -g '*.ts'

Length of output: 20246

examples/example-discord.ts (1)

Line range hint 69-74: LGTM: Improved orchestrator initialization with lifecycle hooks.

The use of makeFlowLifecycle provides better separation of concerns.

packages/core/src/core/io/discord.ts (1)

103-109: Verify message data structure compatibility.

The new message structure includes platform-specific identifiers. Ensure all consumers handle this format correctly.

✅ Verification successful

Message structure compatibility verified.
After examining the propagation of the new fields (platformId, threadId, and contentId) across the codebase and confirming that these identifiers are used consistently—for example, in type definitions and in various message consumers—it appears that the new nested design (with the content now wrapped inside a data object) aligns with the overall message contract. There’s no evidence that any consumers expect a flat “content” property, so all usages now reference the updated structure.

  • The identifiers (platformId, threadId, and contentId) are broadly referenced, ensuring consistent propagation.
  • Type definitions in the core types have been updated accordingly.
  • There’s no sign of legacy code expecting a flat “content” field rather than one under “data.”
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for message handling implementations
ast-grep --pattern 'data: { content: $_.$_ }'

Length of output: 47


Script:

#!/bin/bash
echo "Searching for 'platformId' occurrences:"
rg "platformId" -n .

echo "Searching for 'threadId' occurrences:"
rg "threadId" -n .

echo "Searching for 'contentId' occurrences:"
rg "contentId" -n .

Length of output: 10475

examples/example-server.ts (1)

157-163: LGTM: Improved message dispatch with platform-specific identifiers.

The message dispatch now includes all necessary platform-specific information.

examples/example-api.ts (3)

12-12: LGTM!

The import changes align with the PR objectives of transitioning from room to conversation management.

Also applies to: 25-25


37-37: LGTM!

The initialization of ConversationManager and its integration with makeFlowLifecycle is consistent with the new architecture.

Also applies to: 80-80


215-220: LGTM!

The updated payload structure provides better context with platformId and threadId fields.

examples/example-twitter.ts (5)

13-13: LGTM!

The import changes align with the PR objectives of transitioning from room to conversation management.

Also applies to: 28-28


42-43: LGTM!

The initialization of ConversationManager is consistent with the new architecture.


63-64: LGTM!

The variable renaming from scheduledTaskDb to kvDb improves clarity by better reflecting its purpose.


206-215: LGTM!

The task scheduling intervals have been adjusted to more reasonable values:

  • Twitter mentions check: 60s (was 6s)
  • Thought generation: 5min (was undefined)

139-153: LGTM!

The updated payload structure for mentions provides better context with userId, threadId, contentId, and platformId fields.

packages/core/src/core/db/mongo-db.ts (3)

14-14: LGTM!

The new chatsCollection property and index creation for efficient querying are well implemented:

  • Compound index on (userId, platformId, threadId)
  • Unique constraint ensures data integrity

Also applies to: 40-50


201-228: LGTM!

The getOrCreateChat method is well implemented with:

  • Proper error handling
  • Type safety
  • Efficient querying using the compound index

Line range hint 239-264: LGTM!

The renamed methods addChatMessage and getChatMessages are consistent with the new conversation-centric architecture.

Also applies to: 266-273

packages/core/src/core/types/index.ts (4)

331-331: LGTM!

The change from roomId to conversationId is consistent with the PR objectives.


Line range hint 348-354: LGTM!

The ConversationMetadata interface is well-structured with all necessary fields for tracking conversations, participants, and metadata.


359-359: LGTM!

The change from roomId to conversationId is consistent with the PR objectives.


377-387: LGTM!

The method renames from storeInRoom/findSimilarInRoom to storeInConversation/findSimilarInConversation are consistent with the PR objectives.

packages/core/src/core/orchestrator.ts (3)

34-36: LGTM!

The replacement of RoomManager with FlowLifecycle improves modularity and aligns with the PR objectives.


Line range hint 409-495: LGTM!

The refactoring of processContentItem to use FlowLifecycle hooks improves modularity and maintainability. The error handling and logging improvements are also beneficial.


334-366: ⚠️ Potential issue

Fix switch statement declaration scope.

The actionResult declaration in the switch statement can leak to other cases.

Apply this diff to fix the scope:

-                        case HandlerRole.ACTION:
-                            const actionResult = await this.dispatchToAction(
-                                output.name,
-                                output.data
-                            );
+                        case HandlerRole.ACTION: {
+                            const actionResult = await this.dispatchToAction(
+                                output.name,
+                                output.data
+                            );

                             await this.flowHooks.onFlowStep(
                                 chatId,
                                 HandlerRole.ACTION,
                                 output.name,
                                 { input: output.data, result: actionResult }
                             );

                             await this.flowHooks.onActionDispatched(
                                 chatId,
                                 output.name,
                                 output.data,
                                 actionResult
                             );

                             if (actionResult) {
                                 const newItems = Array.isArray(actionResult)
                                     ? actionResult
                                     : [actionResult];
                                 for (const item of newItems) {
                                     queue.push({
                                         data: item,
                                         source: output.name,
                                     });
                                 }
                             }
                             break;
+                        }

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 335-338: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

@ponderingdemocritus ponderingdemocritus merged commit de959ac into main Feb 1, 2025
5 checks passed
@ponderingdemocritus ponderingdemocritus deleted the hooks branch February 1, 2025 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant