Skip to content

feat: TORIS v2 — Docker, B1-B5+B11, watch_mode, typing, security#4

Closed
ToruGuy wants to merge 19 commits intomainfrom
feat/telegram-token-setup
Closed

feat: TORIS v2 — Docker, B1-B5+B11, watch_mode, typing, security#4
ToruGuy wants to merge 19 commits intomainfrom
feat/telegram-token-setup

Conversation

@ToruGuy
Copy link
Copy Markdown
Contributor

@ToruGuy ToruGuy commented Jan 26, 2026

Summary

  • Docker deployment — Dockerfile, docker-compose, toris.env.example
  • Security & quality — admin auth, async I/O (asyncio.to_thread), JSONDecodeError handling, 61 real tests
  • New commands/cancel, /compact, /health (MCP status), photo/vision handler
  • B11 — MEGG MCP wired into Claude sessions
  • watch_mode — OFF / LIVE / DEBUG replaces old watch_enabled
  • Typing indicator — continuous indicator during processing, fires immediately
  • STT language fix — respects STT_LANGUAGE env var (was hardcoded en)
  • Telegram menuset_my_commands() registers / menu at startup

Test Plan

  • pytest tests/test_bot_logic.py — 61 tests pass
  • Bot starts and responds to /start, /health
  • Voice message transcribed and answered
  • Photo sent with caption — vision response returned
  • /cancel stops in-progress request
  • /compact compresses session

ToruGuy and others added 19 commits January 25, 2026 13:36
* feat: Add production Docker deployment with multi-persona support

Built complete Docker deployment infrastructure:

- Dockerfile: Node 20 + Python 3.12, non-root user (uid 1000), Claude CLI installed
- docker-compose.yml: Two-service setup (v, tc) with named volumes and health checks
- docker/v.env.example: V persona configuration template
- docker/tc.env.example: TC persona configuration template
- .dockerignore: Excludes secrets, state files, and dev artifacts
- README.md: Added deployment guides for both Docker and systemd options

Technical details:
- Multi-stage Dockerfile for efficient caching
- Isolated sandboxes and state per persona via named volumes
- Health checks using process monitoring
- All paths configurable via environment variables
- Ready for production with restart policies and security hardening

Both Docker and non-Docker deployment paths documented for flexibility.

* Genericize prompts and configs for public release

- Replace "Tako" with "the user" in prompts/v.md and prompts/tc.md
- Make TORIS context in tc.md a customizable example/template
- Remove specific ToruAI file paths from tc.md
- Change bot.py defaults from /home/dev to os.path.expanduser("~")
- Update .env.example paths from /home/dev to /home/youruser
- Update README.md paths to use /home/youruser placeholders
- Change tc.env.example topic ID example from 1278 to 12345

Preserves all functionality while removing personal/business-specific content.

* Fix: Use CLAUDE_WORKING_DIR in health check instead of hardcoded path

* Simplify Docker to single generic example

- Replace v.env.example and tc.env.example with assistant.env.example
- Simplify docker-compose.yml to single service
- Add generic prompts/assistant.md
- Update README for simplified structure

Users can duplicate the service block for multiple personas.

* Rename to TORIS as default persona

* Rename to toris-claude-voice-assistant

* Add toru-claude-settings as submodule for agents and skills

* Consolidate prompts to single TORIS persona

- Enhanced toris.md with personality from v.md
- Branded as "Voice Development Assistant by ToruAI"
- Removed v.md and tc.md (multi-persona examples)
- Added voice style guidance and conversational tone

* Rewrite TORIS as second brain thinking partner

- "Your Second Brain" - offload mind, return to act later
- Thinking partner who engages, not just validates
- Note-taker who remembers ideas across conversations
- Reality-checker who researches market before you build
- Honest peer - rational but appreciates creativity
- Voice phrases: "Here's the thing...", "I'll remember that"

* Add MEGG memory system to TORIS prompt

- MEGG is the actual memory layer for second brain
- Check context before starting tasks
- Save learnings with megg learn
- Track session state across conversations
- "I'll remember that" -> actually save to MEGG

* Add flexible Claude authentication for Docker

- Support both API key and subscription auth methods
- ANTHROPIC_API_KEY now optional (commented in env example)
- Add credentials volume for subscription users
- Bot checks auth status on startup with helpful error messages
- Update README with authentication guide
- Change MAX_VOICE_RESPONSE_CHARS default to 2000

* Update toru-claude-settings submodule to v1.0.0

* Add toru-claude-agents install instructions for non-Docker users

---------

Co-authored-by: ToruGuy <browner342@gmail>
- Add /setup command to show API credentials status
- Add /claude_token command to set Claude API token (auto-deletes for security)
- Add /elevenlabs_key command to set ElevenLabs key (auto-deletes for security)
- Store credentials in credentials.json with 0o600 permissions
- Apply saved credentials on startup before environment validation
- Bot starts even without Claude auth (can be configured via Telegram)
- Fix Docker UID 1000 conflict by removing node user first
- Add credentials.json to gitignore
- Remove test_bot.py (superseded by modular tests)
Security:
- Add TELEGRAM_ADMIN_USER_IDS — only listed users can run /setup, /claude_token, /elevenlabs_key, /openai_key
- _is_authorized() + _is_admin() helpers replace 14 repeated auth blocks

