The redirect blocker was rejecting safe stderr patterns like
2>/dev/null and 2>&1. Strip these before operator checks so they
don't trigger the generic > or & blockers.
Also adds debug/trace logging to all early rejection paths in
is_command_allowed for audit visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shell tool now logs at debug level: command invocations, policy
allow/block decisions with reasons, exit codes, and output sizes.
Trace level adds full stdout/stderr content and risk assessment details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow `allowed_commands = ["*"]` to bypass the command allowlist check.
Hardcoded safety blocks (subshell operators, redirections, tee,
background &) still apply regardless of wildcard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Some models (e.g. Qwen 3.5) enforce that all system messages must appear
at the beginning of the conversation. The Telegram delivery instructions
were appended as a separate system message after the user message,
causing a Jinja template error. Merge them into the first system message
instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow ["*"] in http_request.allowed_domains to permit all public
domains without listing each one individually. Private/localhost
hosts remain blocked regardless.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Telegram returns 400 with "message is not modified" when editMessageText
is called with content identical to the current message. This happens
when streaming deltas have already updated the draft to the final text.
Previously this triggered a fallback to sendMessage, producing a
duplicate message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ToolStatusEvent enum (Thinking, ToolStart) and extract_tool_detail
helper to the agent loop. run_tool_call_loop now accepts an optional
on_tool_status sender and emits events before LLM calls and tool
executions. CLI callers pass None; the channel orchestrator uses it
for real-time draft updates.
Includes unit tests for extract_tool_detail covering all tool types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show real-time tool execution status in channels with draft support
(e.g. Telegram with stream_mode=partial). During processing, the draft
message shows "Thinking..." and progressively adds tool lines like
"🔧 shell(ls -la)" as tools execute. The final response replaces
all status lines cleanly via finalize_draft.
Also makes the channel message timeout configurable via
agent.channel_message_timeout_secs (default 300s), replacing the
previously hardcoded constant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The frequency check compared two consecutive calls to
next_run_for_schedule with now and now+1s, which returned the same
next occurrence for daily schedules — making the interval appear as
0 minutes. Compare two consecutive occurrences instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enable matrix-sdk markdown support and send Matrix messages with text_markdown so clients can render formatted_body.
Add listener startup diagnostics for device verification and backup state to reduce confusion around matrix_sdk_crypto backup warnings.
Expand Matrix docs with backup-warning interpretation, unverified-device guidance, markdown formatting expectations, and updated log keyword appendix.
- add scope-aware proxy schema and runtime wiring for providers/channels/tools
- add agent callable proxy_config tool for fast proxy setup
- standardize docs system with index, template, and playbooks
Add mention_only support for the Mattermost channel, matching the existing
Discord implementation. When enabled, the bot only processes messages that
contain an @-mention of the bot username, reducing noise in busy channels.
- Add mention_only field to MattermostConfig schema (Option<bool>, default false)
- Rename get_bot_user_id() to get_bot_identity() returning (user_id, username)
- Add contains_bot_mention_mm() with case-insensitive word-boundary matching
and metadata.mentions array support
- Add normalize_mattermost_content() to strip @-mentions from processed text
- Wire mention_only through channel and cron factory constructors
- Add 23 new tests covering mention detection, stripping, case-insensitivity,
word boundaries, metadata mentions, empty-after-strip, and disabled passthrough
Address clippy pedantic/all lints: format_push_string in sqlite memory,
match_same_arms and match_wildcard_for_single_variants in anthropic
provider and prometheus observer, option_as_ref_cloned in main. Fix
pre-existing test compilation errors in gateway (missing max_keys arg
and trust_forwarded_headers field) and memory_store (missing security
arg). Add .worktrees/ to gitignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Route OVHcloud through OpenAiProvider (with proper tool_call_id
serialization) instead of OpenAiCompatibleProvider, fixing tool-call
round-trips against vLLM-based endpoints.
- Add base_url field and with_base_url() constructor to OpenAiProvider
- Replace all hardcoded api.openai.com URLs with self.base_url
- Pass api_url through for the openai provider arm
- Register ovhcloud/ovh provider with env var OVH_AI_ENDPOINTS_ACCESS_TOKEN
Field is unused since the IMAP polling loop was replaced with IDLE.
Serde ignores unknown fields on deserialization, so existing configs
with the key set will continue to work without error.
Also add two focused tests for idle_timeout_secs: explicit
deserialization and propagation into EmailChannel.
Replace the blocking, poll-based IMAP client with async-imap and
IMAP IDLE (RFC 2177) for instant push delivery. Key changes:
- Add async-imap dependency with tokio runtime feature
- Rewrite connect/fetch/listen paths to fully async using tokio TLS
- Implement IDLE loop with exponential backoff reconnection (1s–60s cap)
- Add idle_timeout_secs config field (default 1740s per RFC 2177)
- Convert health_check to async connect-and-logout with 10s timeout
- Update affected tests from sync to #[tokio::test]
SMTP send path, allowlist enforcement, and Channel trait contract
are unchanged.
Adds mention_only config option to Telegram channel, allowing the bot
to only respond to messages that @-mention the bot in group chats.
Direct messages are always processed regardless of this setting.
Behavior:
- When mention_only = true: Bot only responds to group messages containing @botname
- When mention_only = false (default): Bot responds to all allowed messages
- DM/private chats always work regardless of mention_only setting
Implementation:
- Fetch and cache bot username from Telegram API on startup
- Check for @botname mention in group messages
- Strip mention from message content before processing
Config example:
[channels.telegram]
bot_token = "your_token"
mention_only = true
Changes:
- src/config/schema.rs: Add mention_only to TelegramConfig
- src/channels/telegram.rs: Implement mention_only logic + 6 new tests
- src/channels/mod.rs: Update factory calls
- src/cron/scheduler.rs: Update constructor call
- src/onboard/wizard.rs: Update wizard config
- src/daemon/mod.rs: Update test config
- src/integrations/registry.rs: Update test config
- TESTING_TELEGRAM.md: Add mention_only test section
- CHANGELOG.md: Document feature
Risk: medium
Backward compatible: Yes (default: false)
HEARTBEAT.md is only relevant to the heartbeat worker, which reads it
directly from disk. Including it in channel system prompts caused LLMs
to emit spurious 'HEARTBEAT_OK' acknowledgments at the start of
channel responses.
The agent prompt (src/agent/prompt.rs) still includes HEARTBEAT.md,
which is correct for agent and heartbeat contexts.
Implement chat_with_tools() on CompatibleProvider so OpenAI-compatible
endpoints (OpenRouter, local LLMs, etc.) can use structured tool calling
instead of prompt-injected tool descriptions.
Changes:
- CompatibleProvider: capabilities() reports native_tool_calling, new
chat_with_tools() sends tools in API request and parses tool_calls
from response, chat() bridges to chat_with_tools() when ToolSpecs
are provided
- RouterProvider: chat_with_tools() delegation with model hint resolution
- loop_.rs: expose tools_to_openai_format as pub(crate), add
tools_to_openai_format_from_specs for ToolSpec-based conversion
Adds 9 new tests and updates 1 existing test.
Add two Mattermost channel enhancements:
1. thread_replies config option (default: false)
- When false, replies go to the channel root instead of threading.
- When true, replies thread on the original post.
- Existing thread replies always stay in-thread regardless of setting.
2. Typing indicator (start_typing/stop_typing)
- Implements the Channel trait's typing methods for Mattermost.
- Fires POST /api/v4/users/me/typing every 4s in a background task.
- Supports parent_id for threaded typing indicators.
- Aborts cleanly on stop_typing via JoinHandle.
Updated all MattermostChannel::new call sites (start_channels, scheduler)
and added 9 unit tests covering thread routing and edge cases.