Skip to content

feat: migrate to runtime.handleMessage()#17

Merged
wtfsayo merged 2 commits into1.xfrom
feat/telegram-use-message-service
Oct 20, 2025
Merged

feat: migrate to runtime.handleMessage()#17
wtfsayo merged 2 commits into1.xfrom
feat/telegram-use-message-service

Conversation

@0xbbjoker
Copy link
Copy Markdown
Contributor

@0xbbjoker 0xbbjoker commented Oct 9, 2025

Migrates Telegram plugin from event-based message handling to direct
MessageService calls, making message flow easier to trace and debug.

Changes:

  • Replace runtime.emitEvent(MESSAGE_RECEIVED) with runtime.handleMessage()
  • Remove unused event imports (EventType, TelegramEventTypes, TelegramMessageReceivedPayload)
  • Update @elizaos/core dependency to workspace:* for local development
  • Fix Zod error typing in environment.ts validation

Benefits:

  • Clear call stack: Telegram → runtime.handleMessage() → MessageService
  • Easier debugging: can step through entire flow without event routing
  • Better developer experience: no hidden event dispatching

Before:
this.runtime.emitEvent(EventType.MESSAGE_RECEIVED, {
runtime: this.runtime, message: memory, callback, source: 'telegram'
});
this.runtime.emitEvent(TelegramEventTypes.MESSAGE_RECEIVED, {...});

After:
await this.runtime.handleMessage(memory, callback);

Requires: feat/core-message-service-interface


Note

Replaces event-based Telegram message handling with direct MessageService.handleMessage calls, and cleans up Zod validation and document-processing logs/formatting.

  • Telegram message handling:
    • Replace runtime.emitEvent(...MESSAGE_RECEIVED...) with direct runtime.messageService.handleMessage(runtime, memory, callback) and add missing-service guard.
    • Minor refactors in processMessage/document handlers: consistent quotes, multiline conditions, improved error logging, and attachment cleanup mapping style.
  • Config validation (src/environment.ts):
    • Use ZodError.issues over errors when building error messages.
    • Minor signature/formatting adjustments.

Written by Cursor Bugbot for commit 0c887c5. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Refactor

    • Streamlined message handling to call the message service directly for faster, more reliable incoming message processing.
    • Preserved document processing behavior and configuration validation while improving internal robustness and guards.
  • Style

    • Applied consistent formatting and string-style updates; no user-visible behavior changes.
  • Chores

    • Removed an unused internal type from the public import surface.
    • Improved error logging for clearer diagnostic messages.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 9, 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

Reformats environment validation signature and switches ZodError handling to use error.issues. Refactors message handling to call runtime.messageService.handleMessage(...) directly instead of emitting events; removes an exported type import and applies stylistic/logging tweaks. Core control flow and return values unchanged.

Changes

Cohort / File(s) Summary
Environment validation typing/formatting
src/environment.ts
Reformatted exported validateTelegramConfig signature across multiple lines; catch uses error.issues for ZodError mapping; no control-flow or return-value changes.
Message handling refactor and formatting
src/messageManager.ts
Removed TelegramMessageReceivedPayload from imports; replaced event-emission path with direct runtime.messageService.handleMessage(...) call (with guard if service missing); numerous stylistic/logging and minor parameter/layout tweaks; document/image processing logic preserved.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant TelegramBot as Telegram Bot
  participant MessageManager
  participant MessageService

  rect rgba(200,200,255,0.18)
  note over MessageManager: Old flow (event-driven)
  User->>TelegramBot: Send message
  TelegramBot->>MessageManager: onMessage(...)
  MessageManager->>MessageManager: Build memory/document info
  MessageManager-->>MessageService: Emit MESSAGE_RECEIVED event
  MessageService-->>MessageManager: Handled via listeners
  end
Loading
sequenceDiagram
  autonumber
  participant User
  participant TelegramBot as Telegram Bot
  participant MessageManager
  participant MessageService

  rect rgba(200,255,200,0.18)
  note over MessageManager: New flow (direct call)
  User->>TelegramBot: Send message
  TelegramBot->>MessageManager: onMessage(...)
  MessageManager->>MessageManager: Build memory/document info
  MessageManager->>MessageService: handleMessage(runtime, memory, callback)
  MessageService-->>MessageManager: Returns/ invokes callback
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I twitch my nose at tidy lines, so neat,
Errors sorted, logs in single-quote beat.
Events hopped off — direct calls take the lead,
I nibble docs, then give the service speed.
A little hop for refactor’s delight! 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly summarizes the main change by indicating the migration to runtime.handleMessage(), matches the PR objectives to replace event-based handling, and is concise, clear, and specific enough for team members to understand the key update at a glance.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/telegram-use-message-service

📜 Recent 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 4929cce and 0c887c5.

