Skip to content

feat: enhance message processing with document handling and summary generation#11

Merged
wtfsayo merged 7 commits intoelizaos-plugins:1.xfrom
Neysixx:feat/attachments
Sep 22, 2025
Merged

feat: enhance message processing with document handling and summary generation#11
wtfsayo merged 7 commits intoelizaos-plugins:1.xfrom
Neysixx:feat/attachments

Conversation

@Neysixx
Copy link
Copy Markdown
Contributor

@Neysixx Neysixx commented Aug 6, 2025

  • Added processDocument method to handle various document types, including PDFs and text files.
  • Implemented centralized document processing based on MIME type.
  • Updated processMessage to integrate document processing and summary extraction.
  • Enhanced logging for document processing and error handling.

Summary by CodeRabbit

  • New Features

    • Added support for processing documents (PDF, plain text, CSV, JSON) in Telegram messages, with automatic extraction of titles, descriptions, and content previews.
    • Enhanced message handling to include attachments with detailed metadata and summaries.
    • Introduced text cleaning utility to remove null characters from message content.
  • Bug Fixes

    • Improved filtering to exclude non-image files (such as PDFs) from image processing.
  • Refactor

    • Unified content and attachment extraction for messages, streamlining processing and improving consistency.

…eneration

- Introduced `generateSummary` function to create concise summaries for text.
- Added `processDocument` method to handle various document types, including PDFs and text files.
- Implemented centralized document processing based on MIME type.
- Updated `processMessage` to integrate document processing and summary extraction.
- Enhanced logging for document processing and error handling.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 6, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The update enhances the MessageManager class with advanced document processing for Telegram messages. It introduces methods for extracting, summarizing, and attaching content from PDFs, text, CSV, and JSON files, as well as refactoring message handling to unify content and attachment extraction. Logging and error handling are also improved. Additionally, a new utility function cleanText was added to remove NULL characters from strings.

Changes

Cohort / File(s) Change Summary
MessageManager Document Processing
src/messageManager.ts
Added comprehensive document processing to MessageManager: new interface for document results, summary generation, PDF/text extraction, MIME-type-based processing, unified message processing, attachment enrichment, improved logging, and error handling. Refactored handleMessage to leverage these features and include attachments in memory content.
Text Cleaning Utility
src/utils.ts
Added cleanText function to remove NULL characters from input strings, returning sanitized text or empty string if input is falsy.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Telegram
    participant MessageManager
    participant PDFService
    participant Summarizer

    User->>Telegram: Sends message with document
    Telegram->>MessageManager: Receives message
    MessageManager->>MessageManager: processMessage(message)
    alt Document detected
        MessageManager->>MessageManager: processDocument(message)
        alt PDF Document
            MessageManager->>PDFService: Convert PDF to text
            PDFService-->>MessageManager: Text content
        else Text/CSV/JSON Document
            MessageManager->>MessageManager: Fetch and extract text
        end
        MessageManager->>Summarizer: generateSummary(text)
        Summarizer-->>MessageManager: Title, description
        MessageManager->>MessageManager: Build attachment with summary
    end
    MessageManager->>MessageManager: Compose processedContent, attachments
    MessageManager-->>Telegram: Callback/event with enriched content
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐇✨
In the warren of code, I hop with delight,
Summarizing documents, day and night.
PDFs, texts, all processed anew,
Titles and previews, concise and true.
Attachments now sparkle, content refined—
A message enriched, for all bunnykind!
🌱📄

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.
  • 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.

Support

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

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.

@cursor
Copy link
Copy Markdown

cursor Bot commented Aug 6, 2025

Bugbot found 3 bugs

To see them, have a team admin activate your membership in the Cursor dashboard.

Copy link
Copy Markdown
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

🧹 Nitpick comments (6)
src/messageManager.ts (6)

169-179: Remove duplicate JSDoc comments

There are two JSDoc comment blocks for the same method. Keep only one comprehensive documentation block.

Remove the duplicate JSDoc block at lines 169-175 and keep the more concise one at lines 176-179.


217-222: Consider making processors a class property for better performance

The processors object is recreated on every call. Consider making it a class property to avoid repeated object creation.

Move the processors definition to a class property:

export class MessageManager {
  public bot: Telegraf<Context>;
  protected runtime: IAgentRuntime;
+ private readonly documentProcessors = {
+   "application/pdf": this.processPdfDocument.bind(this),
+   "text/plain": this.processTextDocument.bind(this),
+   "text/csv": this.processTextDocument.bind(this),
+   "application/json": this.processTextDocument.bind(this),
+ };

