- Remove unused import AsyncBufReadExt in compatible.rs
- Remove unused mut keywords from response and tx
- Remove unused variable 'name'
- Prefix unused parameters with _ in traits.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement Server-Sent Events (SSE) streaming for OpenAI-compatible providers:
- Add StreamChunk, StreamOptions, and StreamError types to traits module
- Add supports_streaming() and stream_chat_with_system() to Provider trait
- Implement SSE parser for OpenAI streaming responses (data: {...} format)
- Add streaming support to OpenAiCompatibleProvider
- Add streaming support to ReliableProvider with error propagation
- Add futures dependency for async stream support
Features:
- Token-by-token streaming for real-time feedback
- Token counting option (estimated ~4 chars per token)
- Graceful error handling and logging
- Channel-based stream bridging for async compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add ZeroClaw firmware for ESP32 and Nucleo
* Introduced new firmware for ZeroClaw on ESP32 and Nucleo-F401RE, enabling JSON-over-serial communication for GPIO control.
* Added `zeroclaw-esp32` with support for commands like `gpio_read` and `gpio_write`, along with capabilities reporting.
* Implemented `zeroclaw-nucleo` firmware with similar functionality for STM32, ensuring compatibility with existing ZeroClaw protocols.
* Updated `.gitignore` to include new firmware targets and added necessary dependencies in `Cargo.toml` for both platforms.
* Created README files for both firmware projects detailing setup, build, and usage instructions.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: enhance hardware peripheral support and documentation
- Added `Peripheral` trait implementation in `src/peripherals/` to manage hardware boards (STM32, RPi GPIO).
- Updated `AGENTS.md` to include new extension points for peripherals and their configuration.
- Introduced comprehensive documentation for adding boards and tools, including a quick start guide and supported boards.
- Enhanced `Cargo.toml` to include optional dependencies for PDF extraction and peripheral support.
- Created new datasheets for Arduino Uno, ESP32, and Nucleo-F401RE, detailing pin aliases and GPIO usage.
- Implemented new tools for hardware memory reading and board information retrieval in the agent loop.
This update significantly improves the integration and usability of hardware peripherals within the ZeroClaw framework.
* feat: add ZeroClaw firmware for ESP32 and Nucleo
* Introduced new firmware for ZeroClaw on ESP32 and Nucleo-F401RE, enabling JSON-over-serial communication for GPIO control.
* Added `zeroclaw-esp32` with support for commands like `gpio_read` and `gpio_write`, along with capabilities reporting.
* Implemented `zeroclaw-nucleo` firmware with similar functionality for STM32, ensuring compatibility with existing ZeroClaw protocols.
* Updated `.gitignore` to include new firmware targets and added necessary dependencies in `Cargo.toml` for both platforms.
* Created README files for both firmware projects detailing setup, build, and usage instructions.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: enhance hardware peripheral support and documentation
- Added `Peripheral` trait implementation in `src/peripherals/` to manage hardware boards (STM32, RPi GPIO).
- Updated `AGENTS.md` to include new extension points for peripherals and their configuration.
- Introduced comprehensive documentation for adding boards and tools, including a quick start guide and supported boards.
- Enhanced `Cargo.toml` to include optional dependencies for PDF extraction and peripheral support.
- Created new datasheets for Arduino Uno, ESP32, and Nucleo-F401RE, detailing pin aliases and GPIO usage.
- Implemented new tools for hardware memory reading and board information retrieval in the agent loop.
This update significantly improves the integration and usability of hardware peripherals within the ZeroClaw framework.
* feat: Introduce hardware auto-discovery and expanded configuration options for agents, hardware, and security.
* chore: update dependencies and improve probe-rs integration
- Updated `Cargo.lock` to remove specific version constraints for several dependencies, including `zerocopy`, `syn`, and `strsim`, allowing for more flexibility in version resolution.
- Upgraded `bincode` and `bitfield` to their latest versions, enhancing serialization and memory management capabilities.
- Updated `Cargo.toml` to reflect the new version of `probe-rs` from `0.24` to `0.30`, improving hardware probing functionality.
- Refactored code in `src/hardware` and `src/tools` to utilize the new `SessionConfig` for session management in `probe-rs`, ensuring better compatibility and performance.
- Cleaned up documentation in `docs/datasheets/nucleo-f401re.md` by removing unnecessary lines.
* fix: apply cargo fmt
* docs: add hardware architecture diagram.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Switch Provider trait methods to return structured ChatResponse
- Map OpenAI-compatible tool_calls into shared ToolCall type
- Update reliable/router wrappers and provider tests for new interface
- Make agent loop prefer structured tool calls with text fallback parsing
- Adapt gateway replies to structured responses with safe tool-call fallback
Fixes#221 - SQLite Memory Override bug.
This PR resolves memory overwrite behavior in autosave paths by replacing fixed memory keys with unique keys, and improves short-horizon recall quality in channel runtime.
**Root Cause**
SQLite memory uses a unique constraint on `memories.key` and writes with `ON CONFLICT(key) DO UPDATE`.
Several autosave paths reused fixed keys (or sender-stable keys), so newer messages overwrote earlier conversation entries.
**Changes**
- Channel runtime: autosave key changed from `channel_sender` to `channel_sender_messageId`
- Added memory-context injection before provider calls (aligned with agent loop behavior)
- Agent loop: autosave keys changed from fixed `user_msg`/`assistant_resp` to UUID-suffixed keys
- Gateway: Webhook/WhatsApp autosave keys changed to UUID-suffixed keys
All CI checks passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The OpenAI-compatible provider was not properly handling tool_calls
in API responses. When providers like MiniMax return tool_calls in
OpenAI's native format, the provider was only extracting the content
field and discarding the tool_calls.
Changes:
- Update ResponseMessage struct to include optional tool_calls field
- Add ToolCall and Function structs for deserializing tool_calls
- Serialize full message as JSON when tool_calls are present
- Fall back to plain content when no tool_calls
This allows the parse_tool_calls function in the agent loop to
properly handle OpenAI-style tool_calls format.
All 1080 tests pass.
Related to #226
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add multi-turn conversation history and tool execution
Major enhancement to the agent loop:
**Multi-turn conversation:**
- Add `ChatMessage` type with system/user/assistant constructors
- Add `chat_with_history` method to Provider trait (default impl
delegates to `chat_with_system` for backward compatibility)
- Implement native `chat_with_history` on OpenRouter, Compatible,
Reliable, and Router providers to send full message history
- Interactive mode now maintains persistent history across turns
**Tool execution:**
- Agent loop now parses `<tool_call>` XML tags from LLM responses
- Executes tools from the registry and feeds results back as
`<tool_result>` messages
- Agentic loop continues until LLM produces final text (no tool calls)
- MAX_TOOL_ITERATIONS (10) safety limit prevents runaway loops
- System prompt includes structured tool-use protocol with JSON schemas
**Types:**
- `ChatMessage`, `ChatResponse`, `ToolCall`, `ToolResultMessage`,
`ConversationMessage` — full conversation modeling types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address review comments on multi-turn + tool execution
- Add history sliding window (MAX_HISTORY_MESSAGES=50) to prevent
unbounded conversation history growth in interactive mode
- Add 404→Responses API fallback in compatible.rs chat_with_history,
matching chat_with_system behavior
- Use super::api_error() for error sanitization in compatible.rs
instead of raw error body (prevents secret leakage)
- Add missing operational logs in reliable.rs chat_with_history:
recovery, non-retryable, fallback switch warnings
- Add trim_history tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address second round of review comments
- Sanitize raw error text in compatible.rs chat_with_system using
sanitize_api_error (prevents leaking secrets in error messages)
- Add chat_with_history to MockProvider in reliable.rs tests so
the retry/fallback path is exercised end-to-end
- Add chat_with_history_retries_then_recovers and
chat_with_history_falls_back tests
- Log warning on malformed <tool_call> JSON instead of silent drop
- Flush stdout after print! in agent_turn so output appears before
tool execution on line-buffered terminals
- Make interactive mode resilient to transient errors (continue
loop instead of terminating session)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(providers): use Bearer auth for Gemini CLI OAuth tokens
When credentials come from ~/.gemini/oauth_creds.json (Gemini CLI),
send them as Authorization: Bearer header instead of ?key= query
parameter. API keys from env vars or config continue using ?key=.
Fixes#194
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(gemini): harden OAuth bearer auth flow and tests
* fix(gemini): granular auth source tracking and review fixes
Build on chumyin's auth model refactor with:
- Expand GeminiAuth to 4 variants (ExplicitKey/EnvGeminiKey/EnvGoogleKey/
OAuthToken) so auth_source() uses stored discriminant without re-reading
env vars at call time
- Add is_api_key()/credential() helpers on the enum
- Upgrade expired OAuth token log from debug to warn
- Add tests: provider_rejects_empty_key, auth_source_explicit_key,
auth_source_none_without_credentials
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: apply rustfmt to fix CI lint failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: root <root@instance-20220913-1738.vcn09131738.oraclevcn.com>
Co-authored-by: argenis de la rosa <theonlyhennygod@gmail.com>
* feat(providers): add provider-aware API key resolution
- Add resolve_api_key() function that checks provider-specific env vars first
- For Anthropic, checks ANTHROPIC_OAUTH_TOKEN before ANTHROPIC_API_KEY
- Falls back to generic ZEROCLAW_API_KEY and API_KEY env vars
- Update create_provider() to use resolved_key instead of raw api_key
- Trim and filter empty strings from input keys
This enables setup-token support for Anthropic by checking ANTHROPIC_OAUTH_TOKEN
before ANTHROPIC_API_KEY when resolving credentials.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(providers): add Anthropic setup-token support
- Rename api_key field to credential for clarity
- Add is_setup_token() method to detect setup-token format (sk-ant-oat01-)
- Add input trimming and empty string filtering
- Use Bearer auth for setup-tokens, x-api-key for regular API keys
- Update error message to mention both ANTHROPIC_API_KEY and ANTHROPIC_OAUTH_TOKEN
- Add test for setup-token detection
- Add test for whitespace trimming in new()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: skip serialization of config_path and workspace_dir to prevent save() failures
The config_path and workspace_dir fields are computed paths that should not be
serialized to the config file. When loading from TOML, these fields would be
deserialized as empty paths (or stale paths), causing save() to fail with
"Failed to write config file".
Fixes#112
Changes:
- Add #[serde(skip)] to config_path and workspace_dir fields
- Set computed paths in load_or_init() after deserializing from TOML
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(discord): track gateway sequence number and handle reconnect opcodes
Three Discord Gateway issues fixed:
1. **Heartbeat sent `null` sequence** — Per Discord docs, the Gateway may
disconnect bots that don't include the last sequence number in heartbeats.
Now tracked via `sequence: i64` and included in every heartbeat.
2. **Dispatch sequence ignored** — The `s` field from dispatch events was
never stored. Now extracted and tracked from every event.
3. **Opcodes 7/9 silently ignored** — Reconnect (op 7) and Invalid Session
(op 9) caused the bot to hang on a dead connection. Now breaks the event
loop so the daemon supervisor can restart the channel cleanly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(memory): use SHA-256 for embedding cache keys instead of DefaultHasher
- Replace DefaultHasher with SHA-256 for deterministic cache keys
- DefaultHasher is explicitly documented as unstable across Rust versions
- Truncate SHA-256 to 8 bytes (16 hex chars) to match previous format
- Ensures embedding cache is deterministic across Rust compiler versions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
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>