Bugs:
- CLAUDE_SETTINGS_FILE now actually passed to ClaudeAgentOptions (was ignored)
- STT language defaulted to "en" hardcoded — now None (auto-detect)
- load_state/load_settings silently crash on corrupted JSON — now warns and recovers
- _transcribe_elevenlabs/_transcribe_openai had no try/except
- MAX_VOICE_RESPONSE_CHARS was declared but never applied — now truncates before TTS

Performance:
- 4 sync SDK calls blocking event loop wrapped in asyncio.to_thread()

Code quality:
- resolve_tts_provider + resolve_stt_provider deduplicated → resolve_provider(env)
- handle_voice/handle_text common logic extracted to _process_and_respond()
- debug() using print() replaced with logger.debug/error()
- Unused ToolResultBlock import removed

UX:
- Bot commands registered via set_my_commands (Telegram "/" menu now works)

Tests:
- 32 real tests in tests/test_bot_logic.py (no mocks, no API calls)
  TestResolveProvider, TestLoadSaveState, TestLoadSaveSettings,
  TestRateLimiter, TestCheckClaudeAuth, TestMaxVoiceChars, TestAdminUserIds
- Add settings.json (gitignored) with MEGG MCP server config and sandbox permissions
- CLAUDE_SETTINGS_FILE env var now documented in .env.example and docker/toris.env.example
- Allow MEGG tools in go_all mode (mcp__megg__state/context/learn/maintain/init)
- settings.example.json updated with mcpServers.megg template
- 4 new tests in TestSettingsJson verifying settings schema
- handle_photo() downloads Telegram photo to sandbox, builds prompt with
  file path + optional caption, routes through call_claude (Claude views
  the image via Read tool)
- Registered MessageHandler(filters.PHOTO) in main()
- Session tracking, rate limiting, auth, TTS response — same as voice/text
- 3 new tests in TestPhotoHandler
- cancel_events dict (per user_id) tracks asyncio.Event for each active call
- call_claude clears event at call start, checks it each iteration of the
  response stream loop — breaks on cancellation with [Cancelled] suffix
- cmd_cancel sets the event if an active call exists, else informs user
- /cancel registered in main() and added to Telegram command menu
- 5 new tests in TestCancellation covering event lifecycle
- cmd_compact calls Claude in current session with summarize prompt,
  saves result to state["compact_summary"], clears current_session
- handle_voice/text/photo inject compact_summary as <previous_session_summary>
  block into the next message, then clear it (single-use)
- /compact registered in main() and Telegram command menu
- 5 new tests in TestCompact covering state lifecycle and injection logic
- get_mcp_status() pure helper reads mcpServers from CLAUDE_SETTINGS_FILE
  and checks each server's command binary via shutil.which()
- /health now shows MCP Servers section with OK/MISSING/misconfigured status
- import shutil added to top-level imports
- 12 new tests in TestMcpStatus (6 inline logic + 6 via real get_mcp_status())
- call_claude() accepts optional processing_msg parameter
- Each tool use updates "Asking Claude..." in-place with ⚙ tool log
- MCP tools shown without mcp__ prefix for readability
- Last 5 tools shown; edit failures silently ignored (rate limits)
- Watch mode separate messages preserved alongside
Relative path was resolved against SANDBOX_DIR (cwd for SDK), not the
project root — so settings.json was never found and MCP tools were not
exposed to Claude.
--settings flag doesn't load MCP servers in Claude Code CLI.
MCP must go through --mcp-config (options.mcp_servers in SDK).

- Add load_mcp_servers() reading mcpServers from CLAUDE_SETTINGS_FILE
- Pass mcp_servers to both approve and go_all ClaudeAgentOptions
- Dynamically build allowed_tools megg entries from actual mcp_servers keys
MEGG in Claude Code is a CLI (megg learn/context/state), not an MCP server.
The MCP server approach (--mcp-config) fails with status: failed.

- Update prompts/toris.md: replace mcp__megg__* with bash commands
- Remove mcpServers from settings.json (only permissions remain)
- Remove mcp_servers/megg_tools from call_claude (no MCP needed)
- Fix settings_file -> settings (correct ClaudeAgentOptions field name)
- Update test: check permissions block instead of mcpServers
- OFF: no tool activity shown
- LIVE: processing_msg edited live with all tools, disappears after response
- DEBUG: separate persistent message, full tool log, stays after response;
  Bash commands shown full (no truncation)
- Settings menu: Watch button cycles off→live→debug→off
- Migration: watch_enabled=True → live, show_activity=True → debug
@ToruGuy ToruGuy changed the title Add Telegram-based token configuration commands feat: TORIS v2 — Docker, B1-B5+B11, watch_mode, typing, security Apr 6, 2026
@ToruGuy ToruGuy closed this Apr 6, 2026
@ToruGuy ToruGuy deleted the feat/telegram-token-setup branch April 6, 2026 11:08
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