  // ... rest of the class

  private getDocumentProcessor(mimeType?: string): ((document: Document, url: string) => Promise<{ description: string }>) | null {
    if (!mimeType) return null;

-   const processors = {
-     "application/pdf": this.processPdfDocument.bind(this),
-     "text/plain": this.processTextDocument.bind(this),
-     "text/csv": this.processTextDocument.bind(this),
-     "application/json": this.processTextDocument.bind(this),
-   };

-   for (const [pattern, processor] of Object.entries(processors)) {
+   for (const [pattern, processor] of Object.entries(this.documentProcessors)) {
      if (mimeType.startsWith(pattern)) {
        return processor;
      }
    }

Note: You'll need to initialize the bindings in the constructor if you go with this approach.


322-323: Remove duplicate logging statement

The same log message appears at the beginning and end of the method.

Remove the duplicate logging at line 408 since the one at line 322 already captures the initial state.

Also applies to: 408-409


671-671: Consider using empty string instead of space for fallback

Using a single space " " as fallback for empty text could cause issues with trimming operations downstream.

- text: processedContent || " ",
+ text: processedContent || "",

30-75: Add unit tests for the generateSummary function

This critical function handles AI model interactions and JSON parsing. It should have comprehensive unit tests covering success cases, parsing failures, and edge cases.

Would you like me to generate unit tests for the generateSummary function or open an issue to track this task?


180-300: Consider implementing caching for document processing

Documents might be processed multiple times if referenced in different messages. Consider implementing a simple cache to avoid redundant processing of the same documents.

You could use a Map or LRU cache with document file_id as the key and processed content as the value, with appropriate TTL to manage memory usage.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between edaa711 and 3597267.

📒 Files selected for processing (1)
  • src/messageManager.ts (6 hunks)
⏰ 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

Comment thread src/messageManager.ts Outdated
Comment thread src/messageManager.ts Outdated
Comment thread src/messageManager.ts Outdated
Comment thread src/messageManager.ts Outdated
Comment thread src/messageManager.ts Outdated
Neysixx added 2 commits August 6, 2025 18:47
- Introduced `DocumentProcessingResult` interface for better structure in document handling.
- Updated `generateSummary` function to return a summary instead of a description.
- Refactored `processDocument`, `processPdfDocument`, and `processTextDocument` methods to utilize the new structured result format.
- Enhanced logging and error handling to improve clarity and maintainability.
- Introduced `cleanText` utility function to remove NULL characters from text.
- Updated `MessageManager` to utilize `cleanText` for processing message content and attachments.
- Ensured that both processed content and attachments are cleaned before further processing.
@0xbbjoker
Copy link
Copy Markdown
Contributor

cursor review

cursor[bot]

This comment was marked as outdated.

@odilitime
Copy link
Copy Markdown
Member

odilitime commented Aug 7, 2025

the improved document handling is great, but I think the summarization doesn't belong here, more of a pluing-knowledge thing in my book.

an uploaded document (text-based) could be run through embeddings and saved to memories. And then other actions and subsystem could provide summaries or do searches.

- Eliminated the `generateSummary` function and its usage in document processing methods.
- Updated `MessageManager` to directly set titles and descriptions based on document metadata.
- Simplified formatted descriptions for PDF and text documents, removing summary references.
cursor[bot]

This comment was marked as outdated.

- Modified `formattedDescription` in `MessageManager` to reflect successful text extraction for both PDF and text documents.
- Removed references to errors in content extraction, enhancing clarity in document summaries.
@Neysixx
Copy link
Copy Markdown
Contributor Author

Neysixx commented Aug 7, 2025

the improved document handling is great, but I think the summarization doesn't belong here, more of a pluing-knowledge thing in my book.

an uploaded document (text-based) could be run through embeddings and saved to memories. And then other actions and subsystem could provide summaries or do searches.

You're right, I've deleted the part about summarization.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 8d32336 and 2def7c7.

📒 Files selected for processing (1)
  • src/messageManager.ts (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/messageManager.ts (1)
src/utils.ts (1)
  • cleanText (222-225)
⏰ 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)
src/messageManager.ts (7)

28-39: Well-structured interface for document processing results

The DocumentProcessingResult interface effectively addresses the previous fragile string parsing approach by providing structured data fields. This improves maintainability and reduces parsing errors.


10-27: LGTM - Import changes support new functionality

The added imports are appropriate for the new document processing capabilities and text cleaning functionality.


110-111: Good logic improvement to exclude PDFs from image processing

The additional filter prevents PDF documents from being incorrectly processed as images, which improves processing accuracy.


287-382: Excellent refactoring that addresses previous review concerns

This method successfully:

  • Eliminates redundant document processing by processing once and reusing results
  • Uses structured data directly instead of fragile regex parsing
  • Provides comprehensive error handling with fallback attachments
  • Includes proper logging for debugging
  • Consolidates message processing logic effectively

The implementation properly addresses all the issues identified in past reviews.


609-623: LGTM - Well-implemented refactoring with proper sanitization

The refactoring effectively:

  • Utilizes the new unified processMessage method for cleaner code organization
  • Applies cleanText sanitization to prevent NULL character issues
  • Properly handles edge cases by skipping messages without meaningful content
  • Maintains all existing functionality while improving code structure

651-652: Good data integrity practice

Using cleaned content and attachments in the memory object ensures NULL characters don't cause issues in downstream processing.


657-661: LGTM - Reply functionality preserved correctly

The reply-to functionality is properly maintained with appropriate UUID generation for message references.

Comment thread src/messageManager.ts
Comment thread src/messageManager.ts
Copy link
Copy Markdown
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

🔭 Outside diff range comments (2)
src/messageManager.ts (2)

100-101: Avoid logging full Telegram message objects (PII risk and noisy logs)

Dumping the entire message leaks PII and drastically increases log volume. Log only essentials at debug level.

Apply:

-      logger.info(`Telegram Message: ${JSON.stringify(message, null, 2)}`);
+      logger.debug(
+        {
+          messageId: (message as any).message_id,
+          chatId: (message as any).chat?.id,
+          hasPhoto: 'photo' in message,
+          hasDocument: 'document' in message,
+        },
+        'Telegram message received'
+      );

388-416: Async map not awaited → possible unhandled rejections; improve contentType mapping

  • The async map is not awaited; failures will be unhandled and the function returns immediately, racing the send operations.
  • The 'doc' prefix isn’t a valid MIME prefix; map on standard prefixes like application/ and text/.
-    if (content.attachments && content.attachments.length > 0) {
-      content.attachments.map(async (attachment: Media) => {
-        const typeMap: { [key: string]: MediaType } = {
-          'image/gif': MediaType.ANIMATION,
-          image: MediaType.PHOTO,
-          doc: MediaType.DOCUMENT,
-          video: MediaType.VIDEO,
-          audio: MediaType.AUDIO,
-        };
+    if (content.attachments && content.attachments.length > 0) {
+      await Promise.all(content.attachments.map(async (attachment: Media) => {
+        const typeMap: { [key: string]: MediaType } = {
+          'image/gif': MediaType.ANIMATION,
+          'image/': MediaType.PHOTO,
+          'video/': MediaType.VIDEO,
+          'audio/': MediaType.AUDIO,
+          'application/': MediaType.DOCUMENT,
+          'text/': MediaType.DOCUMENT,
+        };

         let mediaType: MediaType | undefined = undefined;

-        for (const prefix in typeMap) {
+        for (const prefix of Object.keys(typeMap)) {
           if (attachment.contentType?.startsWith(prefix)) {
             mediaType = typeMap[prefix];
             break;
           }
         }

         if (!mediaType) {
           throw new Error(
             `Unsupported Telegram attachment content type: ${attachment.contentType}`
           );
         }

         await this.sendMedia(ctx, attachment.url, mediaType, attachment.description);
-      });
+      }));
       return [];
     } else {

Optional: consider returning the sent media messages so the caller can create memories for attachments; this would require sendMedia to return the Telegram message object instead of void.

🧹 Nitpick comments (1)
src/messageManager.ts (1)

198-210: Clarify fallback message when PDF service is unavailable

This is not a processing error; it’s a feature unavailability. Make the message neutral to avoid confusion.

-          formattedDescription: `[PDF Document: ${document.file_name || 'Unknown Document'}\nSize: ${document.file_size || 0} bytes\nUnable to extract text content]`,
+          formattedDescription: `[PDF Document: ${document.file_name || 'Unknown Document'}\nSize: ${document.file_size || 0} bytes\nText extraction unavailable (PDF service not configured)]`,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 3263938 and 953ba95.

📒 Files selected for processing (1)
  • src/messageManager.ts (5 hunks)
⏰ 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 (6)
src/messageManager.ts (6)

106-106: Exclude PDFs from image-doc path — good guard

The additional check to skip PDFs in the image document branch is correct and prevents misclassification.


221-229: PDF success path messaging is now accurate

The formattedDescription correctly reflects successful extraction with character count. Good fix.


247-276: Text document success path messaging is accurate

The success message reflects extracted character count; error path is informative. Looks good.


369-371: Accurate post-processing attachments count logging

Logging after processing documents and images avoids the earlier "0 attachments" issue. Good.


577-588: Null character sanitization for content and attachments is correct

Cleaning both text and attachment fields proactively prevents downstream issues. Nice touch.


132-170: AI summary mismatches current code (summarization removed)

The AI summary mentions summary generation, but the code no longer generates summaries or calls a generateSummary function. The refactor correctly focuses on document handling only.

Likely an incorrect or invalid review comment.

Comment thread src/messageManager.ts
Comment thread src/messageManager.ts
Comment thread src/messageManager.ts
- Handling all text/* documents.
- Removed commented-out code and unnecessary comments in `MessageManager` for improved readability.
- Updated import statements in `utils.ts` to use type imports for better clarity and performance.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (3)
src/messageManager.ts (3)

363-365: LGTM: Log after processing attachments

This corrects the earlier premature logging issue—count now reflects processed attachments.


124-131: Outdated JSDoc return type for processDocument

JSDoc still says it returns { description: string } | null, but the function returns DocumentProcessingResult | null.

Apply this diff:

-  /**
-   * Process a document from a Telegram message to extract the document URL and description.
-   * Handles PDFs and other document types by converting them to text when possible.
-   *
-   * @param {Message} message - The Telegram message object containing the document.
-   * @returns {Promise<{ description: string } | null>} The description of the processed document or null if no document found.
-   */
+  /**
+   * Process a document from a Telegram message and extract its content.
+   * Handles PDFs, text files, and other document types centrally.
+   *
+   * @param {Message} message - The Telegram message object containing the document.
+   * @returns {Promise<DocumentProcessingResult | null>}
+   */

306-310: Bound embedded document text to avoid memory/token bloat

Appending full document text into processedContent can be huge. Truncate in the message body and keep the full text in the attachment.

Apply this diff:

-          if (fullText) {
-            const documentContent = `\n\n--- DOCUMENT CONTENT ---\nTitle: ${title}\n\nFull Content:\n${fullText}\n--- END DOCUMENT ---\n\n`;
-            processedContent += documentContent;
-          }
+          if (fullText) {
+            const MAX_EMBED_CHARS = 20000;
+            const embeddedText =
+              fullText.length > MAX_EMBED_CHARS
+                ? `${fullText.slice(0, MAX_EMBED_CHARS)}... [truncated]`
+                : fullText;
+            const documentContent = `\n\n--- DOCUMENT CONTENT ---\nTitle: ${title}\n\nFull Content:\n${embeddedText}\n--- END DOCUMENT ---\n\n`;
+            processedContent += documentContent;
+          }
🧹 Nitpick comments (1)
src/messageManager.ts (1)

105-108: Simplify image document MIME check

The negative PDF check is redundant because a MIME starting with image/ cannot start with application/pdf.

Apply this diff:

-} else if ('document' in message && message.document?.mime_type?.startsWith('image/') && !message.document?.mime_type?.startsWith('application/pdf')) {
+} else if ('document' in message && message.document?.mime_type?.startsWith('image/')) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 953ba95 and 22006b3.

📒 Files selected for processing (2)
  • src/messageManager.ts (5 hunks)
  • src/utils.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/messageManager.ts (1)
src/utils.ts (1)
  • cleanText (222-225)
🪛 Biome (2.1.2)
src/utils.ts

[error] 224-225: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)

⏰ 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 (3)
src/utils.ts (1)

2-3: LGTM: Type-only imports reduce runtime footprint

Using type-only imports for Button and InlineKeyboardButton is correct and avoids bundling types at runtime.

src/messageManager.ts (2)

170-186: LGTM: MIME router with prefix matching

The prefix-based routing covers text/* broadly and keeps application/json explicit. This is clear and extensible.


571-579: LGTM: Sanitize content and attachments via cleanText

Good defensive step to strip NULLs before persistence; prevents downstream formatting/parsing issues.

Comment thread src/messageManager.ts
Comment thread src/utils.ts
@Neysixx
Copy link
Copy Markdown
Contributor Author

Neysixx commented Aug 22, 2025

up

@standujar standujar requested a review from odilitime August 28, 2025 14:28
@wtfsayo wtfsayo merged commit 07d8cd6 into elizaos-plugins:1.x Sep 22, 2025
2 checks passed
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.

5 participants