📒 Files selected for processing (2)
  • src/environment.ts (2 hunks)
  • src/messageManager.ts (12 hunks)
🔇 Additional comments (6)
src/environment.ts (2)

20-22: LGTM - Improved readability.

The multi-line function signature formatting improves readability without changing functionality.


32-32: Correct fix: error.issues is the proper ZodError property.

This change correctly uses error.issues instead of the non-existent error.errors property. ZodError's validation issues are exposed via the issues array, so this fix aligns with Zod's API.

src/messageManager.ts (4)

104-108: LGTM - Improved formatting.

The conditional reformatting improves readability without altering the logic.


134-169: Good defensive programming and consistent error handling.

The changes improve robustness:

  • Return type now explicitly documents DocumentProcessingResult | null
  • Additional null check on line 136 provides defense in depth
  • Consistent error logging pattern using error instanceof Error ? error.message : String(error)
  • Empty string default for fullText ensures consistent type

707-715: Verify: Throwing on missing messageService is harsh - is this intentional?

The null check is now present (addressing the previous review concern), but the current implementation throws an error rather than gracefully degrading. This will crash the Telegram bot if messageService is unavailable, whereas the previous event-based approach would silently no-op.

Given that the PR description states this "Requires: feat/core-message-service-interface", this aggressive behavior may be intentional to enforce the dependency. However, consider whether a more graceful approach would improve the developer experience during upgrades or partial deployments.

Current behavior: Hard crash if messageService is missing
Previous suggestion: Log error and return gracefully

If the hard dependency is intentional, consider documenting this breaking change prominently in:

  1. Migration guide or changelog
  2. README prerequisites
  3. Error message (which is already quite clear)

Otherwise, consider this alternative that warns but doesn't crash:

 if (!this.runtime.messageService) {
-  logger.error('Message service is not available');
-  throw new Error(
-    'Message service is not initialized. Ensure the message service is properly configured.'
-  );
+  logger.warn(
+    'Message service is not available; skipping message handling. Ensure feat/core-message-service-interface is merged.'
+  );
+  return;
 }

594-599: LGTM - Proper immutable transformation.

Using map to create cleaned attachments maintains immutability and correctly sanitizes text fields.


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

Comment @coderabbitai help to get the list of available commands and usage tips.

cursor[bot]

This comment was marked as outdated.

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

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

32-33: Avoid reverting to any when handling Zod errors

You already narrowed the catch to z.ZodError, so you can keep type safety without falling back to any.

Apply this diff to preserve typing:

-      const errorMessages = (error as any).errors
-        .map((err: any) => `${err.path.join('.')}: ${err.message}`)
+      const zodError = error as z.ZodError;
+      const errorMessages = zodError.errors
+        .map((issue) => `${issue.path.join('.')}: ${issue.message}`)
📜 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 07d8cd6 and 4929cce.

📒 Files selected for processing (2)
  • src/environment.ts (2 hunks)
  • src/messageManager.ts (12 hunks)

Comment on lines +707 to +709
// Call the message handler directly instead of emitting events
// This provides a clearer, more traceable flow for message processing
await this.runtime.messageService!.handleMessage(this.runtime, memory, callback);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard against missing MessageService before using it

The new direct call assumes runtime.messageService is always defined. If the runtime hasn’t registered the service yet (or a downstream integrator upgrades the plugin before the core), this becomes a hard crash instead of the previous no-op event emission.

Add a defensive check so we fail gracefully:

-      await this.runtime.messageService!.handleMessage(this.runtime, memory, callback);
+      const messageService = this.runtime.messageService;
+      if (!messageService) {
+        logger.error('Message service not available; skipping Telegram message handling');
+        return;
+      }
+      await messageService.handleMessage(this.runtime, memory, callback);
📝 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
// Call the message handler directly instead of emitting events
// This provides a clearer, more traceable flow for message processing
await this.runtime.messageService!.handleMessage(this.runtime, memory, callback);
// Call the message handler directly instead of emitting events
// This provides a clearer, more traceable flow for message processing
const messageService = this.runtime.messageService;
if (!messageService) {
logger.error('Message service not available; skipping Telegram message handling');
return;
}
await messageService.handleMessage(this.runtime, memory, callback);
🤖 Prompt for AI Agents
In src/messageManager.ts around lines 707 to 709, the direct call to
this.runtime.messageService!.handleMessage(...) assumes messageService is always
present and will crash if it is undefined; add a defensive check that verifies
this.runtime.messageService exists before calling handleMessage, and if it's
missing, gracefully handle the case (e.g., log a warning and return or fall back
to the previous emit-based no-op behavior) so the code does not throw when the
service is not registered yet.

@wtfsayo wtfsayo merged commit bbc5903 into 1.x Oct 20, 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.

2 participants