Add Astrai (https://as-trai.com) as a first-class OpenAI-compatible
provider. Astrai is an AI inference router with built-in cost
optimization, PII stripping, and compliance logging.
- Register ASTRAI_API_KEY env var in resolve_api_key
- Add "astrai" entry in provider factory → as-trai.com/v1
- Add factory_astrai unit test
- Add Astrai to compatible provider test list
- Update README provider count (22+ → 23+) and list
Co-authored-by: Maya Walcher <maya.walcher@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* security(deps): remove vulnerable xmas-elf dependency via embuild
* chore(deps): update dependencies and improve ESP-IDF compatibility
- Updated `bindgen`, `embassy-sync`, `embedded-svc`, and `embuild` versions in `Cargo.lock`.
- Added patch section in `Cargo.toml` to use latest esp-rs crates for better compatibility with ESP-IDF 5.x.
- Enhanced README with updated prerequisites and build instructions for Python and Rust tools.
- Introduced `rust-toolchain.toml` to pin nightly Rust and added necessary components.
- Modified GPIO handling in `main.rs` to improve pin management and added support for 64-bit time_t in ESP-IDF.
- Updated `.cargo/config.toml` for new linker and runner configurations.
* docs: add detailed setup guide for ESP32 firmware and link in README
- Introduced a new `SETUP.md` file with comprehensive step-by-step instructions for building and flashing the ZeroClaw ESP32 firmware.
- Updated `README.md` to include a link to the new setup guide for easier access to installation and troubleshooting information.
* chore: update .gitignore and refactor main.rs for improved readability
- Added .embuild/ to .gitignore to exclude ESP32 build cache.
- Refactored code in main.rs for better readability by adjusting the formatting of the handle_request function call.
* docs: add newline for better readability in README.md
- Added a newline in the protocol section of README.md to enhance clarity and formatting.
* chore: configure workspace settings in Cargo.toml
- Added workspace configuration to `Cargo.toml` with members and resolver settings for improved project management.
---------
Co-authored-by: ehushubhamshaw <eshaw1@wpi.edu>
Co-authored-by: Will Sarg <12886992+willsarg@users.noreply.github.com>
* test(security): add HTTP hostname canonicalization edge-case tests
Document that Rust's IpAddr::parse() rejects non-standard IP notations
(octal, hex, decimal integer, zero-padded) which provides defense-in-depth
against SSRF bypass attempts. Tests only — no production code changes.
Closes#515
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: apply rustfmt to providers/mod.rs
Fix pre-existing formatting issue from main.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The contributor-tier-issues job triggers on pull_request_target events
but only had issues:write permission. GitHub API requires
pull-requests:write to set labels on pull requests, causing a 403
"Resource not accessible by integration" error.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The CLI --port and --host args had hardcoded defaults (8080, 127.0.0.1)
that always overrode the user's config.toml [gateway] settings (port=3000,
host=127.0.0.1). Changed both args to Option types and fall back to
config.gateway.port / config.gateway.host when not explicitly provided.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Changed the project license from Apache-2.0 to MIT for maximum
permissiveness and openness.
Changes:
- Cargo.toml: Updated license field from "Apache-2.0" to "MIT"
- LICENSE: Replaced Apache-2.0 text with MIT license text
- README.md: Updated license badge and section from Apache 2.0 to MIT
MIT is a simpler, more permissive license that allows for maximum
flexibility while still requiring attribution and disclaiming warranty.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(channels): add channel capabilities to system prompt
Add channel capabilities section to system prompt so the agent knows
it can send Discord messages directly without asking permission.
Also reminds agent not to repeat or echo credentials.
Co-authored-by: Vernon Stinebaker <vernon.stinebaker@gmail.com>
* chore: fix formatting and clippy warnings
When mention_only is true, the bot only responds to messages that
@-mention the bot. Other messages in the guild are silently ignored.
Also strips the bot mention from content before processing.
Co-authored-by: Will Sarg <12886992+willsarg@users.noreply.github.com>
* fix(security): enhance shell redirection blocking in security policy
Block process substitution (<(...) and >(...)) and tee command in
is_command_allowed() to close shell escape vectors that bypass existing
redirect and subshell checks.
Closes#514
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: apply rustfmt to providers/mod.rs
Fix pre-existing formatting issue from main.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): expand git argument sanitization
Expand sanitize_git_args() blocklist to also reject --pager=, --editor=,
-c (config injection), --no-verify, and > in arguments. Apply validation
to git_add() paths and git_diff() files argument (previously only called
from git_checkout()). The -c check uses exact match to avoid
false-positives on --cached.
Closes#516
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: apply rustfmt to providers/mod.rs
Fix pre-existing formatting issue from main.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Pin ubuntu:22.04 to its current manifest digest to ensure
reproducible builds and prevent supply-chain mutations.
Closes#513
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace floating tag refs (@v1, @v2) with SHA-pinned refs to prevent
supply-chain attacks via tag mutation on third-party Actions.
Pinned:
- useblacksmith/setup-docker-builder@v1 → ef12d5b1
- useblacksmith/build-push-action@v2 → 30c71162
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): add config file permission hardening
Set 0o600 permissions on newly created config.toml files and warn if
an existing config file is world-readable. Prevents accidental exposure
of API keys on multi-user systems. Unix-only (#[cfg(unix)]).
Follows existing pattern from src/security/secrets.rs.
Closes#517
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: apply rustfmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(memory): add session_id isolation to Memory trait
Add optional session_id parameter to store(), recall(), and list()
methods across the Memory trait and all four backends (sqlite, markdown,
lucid, none). This enables per-session memory isolation so different
agent sessions cannot cross-read each other's stored memories.
Changes:
- traits.rs: Add session_id: Option<&str> to store/recall/list
- sqlite.rs: Schema migration (ALTER TABLE ADD COLUMN session_id),
index, persist/filter by session_id in all query paths
- markdown.rs, lucid.rs, none.rs: Updated signatures
- All callers pass None for backward compatibility
- 5 new tests: session-filtered recall, cross-session isolation,
session-filtered list, no-filter returns all, migration idempotency
Closes#518
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(channels): fix discord _channel_id typo and lark missing reply_to
Pre-existing compilation errors on main after reply_to was added to
ChannelMessage: discord.rs used _channel_id (underscore prefix) but
referenced channel_id, and lark.rs was missing the reply_to field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add `lmstudio` / `lm-studio` as a built-in provider alias for local LM Studio instances
(`http://localhost:1234/v1`)
- Uses a dummy API key when none is provided, since LM Studio does not require authentication
- Users can connect to remote LM Studio instances via `custom:http://<ip>:1234/v1`
ChannelMessage.sender was used both for display (username) and as the
reply target in Channel::send(). For Telegram, sender is the username
(e.g. "unknown") while send() requires the numeric chat_id, causing
"Bad Request: chat not found" errors.
Add a dedicated reply_to field to ChannelMessage that stores the
channel-specific reply address (Telegram chat_id, Discord channel_id,
Slack channel, etc.). Update all channel implementations and dispatch
code to use reply_to for send/start_typing/stop_typing calls.
This also fixes the same latent bug in Discord and Slack channels where
sender (user ID) was incorrectly passed as the reply target.
`cargo install` places the binary in ~/.cargo/bin, which may not be in
the user's PATH by default. This adds an explicit export step so new
users don't hit a "not found" error after install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ProviderCapabilities struct to enable runtime detection of
provider-specific features, starting with native tool calling support.
This is a foundational change that enables future PRs to implement
intelligent tool calling mode selection (native vs prompt-guided).
Changes:
- Add ProviderCapabilities struct with native_tool_calling field
- Add capabilities() method to Provider trait with default impl
- Add unit tests for capabilities equality and defaults
Why:
- Current design cannot distinguish providers with native tool calling
- Needed to enable Gemini/Anthropic/OpenAI native function calling
- Fully backward compatible (all providers inherit default)
What did NOT change:
- No existing Provider methods modified
- No behavior changes for existing code
- Zero breaking changes
Testing:
- cargo test: all tests passed
- cargo fmt: pass
- cargo clippy: pass