Commit graph

954 commits

Author SHA1 Message Date
Alex Gorevski
673697a43e test(peripherals): add unit tests for peripheral module configuration and listing
Add tests for list_configured_boards() covering enabled/disabled states and
empty/non-empty board configurations. Add test verifying create_peripheral_tools()
returns empty when peripherals are disabled. Addresses audit finding CRITICAL-1
for the untested peripherals module — covers all non-hardware-gated logic paths.

Fix pre-existing Windows build errors in config/schema.rs: make non-unix
sync_directory async and gate unix-only imports behind #[cfg(unix)].

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:28:22 -08:00
Alex Gorevski
22bd03c65a test(quality): replace bare .unwrap() with .expect() in agent and shell tests
Replace bare .unwrap() calls with descriptive .expect() messages in
src/agent/agent.rs and src/tools/shell.rs test modules. Adds meaningful
failure context for memory creation, agent builder, and tool execution
assertions. Addresses audit finding on test assertion quality (§5.2).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:23:33 -08:00
Alex Gorevski
d407eb61f0 test(fuzz): add webhook, provider response, and command validation fuzz targets
Add three new fuzz targets expanding coverage from 2 to 5 targets:
- fuzz_webhook_payload: fuzzes webhook body JSON deserialization
- fuzz_provider_response: fuzzes provider API response parsing
- fuzz_command_validation: fuzzes security policy command validation
Addresses audit findings for critical fuzz coverage gaps in gateway,
provider, and security subsystems.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:56 -08:00
Alex Gorevski
dd541bd7e4 docs(code): add decision-point comments to agent loop, security policy, and reliable provider
Adds section markers and decision-point comments to the three most complex
control-flow modules. Comments explain loop invariants, retry/fallback
strategy, security policy precedence rules, and error handling rationale.

This improves maintainability by making the reasoning behind complex
branches explicit for reviewers and future contributors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:53 -08:00
Alex Gorevski
eae8a99584 docs(code): add comprehensive doc comments to config schema public fields
Every public field in the Config struct hierarchy now has a /// doc comment
explaining its purpose, default value, and usage context. This ensures
operators and extension developers can understand config options directly
from rustdoc without cross-referencing the config reference documentation.

Comments are consistent with docs/config-reference.md descriptions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:52 -08:00
Alex Gorevski
25fd10a538 docs(code): expand doc comments on security, observability, runtime, and peripheral traits
The four underdocumented core trait files now include trait-level doc blocks
explaining purpose and architecture role, method-level documentation with
parameter/return/error descriptions, and public struct/enum documentation.

This brings parity with the well-documented provider, channel, tool, and
memory traits, giving extension developers clear guidance for implementing
these core extension points.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:46 -08:00
Alex Gorevski
6d4bfb73ba docs: add architecture, subscription auth, and memory system sections to multilingual READMEs
The English README contains architecture overview (diagram + trait table),
subscription auth setup (OAuth flow + examples), and memory system design
(vector + FTS5 hybrid search) sections that were missing from the Chinese,
Japanese, and Russian translations.

This closes the content parity gap identified in the documentation audit,
ensuring non-English speakers have access to the same critical architectural
context and setup guidance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:46 -08:00
Alex Gorevski
4a7dff6ef1 docs(code): add module-level doc blocks to providers, channels, tools, and security
Each major subsystem mod.rs now includes a //! doc block explaining the
subsystem purpose, trait-driven architecture, factory registration pattern,
and extension guidance. This improves the generated rustdoc experience for
developers navigating ZeroClaw's modular architecture.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:19:46 -08:00
Alex Gorevski
3b471e74b7 docs: enhance getting-started, hardware, and project collection indexes
Adds onboarding decision tree to getting-started/README.md so users can
quickly identify the right setup command for their situation.

Adds hardware vision overview to hardware/README.md explaining the
Peripheral trait and supported board types.

