Reset supervisor backoff after successful component run to prevent excessive delays.
- Reset backoff to initial value when component exits cleanly (Ok(()))
- Move backoff doubling to AFTER sleep so first error uses initial_backoff
- Applied to both channel listener and daemon component supervisors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skip retries on non-retryable HTTP client errors (4xx) to avoid wasting time on requests that will never succeed.
- Added is_non_retryable() function to detect non-retryable errors
- 4xx client errors (400, 401, 403, 404) are now non-retryable
- Exceptions: 429 (rate limiting) and 408 (timeout) remain retryable
- 5xx server errors remain retryable
- Fallback logic now skips retries for non-retryable errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive IRC over TLS channel implementation with:
- TLS support with optional certificate verification
- SASL PLAIN authentication (IRCv3)
- NickServ IDENTIFY authentication
- Server password support (for bouncers like ZNC)
- Channel and private message (DM) support
- Message splitting for IRC 512-byte line limit
- UTF-8 safe splitting at character boundaries
- Case-insensitive nickname allowlist
- IRC style prefix for LLM responses (plain text only)
- Configurable via TOML or onboard wizard
All 959 tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add new structs for Responses API request/response format
- Add helper functions for extracting text from Responses API responses
- Refactor auth header application into a shared apply_auth_header method
- When chat completions returns 404 NOT_FOUND, fall back to Responses API
- Add tests for Responses API text extraction
This enables compatibility with providers that implement the Responses API
instead of Chat Completions (e.g., some newer Groq models).
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Use Path::components() to check for actual .. path components instead of
simple string matching (which was too conservative)
- Block URL-encoded traversal attempts (e.g., ..%2f)
- Expand tilde (~) for comparison
- Use path-component-aware matching for forbidden paths
- Update test to allow .. in filenames but block actual path traversal
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Move create_dir_all before canonicalize to prevent race condition where
an attacker could create a symlink after the check but before the write
- Reject symlinks at the target path to prevent symlink attacks
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This fix addresses CWE-200 by clearing environment variables before
executing shell commands and only re-adding safe, functional variables.
- Add SAFE_ENV_VARS constant with whitelist of safe variables
- Use .env_clear() before executing commands
- Add tests for environment variable isolation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Warn when fallback providers share the same API key as primary (could fail
if providers require different keys)
- Warm up all providers instead of just the first, continuing on warmup failures
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Fix URL validation to check for https:// or http:// prefixes instead of partial string matching which could be bypassed
- Add path traversal protection in skill remove command to reject .., /, and verify canonical path is inside the skills directory
- Update truncate_with_ellipsis to trim trailing whitespace for cleaner output
- Fix test expectations to match trimmed behavior
- This resolves merge conflicts and ensures consistent string truncation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move all CLI command enums (ChannelCommands, SkillCommands, CronCommands, IntegrationCommands, MigrateCommands, ServiceCommands) to lib.rs
- Add clap derives for use in main.rs CLI parsing
- Update all modules to use crate:: prefix instead of super:: for command types
- Add mod util; to main.rs for binary compilation
- Export Config type from lib.rs for main.rs
This refactoring eliminates code duplication between library modules and binary, centralizing all CLI command definitions in one place.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes Issue #55: Unicode string truncation causes panics with non-ASCII input
Previously, code used byte-index slicing (`&s[..n]`) which panics when the
slice boundary falls in the middle of a multi-byte UTF-8 character (emoji,
CJK, accented characters).
Changes:
- Added `truncate_with_ellipsis()` helper in `src/util.rs` that uses
`char_indices()` to find safe character boundaries
- Replaced 2 unsafe truncations in `src/channels/mod.rs` with the safe helper
- Added 12 comprehensive tests covering emoji, CJK, accented chars, and edge cases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>