Add messaging platform enhancements: STT, stickers, Discord UX, Slack, pairing, hooks
Major feature additions inspired by OpenClaw/ClawdBot integration analysis:
Voice Message Transcription (STT):
- Auto-transcribe voice/audio messages via OpenAI Whisper API
- Download voice to ~/.hermes/audio_cache/ on Telegram/Discord/WhatsApp
- Inject transcript as text so all models can understand voice input
- Configurable model (whisper-1, gpt-4o-mini-transcribe, gpt-4o-transcribe)
Telegram Sticker Understanding:
- Describe static stickers via vision tool with JSON-backed cache
- Cache keyed by file_unique_id avoids redundant API calls
- Animated/video stickers get emoji-based fallback description
Discord Rich UX:
- Native slash commands (/ask, /reset, /status, /stop) via app_commands
- Button-based exec approvals (Allow Once / Always Allow / Deny)
- ExecApprovalView with user authorization and timeout handling
Slack Integration:
- Full SlackAdapter using slack-bolt with Socket Mode
- DMs, channel messages (mention-gated), /hermes slash command
- File attachment handling with bot-token-authenticated downloads
DM Pairing System:
- Code-based user authorization as alternative to static allowlists
- 8-char codes from unambiguous alphabet, 1-hour expiry
- Rate limiting, lockout after failed attempts, chmod 0600 on data
- CLI: hermes pairing list/approve/revoke/clear-pending
Event Hook System:
- File-based hook discovery from ~/.hermes/hooks/
- HOOK.yaml + handler.py per hook, sync/async handler support
- Events: gateway:startup, session:start/reset, agent:start/step/end
- Wildcard matching (command:* catches all command events)
Cross-Channel Messaging:
- send_message agent tool for delivering to any connected platform
- Enables cron job delivery and cross-platform notifications
Human-Like Response Pacing:
- Configurable delays between message chunks (off/natural/custom)
- HERMES_HUMAN_DELAY_MODE env var with min/max ms settings
Warm Injection Message Style:
- Retrofitted image vision messages with friendly kawaii-consistent tone
- All new injection messages (STT, stickers, errors) use warm style
Also: updated config migration to prompt for optional keys interactively,
bumped config version, updated README, AGENTS.md, .env.example,
cli-config.yaml.example, install scripts, pyproject.toml, and toolsets.
2026-02-15 21:38:59 -08:00
|
|
|
"""
|
|
|
|
|
CLI commands for the DM pairing system.
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
hermes pairing list # Show all pending + approved users
|
|
|
|
|
hermes pairing approve <platform> <code> # Approve a pairing code
|
|
|
|
|
hermes pairing revoke <platform> <user_id> # Revoke user access
|
|
|
|
|
hermes pairing clear-pending # Clear all expired/pending codes
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def pairing_command(args):
|
|
|
|
|
"""Handle hermes pairing subcommands."""
|
|
|
|
|
from gateway.pairing import PairingStore
|
|
|
|
|
|
|
|
|
|
store = PairingStore()
|
|
|
|
|
action = getattr(args, "pairing_action", None)
|
|
|
|
|
|
|
|
|
|
if action == "list":
|
|
|
|
|
_cmd_list(store)
|
|
|
|
|
elif action == "approve":
|
|
|
|
|
_cmd_approve(store, args.platform, args.code)
|
|
|
|
|
elif action == "revoke":
|
|
|
|
|
_cmd_revoke(store, args.platform, args.user_id)
|
|
|
|
|
elif action == "clear-pending":
|
|
|
|
|
_cmd_clear_pending(store)
|
|
|
|
|
else:
|
|
|
|
|
print("Usage: hermes pairing {list|approve|revoke|clear-pending}")
|
|
|
|
|
print("Run 'hermes pairing --help' for details.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _cmd_list(store):
|
|
|
|
|
"""List all pending and approved users."""
|
|
|
|
|
pending = store.list_pending()
|
|
|
|
|
approved = store.list_approved()
|
|
|
|
|
|
|
|
|
|
if not pending and not approved:
|
|
|
|
|
print("No pairing data found. No one has tried to pair yet~")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if pending:
|
|
|
|
|
print(f"\n Pending Pairing Requests ({len(pending)}):")
|
|
|
|
|
print(f" {'Platform':<12} {'Code':<10} {'User ID':<20} {'Name':<20} {'Age'}")
|
|
|
|
|
print(f" {'--------':<12} {'----':<10} {'-------':<20} {'----':<20} {'---'}")
|
|
|
|
|
for p in pending:
|
|
|
|
|
print(
|
|
|
|
|
f" {p['platform']:<12} {p['code']:<10} {p['user_id']:<20} "
|
|
|
|
|
f"{p.get('user_name', ''):<20} {p['age_minutes']}m ago"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
print("\n No pending pairing requests.")
|
|
|
|
|
|
|
|
|
|
if approved:
|
|
|
|
|
print(f"\n Approved Users ({len(approved)}):")
|
|
|
|
|
print(f" {'Platform':<12} {'User ID':<20} {'Name':<20}")
|
|
|
|
|
print(f" {'--------':<12} {'-------':<20} {'----':<20}")
|
|
|
|
|
for a in approved:
|
|
|
|
|
print(f" {a['platform']:<12} {a['user_id']:<20} {a.get('user_name', ''):<20}")
|
|
|
|
|
else:
|
|
|
|
|
print("\n No approved users.")
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _cmd_approve(store, platform: str, code: str):
|
|
|
|
|
"""Approve a pairing code."""
|
|
|
|
|
platform = platform.lower().strip()
|
|
|
|
|
code = code.upper().strip()
|
|
|
|
|
|
|
|
|
|
result = store.approve_code(platform, code)
|
|
|
|
|
if result:
|
|
|
|
|
uid = result["user_id"]
|
|
|
|
|
name = result.get("user_name", "")
|
|
|
|
|
display = f"{name} ({uid})" if name else uid
|
|
|
|
|
print(f"\n Approved! User {display} on {platform} can now use the bot~")
|
chore: fix 154 f-strings, simplify getattr/URL patterns, remove dead code (#3119)
Three categories of cleanup, all zero-behavioral-change:
1. F-strings without placeholders (154 fixes across 29 files)
- Converted f'...' to '...' where no {expression} was present
- Heaviest files: run_agent.py (24), cli.py (20), honcho_integration/cli.py (34)
2. Simplify defensive patterns in run_agent.py
- Added explicit self._is_anthropic_oauth = False in __init__ (before
the api_mode branch that conditionally sets it)
- Replaced 7x getattr(self, '_is_anthropic_oauth', False) with direct
self._is_anthropic_oauth (attribute always initialized now)
- Added _is_openrouter_url() and _is_anthropic_url() helper methods
- Replaced 3 inline 'openrouter' in self._base_url_lower checks
3. Remove dead code in small files
- hermes_cli/claw.py: removed unused 'total' computation
- tools/fuzzy_match.py: removed unused strip_indent() function and
pattern_stripped variable
Full test suite: 6184 passed, 0 failures
E2E PTY: banner clean, tool calls work, zero garbled ANSI
2026-03-25 19:47:58 -07:00
|
|
|
print(" They'll be recognized automatically on their next message.\n")
|
Add messaging platform enhancements: STT, stickers, Discord UX, Slack, pairing, hooks
Major feature additions inspired by OpenClaw/ClawdBot integration analysis:
Voice Message Transcription (STT):
- Auto-transcribe voice/audio messages via OpenAI Whisper API
- Download voice to ~/.hermes/audio_cache/ on Telegram/Discord/WhatsApp
- Inject transcript as text so all models can understand voice input
- Configurable model (whisper-1, gpt-4o-mini-transcribe, gpt-4o-transcribe)
Telegram Sticker Understanding:
- Describe static stickers via vision tool with JSON-backed cache
- Cache keyed by file_unique_id avoids redundant API calls
- Animated/video stickers get emoji-based fallback description
Discord Rich UX:
- Native slash commands (/ask, /reset, /status, /stop) via app_commands
- Button-based exec approvals (Allow Once / Always Allow / Deny)
- ExecApprovalView with user authorization and timeout handling
Slack Integration:
- Full SlackAdapter using slack-bolt with Socket Mode
- DMs, channel messages (mention-gated), /hermes slash command
- File attachment handling with bot-token-authenticated downloads
DM Pairing System:
- Code-based user authorization as alternative to static allowlists
- 8-char codes from unambiguous alphabet, 1-hour expiry
- Rate limiting, lockout after failed attempts, chmod 0600 on data
- CLI: hermes pairing list/approve/revoke/clear-pending
Event Hook System:
- File-based hook discovery from ~/.hermes/hooks/
- HOOK.yaml + handler.py per hook, sync/async handler support
- Events: gateway:startup, session:start/reset, agent:start/step/end
- Wildcard matching (command:* catches all command events)
Cross-Channel Messaging:
- send_message agent tool for delivering to any connected platform
- Enables cron job delivery and cross-platform notifications
Human-Like Response Pacing:
- Configurable delays between message chunks (off/natural/custom)
- HERMES_HUMAN_DELAY_MODE env var with min/max ms settings
Warm Injection Message Style:
- Retrofitted image vision messages with friendly kawaii-consistent tone
- All new injection messages (STT, stickers, errors) use warm style
Also: updated config migration to prompt for optional keys interactively,
bumped config version, updated README, AGENTS.md, .env.example,
cli-config.yaml.example, install scripts, pyproject.toml, and toolsets.
2026-02-15 21:38:59 -08:00
|
|
|
else:
|
|
|
|
|
print(f"\n Code '{code}' not found or expired for platform '{platform}'.")
|
chore: fix 154 f-strings, simplify getattr/URL patterns, remove dead code (#3119)
Three categories of cleanup, all zero-behavioral-change:
1. F-strings without placeholders (154 fixes across 29 files)
- Converted f'...' to '...' where no {expression} was present
- Heaviest files: run_agent.py (24), cli.py (20), honcho_integration/cli.py (34)
2. Simplify defensive patterns in run_agent.py
- Added explicit self._is_anthropic_oauth = False in __init__ (before
the api_mode branch that conditionally sets it)
- Replaced 7x getattr(self, '_is_anthropic_oauth', False) with direct
self._is_anthropic_oauth (attribute always initialized now)
- Added _is_openrouter_url() and _is_anthropic_url() helper methods
- Replaced 3 inline 'openrouter' in self._base_url_lower checks
3. Remove dead code in small files
- hermes_cli/claw.py: removed unused 'total' computation
- tools/fuzzy_match.py: removed unused strip_indent() function and
pattern_stripped variable
Full test suite: 6184 passed, 0 failures
E2E PTY: banner clean, tool calls work, zero garbled ANSI
2026-03-25 19:47:58 -07:00
|
|
|
print(" Run 'hermes pairing list' to see pending codes.\n")
|
Add messaging platform enhancements: STT, stickers, Discord UX, Slack, pairing, hooks
Major feature additions inspired by OpenClaw/ClawdBot integration analysis:
Voice Message Transcription (STT):
- Auto-transcribe voice/audio messages via OpenAI Whisper API
- Download voice to ~/.hermes/audio_cache/ on Telegram/Discord/WhatsApp
- Inject transcript as text so all models can understand voice input
- Configurable model (whisper-1, gpt-4o-mini-transcribe, gpt-4o-transcribe)
Telegram Sticker Understanding:
- Describe static stickers via vision tool with JSON-backed cache
- Cache keyed by file_unique_id avoids redundant API calls
- Animated/video stickers get emoji-based fallback description
Discord Rich UX:
- Native slash commands (/ask, /reset, /status, /stop) via app_commands
- Button-based exec approvals (Allow Once / Always Allow / Deny)
- ExecApprovalView with user authorization and timeout handling
Slack Integration:
- Full SlackAdapter using slack-bolt with Socket Mode
- DMs, channel messages (mention-gated), /hermes slash command
- File attachment handling with bot-token-authenticated downloads
DM Pairing System:
- Code-based user authorization as alternative to static allowlists
- 8-char codes from unambiguous alphabet, 1-hour expiry
- Rate limiting, lockout after failed attempts, chmod 0600 on data
- CLI: hermes pairing list/approve/revoke/clear-pending
Event Hook System:
- File-based hook discovery from ~/.hermes/hooks/
- HOOK.yaml + handler.py per hook, sync/async handler support
- Events: gateway:startup, session:start/reset, agent:start/step/end
- Wildcard matching (command:* catches all command events)
Cross-Channel Messaging:
- send_message agent tool for delivering to any connected platform
- Enables cron job delivery and cross-platform notifications
Human-Like Response Pacing:
- Configurable delays between message chunks (off/natural/custom)
- HERMES_HUMAN_DELAY_MODE env var with min/max ms settings
Warm Injection Message Style:
- Retrofitted image vision messages with friendly kawaii-consistent tone
- All new injection messages (STT, stickers, errors) use warm style
Also: updated config migration to prompt for optional keys interactively,
bumped config version, updated README, AGENTS.md, .env.example,
cli-config.yaml.example, install scripts, pyproject.toml, and toolsets.
2026-02-15 21:38:59 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def _cmd_revoke(store, platform: str, user_id: str):
|
|
|
|
|
"""Revoke a user's access."""
|
|
|
|
|
platform = platform.lower().strip()
|
|
|
|
|
|
|
|
|
|
if store.revoke(platform, user_id):
|
|
|
|
|
print(f"\n Revoked access for user {user_id} on {platform}.\n")
|
|
|
|
|
else:
|
|
|
|
|
print(f"\n User {user_id} not found in approved list for {platform}.\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _cmd_clear_pending(store):
|
|
|
|
|
"""Clear all pending pairing codes."""
|
|
|
|
|
count = store.clear_pending()
|
|
|
|
|
if count:
|
|
|
|
|
print(f"\n Cleared {count} pending pairing request(s).\n")
|
|
|
|
|
else:
|
|
|
|
|
print("\n No pending requests to clear.\n")
|