Expands project/README.md with scope explanation describing the purpose
of project snapshots and how they relate to documentation maintenance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:04:11 -08:00
Alex Gorevski
bec1dc7b8c
Merge pull request #994 from zeroclaw-labs/algore/merge_fix
fix: resolve merge conflict in pull request template
2026-02-19 12:55:23 -08:00
Alex Gorevski
d22adb21e6 fix: resolve merge conflict in pull request template
Remove merge conflict markers in .github/pull_request_template.md,
keeping the spaced module label format (\<module>: <component>\)
from the chore/labeler-spacing-trusted-tier branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 12:54:42 -08:00
Alex Gorevski
835d51d7e1
Merge pull request #971 from zeroclaw-labs/docs/social-telegram-cn-ru-channels
docs(readme): add Telegram CN/RU channels to media matrix
2026-02-19 12:51:04 -08:00
Alex Gorevski
229f826656
Merge pull request #969 from zeroclaw-labs/docs/homebrew-install-readme
docs(readme): add Homebrew install instructions
2026-02-19 12:50:41 -08:00
Alex Gorevski
141d483aa4
Merge pull request #987 from ecschoye/fix/openrouter-embedding-provider
fix(memory): add openrouter as recognized embedding provider
2026-02-19 12:47:25 -08:00
Edvard
832facf5ef fix(memory): add openrouter as recognized embedding provider
The embedding provider factory only recognized "openai" and "custom:*",
causing "openrouter" to silently fall through to NoopEmbedding. This
made vector/semantic search completely non-functional — memory recall
fell back to BM25 keyword-only matching, with 70% of the hybrid score
always returning zero.

