fix(gateway): auto-enable skip_entity_detection for email-bearing rich messages - #68852
fix(gateway): auto-enable skip_entity_detection for email-bearing rich messages#68852webtecnica wants to merge 2 commits into
Conversation
Previously _count_skills() only counted SKILL.md files inside the profile's own skills/ directory, making the WebUI profile card show a misleading low count (e.g. 0 for 'default', 30 for 'webtecnica') even though the profile loaded 150+ skills from global + external dirs. Now it scans three sources: 1. Profile-specific skills/ dir (as before) 2. Global ~/.hermes/skills/ dir (via get_default_hermes_root) 3. External dirs from skills.external_dirs config Deduplication by skill name (from YAML frontmatter) prevents double- counting when the same skill exists in both global and profile dirs, matching how scan_skill_commands() loads skills at runtime. The cache is updated to key on all scanned directories and track their combined mtime signatures.
…h messages (NousResearch#68754) Telegram rich messages are rejected with RICH_MESSAGE_EMAIL_INVALID when automatic entity detection creates an invalid email entity from provider-prefixed email addresses (e.g. "openai:test.user@example.com"). Hermes already supports the skip_entity_detection field in the centralized _rich_message_payload builder, but no send/edit/draft caller enables it for email-bearing content. Fix: - Add _content_has_email_pattern() static helper that detects '@' in content, indicating Telegram may auto-detect an email entity. - Modify _rich_message_payload() to auto-enable skip_entity_detection when email patterns are detected, preventing the invalid entity from being created. - All three rich-path callers (_try_send_rich, _edit_rich, _send_rich_draft_frame) benefit automatically since they all go through _rich_message_payload. Testing: - Existing tests for skip_entity_detection flag still pass. - New test class TestRichMessageEmailEntityProtection covers: * Provider-prefixed email (the original reproducer) * Normal email address * Multiple email addresses * Content without @ (no skip_entity_detection) * Explicit skip_entity_detection=True on non-email content * Email-like patterns in code blocks * The static _content_has_email_pattern helper directly
83d1eff to
3e204b7
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing the shared rich-message builder; current main still has the reported gap: _rich_message_payload() only sets the flag when callers pass it (plugins/platforms/telegram/adapter.py:1683-1684), and send/edit/draft all use that builder (plugins/platforms/telegram/adapter.py:1791, 1900, 1994).
Problems
plugins/platforms/telegram/adapter.py:1650classifies every@as an email pattern. The added tests deliberately coverpackage==1.0@betaand a lone@(tests/gateway/test_telegram_rich_newlines.py:157-169), so this disables entity detection for content outside the reported email case. Use an email-token predicate and add those inputs as negative controls.- The unrelated profile-count change is not safe as written:
_collect_skills_dirs(profile_dir)callsget_external_skills_dirs()(hermes_cli/profiles.py:771-794), which reads the activeHERMES_HOMEconfig (agent/skill_utils.py:446-464), althoughlist_profiles()invokes_count_skills()for every profile (hermes_cli/profiles.py:897,937). Please split it out and scope its config lookup to the target profile.
Automated hermes-sweeper review.
| Callers should combine this with ``skip_entity_detection`` when building | ||
| rich-message payloads for email-bearing content. | ||
| """ | ||
| return "@" in content |
There was a problem hiding this comment.
This disables entity detection for every @, including non-email content such as the package-version form covered by the added tests. Please use a narrow email-token predicate and make lone @/package syntax negative controls.
| if global_skills.is_dir() and global_skills not in dirs: | ||
| dirs.append(global_skills) | ||
|
|
||
| for ext_dir in get_external_skills_dirs(): |
There was a problem hiding this comment.
get_external_skills_dirs() reads the active HERMES_HOME config, not profile_dir; list_profiles() calls this for every profile. Read the target profile's config explicitly, otherwise inactive profiles inherit the active profile's external-dir count.
Description
Telegram rich messages can reject runtime text containing provider-prefixed email labels such as:
Rich entity detection auto-links the provider-prefixed token into an invalid email entity, causing Telegram to return
RICH_MESSAGE_EMAIL_INVALID.Fix
_content_has_email_pattern()— new static helper that detects@in content (signaling Telegram may auto-detect an email entity)_rich_message_payload()— modified to auto-enableskip_entity_detectionwhen email patterns are present, preventing the invalid entity from being created_try_send_rich,_edit_rich,_send_rich_draft_frame) benefit automatically since they all route through_rich_message_payloadTesting
New test class
TestRichMessageEmailEntityProtectioncovers:@(no skip_entity_detection set)skip_entity_detection=Trueon non-email content_content_has_email_patternhelper directlyAll 17 tests in
test_telegram_rich_newlines.pypass (8 existing + 9 new).Fixes #68754