Commit Graph

37 Commits

Author SHA1 Message Date
Azimkin
40e7930e60 feat: show AI progress and configure prompt directory 2026-09-14 14:25:50 +02:00
Azimkin
b68e715267 feat: add QR login and browser-backed web tools 2026-09-14 14:19:20 +02:00
Azimkin
3a8c198caa refactor: remove GitHub webhook support 2026-09-14 13:39:41 +02:00
Azimkin
3f0cce6732 build: migrate dependency management to uv 2026-09-14 13:27:35 +02:00
Azimkin
4421c9cd31 feat: rebuild AI commands and migrate config to TOML 2026-09-14 13:03:14 +02:00
Azimkin
01d3173254 Add temporary AI commands and request transcripts 2026-08-28 23:53:42 +02:00
Azimkin
d3c02ca203 Add process controls and restart command 2026-08-28 23:25:20 +02:00
12434ec557 Add id command 2026-07-01 21:47:01 +02:00
62ea12033f Add GitHub webhook receiver 2026-07-01 21:41:01 +02:00
36170f83d1 Normalize Brave search locale parameters 2026-05-19 21:52:28 +02:00
cc783ab8ed Log Brave search responses 2026-05-19 21:49:31 +02:00
5ed1104c12 Fix Brave search auth and prompt variables 2026-05-19 21:33:46 +02:00
68934b23a0 Add page extraction tool 2026-05-18 22:54:19 +02:00
7147c657ab Add Brave web search support 2026-05-18 22:38:54 +02:00
1ef2893345 Remove MiniMax MCP support 2026-05-18 18:32:51 +02:00
aab630661f Fix MiniMax MCP startup handling 2026-05-18 15:46:44 +02:00
7356a1812e Collapse blockquote and strip <think> blocks from AI responses
- blockquote expandable: replies are collapsed by default in Telegram
- strip <think>...</think> sections (chain-of-thought from reasoning
  models like DeepSeek R1 / QwQ) before sending the response

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:40:33 +02:00
777aa90f17 Fix parse mode: use enums.ParseMode.HTML instead of string
ParseMode is a plain Enum, not a str subclass — string "html" fails
equality check against the enum member and raises ValueError.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:36:46 +02:00
0cafff8696 Convert AI responses to Telegram HTML with blockquote wrapping
Markdown (headings, bold, italic, strikethrough, code blocks, links)
is converted to Telegram-compatible HTML tags before sending. Each
reply chunk is wrapped in <blockquote> for visual distinction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:29:34 +02:00
42472dc91c Fix file tool sandbox: prompts/ was unreachable and workspace paths were doubly nested
The workspace root matched every relative path, so prompts/ was never reached,
and paths like workspace/notes.txt landed at workspace/workspace/notes.txt.

Fix: _resolve_sandboxed_path now treats allowed_roots[0] as the resolution base
(project root) and allowed_roots[1:] as permitted subdirectories. _get_allowed_roots
returns (project_root, workspace_dir, prompts_root). Paths are now correctly routed:
workspace/notes.txt -> workspace/notes.txt, prompts/ai/parts/x.md -> prompts/ai/parts/x.md.
app/ and other project dirs remain blocked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:24:35 +02:00
f04ab527b8 Add user_template to wrap user messages with sender context (name, id, username)
Configure via ai.prompt.user_template in config.json using {text}, {full_name},
{user_id}, {first_name}, {last_name}, {username} placeholders. Applied to both
history user messages and the current prompt. No-op when unset.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:19:13 +02:00
c85af7c54d Add python_exec tool: run Python code in subprocess with ctx injection and timeout
Executes code in a fresh python3 subprocess (max 30s, default 10s).
Pre-injects a 'ctx' dict with: chat_id, message_id, message_text, args,
from_user, replied_message. stdout+stderr returned; output capped at 3000 chars.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 14:16:12 +02:00
95cac39fcf Add send_file tool to send workspace files to Telegram chat
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:59:40 +02:00
310ee4a266 Document python3 -m uv alternative for image_understand command in CLAUDE.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:53:38 +02:00
6ffb769b95 Eagerly initialize MCP tools at startup so loading is logged to console
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 13:22:31 +02:00
3932e44495 Log MCP tool loading outcome (fetching, loaded names, or failure with traceback)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:16:22 +02:00
fa090412d2 Auto-update config.json with new scalar fields from config.example.json on startup
On each startup, if config.json exists alongside config.example.json, any scalar
fields (strings, ints, booleans) present in the example but absent in the running
config are added automatically and the file is rewritten atomically. Existing values
and dict/list sections are never touched. Added fields are logged at INFO level.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:58:09 +02:00
9a3b7aa4f5 Add OpenAI tool-calling agentic loop with file tools and MiniMax MCP integration
- AIService.generate() now runs an agentic loop: sends tools to the API,
  handles tool_calls responses, executes tools, appends results, and repeats
  until a text response (up to tool_max_rounds, default 10)
- New app/ai/tools.py: six sandboxed file tools (write/read/create/modify/delete/list),
  OpenAI JSON schemas, path sandbox validator, and MCP→OpenAI schema converter
- Paths are sandboxed to workspace/ (project root) and prompts/ai/; traversal blocked
- MinimaxImageUnderstandClient gains list_tools() and call_tool() methods; MCP tool
  schemas are lazily fetched once per session and forwarded to the AI as callable tools
- AIConfig gains workspace_dir (Path, default workspace/) and tool_max_rounds (int, default 10)
- MCP client opened lazily only when an MCP tool is actually called during a loop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 09:55:45 +02:00
fb78d813af Use free Telegram reactions for AI status (🤔/👍/👎)
Replace premium-only ⏳/✅/❌ with reactions available to all users:
🤔 while processing, 👍 on success, 👎 on error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 16:02:13 +02:00
65088c2fdc Replace AI status message with emoji reactions
Instead of sending/editing a verbose status message, now reacts to the
command message: ⏳ while processing, ✅ on success, ❌ on error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 15:19:14 +02:00
e4e47c4649 Fix UTF-8 decode error for providers returning invalid encoding (Ollama)
Some providers (e.g. Ollama) may return response bytes that aren't valid
UTF-8. json.loads() raises UnicodeDecodeError in that case. Add an httpx
response event hook that replaces invalid bytes before the SDK parses the
response body.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 15:14:27 +02:00
783c5c2b87 Fix Minimax chat completions base_url in .env.example
Chat completions API lives on api.minimax.io, not api.minimax.chat.
api.minimax.chat is only for the coding-plan MCP (image understanding).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 13:32:33 +02:00
56352a19b0 Add rotating file logging
Logs go to bot.log in the project root by default (10 MB, 3 backups).
Set LOG_FILE env var to override the path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:39:24 +02:00
ba41ad6a70 Fix wrong-prefix silent ignore and Minimax image understand host
- Remove "Use .cmd for this role" reply when owner uses wrong prefix;
  wrong-prefix commands are now silently ignored for all users
- Fix AIImageUnderstandConfig default api_host to api.minimax.chat
  (minimax-coding-plan-mcp routes all calls there, not api.minimax.io)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 12:34:43 +02:00
Codex
86f7827802 Refine AI image context handling 2026-05-14 18:34:40 +02:00
Codex
2a731600e0 Add dual-prefix AI command 2026-05-14 13:24:47 +02:00
Codex
27b2760079 Add multi-account command ACL system 2026-05-13 22:19:27 +02:00