Route "openrouter" through OpenAiEmbedding with the OpenRouter API base
URL (https://openrouter.ai/api/v1), which is OpenAI-compatible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:10:25 -05:00
Alex Gorevski
007e9fa7ea
Merge pull request #984 from zeroclaw-labs/fix/improve-config-error-messages
fix(errors): improve config error messages with section paths and remediation hints
2026-02-19 11:56:45 -08:00
Alex Gorevski
9ab2b7be61
Merge pull request #983 from zeroclaw-labs/fix/env-example-missing-vars
docs(env): add missing environment variables to .env.example
2026-02-19 11:55:36 -08:00
Alex Gorevski
b6f99c31d1
Merge pull request #982 from zeroclaw-labs/fix/cli-help-text-improvements
docs(cli): add detailed help text and examples to complex subcommands
2026-02-19 11:54:38 -08:00
Alex Gorevski
f308353ab2
Merge pull request #981 from zeroclaw-labs/fix/config-validation-on-load
fix(config): add startup validation to catch invalid config values early
2026-02-19 11:52:57 -08:00
Alex Gorevski
63f3c5fe6d
Merge pull request #980 from zeroclaw-labs/fix/config-reference-missing-sections
docs(config): add missing config sections to config-reference.md
2026-02-19 11:51:31 -08:00
Alex Gorevski
b84f0e1956
Merge pull request #979 from zeroclaw-labs/fix/cli-argument-range-validation
fix(cli): add range validation for temperature argument
2026-02-19 11:50:08 -08:00
Alex Gorevski
39a09f007b fix(cli): add range validation for temperature argument
Add a custom value_parser for the --temperature CLI argument to enforce
the documented 0.0-2.0 range at parse time. Previously, the comment
stated the valid range but clap did not reject out-of-range values,
allowing invalid temperatures to propagate to provider API calls.

- Add parse_temperature() validator that rejects values outside 0.0..=2.0
- Wire it into the Agent subcommand's temperature arg via value_parser

Addresses API surface audit §2.3 (CLI argument range validation).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:45:12 -08:00
Alex Gorevski
cc07cb66c3 fix(errors): improve config error messages with section paths and remediation hints
Improve vague error messages in channel initialization and tool setup
to include specific config key paths and remediation steps, matching
the quality standard set by proxy validation errors.

Changes:
- telegram.rs: Include [channels.telegram] section path and required
  fields (bot_token, allowed_users) in missing-config error; add
  onboard hint; specify channels.telegram.allowed_users in pairing
  message; improve parse error context
- whatsapp.rs: Specify channels.whatsapp.allowed_numbers key path
  in unauthorized-number warning
- linq.rs: Specify channels.linq.allowed_senders key path in
  unauthorized-sender warning; add onboard hint
- web_search_tool.rs: Include tools.web_search.provider config path
  and valid values in unknown-provider error

Addresses API surface audit §8.2 (config context in error messages).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:44:04 -08:00
Alex Gorevski
9f1a306962 docs(cli): add detailed help text and examples to complex subcommands
Add long_about attributes with usage examples to the following commands:

src/main.rs (binary CLI):
- Agent: interactive/single-message modes, provider/peripheral options
- Gateway: port/host binding with examples
- Daemon: full runtime explanation with service install reference
- Cron: cron expression format, timezone handling, all scheduling modes
- Channel: supported types, JSON config format, bind-telegram
- Hardware: discover, introspect, info subcommands
- Peripheral: add, flash, board types
- Config: schema export

src/lib.rs (library enums):
- CronCommands::Add: cron syntax and timezone examples
- CronCommands::AddAt: RFC 3339 timestamp format
- CronCommands::AddEvery: interval in milliseconds
- CronCommands::Once: human-readable duration syntax
- CronCommands::Update: partial field update
- ChannelCommands::Add: JSON config and supported types
- ChannelCommands::BindTelegram: username/numeric ID format
- HardwareCommands::Discover, Introspect, Info: device paths and chip names
- PeripheralCommands::Add: board types and transport paths
- PeripheralCommands::Flash: serial port options

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:42:31 -08:00
Alex Gorevski
99cf2fdfee fix(config): add startup validation to catch invalid config values early
Add Config::validate() called from load_or_init() after env overrides
are applied. This catches obviously invalid configuration values at
startup instead of allowing them to silently cause runtime failures.

Validated fields:
- gateway.host: must not be empty
- autonomy.max_actions_per_hour: must be > 0
- scheduler.max_concurrent: must be > 0
- scheduler.max_tasks: must be > 0
- model_routes[*]: hint, provider, model must not be empty
- embedding_routes[*]: hint, provider, model must not be empty
- proxy: delegates to existing ProxyConfig::validate()

Previously, ProxyConfig::validate() was only called during
apply_env_overrides() and only warned/disabled on failure. The new
Config::validate() runs it as a hard error after all overrides are
resolved, ensuring proxy misconfiguration is surfaced early.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:37:30 -08:00
Alex Gorevski
753e90e0e7 docs(config): add missing config sections to config-reference.md
Add documentation for config schema sections that were undocumented:

- [cost] — daily/monthly spending limits and cost tracking
- [identity] — AIEOS / OpenClaw identity format
- [hardware] — hardware wizard config (STM32, serial, probe)
- [peripherals] — peripheral board configurations (STM32, RPi GPIO)
- [browser] — browser automation backend config
- [browser.computer_use] — computer-use sidecar endpoint config
- [http_request] — HTTP request tool config
- [agents.<name>] — delegate sub-agent configurations
- [query_classification] — automatic model hint routing

Also expanded existing sections:
- [agent] — added compact_context, max_history_messages, parallel_tools, tool_dispatcher
- [[model_routes]] — added field reference table
- [[embedding_routes]] — added field reference table

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:34:48 -08:00
Alex Gorevski
7feb57ad53 docs(env): add missing environment variables to .env.example
Add env vars from apply_env_overrides() that were absent from .env.example:

- ZEROCLAW_REASONING_ENABLED / REASONING_ENABLED (reasoning mode)
- ZEROCLAW_STORAGE_PROVIDER (storage backend override)
- ZEROCLAW_STORAGE_DB_URL (remote storage connection URL)
- ZEROCLAW_STORAGE_CONNECT_TIMEOUT_SECS (storage connect timeout)
- ZEROCLAW_PROXY_ENABLED (proxy toggle)
- ZEROCLAW_HTTP_PROXY (HTTP proxy URL)
- ZEROCLAW_HTTPS_PROXY (HTTPS proxy URL)
- ZEROCLAW_ALL_PROXY (SOCKS/universal proxy URL)
- ZEROCLAW_NO_PROXY (proxy bypass list)
- ZEROCLAW_PROXY_SCOPE (proxy scope: environment|zeroclaw|services)
- ZEROCLAW_PROXY_SERVICES (service selector for scoped proxy)

Resolves audit finding §6.3.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 11:31:43 -08:00
Alex Gorevski
77609777ab
Merge pull request #951 from zeroclaw-labs/fix/per-client-pairing-lockout
fix(security): change pairing lockout to per-client accounting
2026-02-19 11:26:46 -08:00
Chummy
f7076183b9 docs(readme): add Telegram CN and RU channels to media matrix 2026-02-20 02:19:05 +08:00
Chummy
3733856093 Fix skill instruction/tool injection in system prompts 2026-02-20 02:16:41 +08:00
Nikolay Vyahhi
315985199b docs(readme): add Homebrew install instructions 2026-02-19 13:03:32 -05:00
Chummy
f2ffd653de fix(channel): preserve trailing user turn in normalization 2026-02-20 02:01:42 +08:00
Chummy
c5834b1077 fix(channel): normalize telegram history for MiniMax 2026-02-20 02:01:42 +08:00
Chummy
7173045f1c docs(readme): sync social badges to translated READMEs 2026-02-20 01:56:41 +08:00
Chummy
132a6b70e0 docs(readme): add X, Xiaohongshu, and Telegram media badges 2026-02-20 01:56:41 +08:00
Chummy
13dce49a5e docs(readme): add official Reddit badge and channel link 2026-02-20 01:56:41 +08:00
Chummy
4531c342f5 fix(onboard): remove fragile numeric channel dispatch
Use enum-backed channel menu dispatch to prevent duplicated match-arm indices and unreachable-pattern warnings (issue #913).

Also switch OpenAI native tool spec parsing to owned serde structs so tool-schema validation compiles.
2026-02-20 01:56:41 +08:00
Chummy
ef82c7dbcd fix(channels): interrupt in-flight telegram requests on newer sender messages 2026-02-20 01:54:07 +08:00
Chummy
d9a94fc763 fix(skills): escape inlined skill XML content 2026-02-20 01:28:49 +08:00
Edvard
8a4da141d6 fix(skills): inject skill prompts and tools into agent system prompt
Skill prompts and tool definitions from SKILL.toml were parsed and stored
correctly but never included in the agent's system prompt. Both prompt-building
paths (channels/mod.rs and agent/prompt.rs) only emitted skill metadata (name,
description, location), telling the LLM to "read" the SKILL.toml on demand.
This caused the agent to attempt manual file reads that often failed, leaving
skills effectively ignored.

Now both paths inline <instructions> and <tools> blocks inside each <skill>
XML element, so the agent receives full skill context without extra tool calls.

Closes #877

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:28:49 +08:00
Chummy
14fb3fbcae fix(composio): resolve connected account refs after OAuth 2026-02-20 01:28:19 +08:00
Chummy
d714d3984e fix(memory): stop autosaving assistant summaries and filter legacy entries 2026-02-20 01:14:08 +08:00
Chummy
6d745e9cb3 fix(openai): deserialize native tool specs with owned fields 2026-02-20 00:07:28 +08:00
Chummy
4c249c579f fix(composio): repair v3 execute path and enable alias 2026-02-20 00:07:28 +08:00
argenis de la rosa
a03ddc3ace fix: gate nusb/hardware discovery to Linux/macOS/Windows only
Android (Termux) reports target_os="android" which is not supported
by nusb::list_devices(). This caused E0425 and E0282 compile errors
when building on Termux.

Changes:
- Cargo.toml: move nusb to a target-gated dependency block so it is
  only compiled on linux/macos/windows
- src/hardware/discover.rs: add #![cfg(...)] file-level gate matching
  the nusb platform support matrix
- src/hardware/mod.rs: gate discover/introspect module declarations,
  discover_hardware() call, handle_command() dispatch, and all helper
  fns on the same platform set; add a clear user-facing message on
  unsupported platforms
- src/security/pairing.rs: replace deprecated rand::thread_rng() with
  rand::rng() to keep clippy -D warnings clean

Fixes #880
2026-02-20 00:02:01 +08:00
Alex Gorevski
56af0d169e fix(security): change pairing lockout to per-client accounting
Replace global failed-attempt counter with per-client HashMap keyed by
client identity (IP address for gateway, chat_id for Telegram).  This
prevents a single attacker from locking out all legitimate clients.

Bounded state: entries are evicted after lockout expiry, and the map is
capped at 1024 tracked clients.

Closes #603

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 07:33:11 -08:00
Alex Gorevski
ba500a606e
Merge pull request #948 from zeroclaw-labs/fix/wizard-channel-default-index
fix(onboard): correct channel selector default to 'Done' item
2026-02-19 07:21:10 -08:00
Alex Gorevski
8f8641d9fb fix(onboard): correct channel selector default to 'Done' item
The hardcoded .default(11) became stale when Lark/Feishu was
added at index 11, shifting 'Done — finish setup' to index 12.
The wizard now pre-selects the wrong channel instead of 'Done'.

Use options.len() - 1 so the default always tracks the last
item regardless of how many channels exist.

Fixes #913

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 07:19:20 -08:00
Alex Gorevski
3a19d6cd98
Merge pull request #872 from agorevski/perf/eliminate-unnecessary-heap-allocations
perf: eliminate unnecessary heap allocations across agent loop, memory and channels
2026-02-19 07:11:55 -08:00
Alex Gorevski
a4b27d2afe perf: eliminate unnecessary heap allocations across agent loop, memory, and channels
- Replace clone()+clear() with std::mem::take() in chunker (items 1, 6)
- Add Vec::with_capacity() hints in chunker split functions (item 2)
- Replace collect::<Vec<_>>().join() with direct iteration in IRC and
  email channels (item 3)
- Share heading strings via Rc<str> instead of cloning per chunk (item 5)
- Use borrowed references in provider tool spec types to avoid cloning
  name/description/parameters per tool per request (item 7)

Closes #712

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 07:06:27 -08:00