Commit graph

592 commits

Author SHA1 Message Date
Chummy
bc0be9a3c1 fix(linq): accept prefixed and uppercase webhook signatures 2026-02-19 14:49:52 +08:00
George McCain
361e750576 feat(channels): add Linq channel for iMessage/RCS/SMS support
The existing iMessage channel relies on AppleScript and only works on macOS.
Linq provides a REST API for iMessage, RCS, and SMS — this gives ZeroClaw
native iMessage support on any platform via webhooks.

Implements LinqChannel following the same patterns as WhatsAppChannel:
- Channel trait impl (send, listen, health_check, typing indicators)
- Webhook handler with HMAC-SHA256 signature verification
- Sender allowlist filtering
- Onboarding wizard step with connection testing
- 18 unit tests covering parsing, auth, and signature verification

Resolves #656 — the prior issue was closed without a merged PR, so this
is the actual implementation.
2026-02-19 14:49:52 +08:00
Chummy
cf476a81c1 fix(provider): preserve native Ollama tool history structure 2026-02-19 14:32:43 +08:00
reidliu41
cd59dc65c4 fix(provider): enable native tool calling for OllamaProvider 2026-02-19 14:32:43 +08:00
Chummy
d548caa5f3 fix(channel): clamp configurable timeout to minimum 30s 2026-02-19 14:19:49 +08:00
ZeroClaw Contributor
41a6ed30dd feat(channel): make message timeout configurable via channels_config.message_timeout_secs
Add configurable timeout for processing channel messages (LLM + tools).
Default: 300s (optimized for on-device LLMs like Ollama).
Can be overridden in config.toml:

[channels_config]
message_timeout_secs = 600
2026-02-19 14:19:49 +08:00
wonder_land
4ecaf6070c fix(tools): remove non-string enum from pushover priority for Gemini compat
The pushover tool priority parameter schema used integer enum values
[-2, -1, 0, 1, 2]. OpenAI-compatible APIs accept this, but the Gemini
API (and Gemini-relay proxies) strictly require all enum values to be
strings, rejecting the request with 400 Bad Request.

This causes every agent turn to fail with a non_retryable error when
using Gemini models, regardless of user message content, because tool
schemas are included in every request.

Fix: remove the enum constraint, keeping integer type and description
documenting the valid range. This is valid for both OpenAI and Gemini
providers and requires no changes to execute() which already uses
as_i64() with range validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 13:24:23 +08:00
Alex Gorevski
52dc9fd9e9
Merge pull request #883 from agorevski/fix/cleartext-logging-sensitive-data
fix(security): prevent cleartext logging of sensitive data
2026-02-18 21:11:31 -08:00
Alex Gorevski
bbbcd06cca
Merge pull request #882 from agorevski/fix/hardcoded-crypto-test-values-v2
fix(security): replace hard-coded crypto test values with runtime-generate secrets
2026-02-18 21:11:23 -08:00
Alex Gorevski
4a9fc9b6cc fix(security): prevent cleartext logging of sensitive data
Address CodeQL rust/cleartext-logging alerts by breaking data-flow taint
chains from sensitive variables (api_key, credential, session_id, user_id)
to log/print sinks. Changes include:

- Replace tainted profile IDs in println! with untainted local variables
- Add redact() helper for safe logging of sensitive values
- Redact account identifiers in auth status output
- Rename session_id locals in memory backends to break name-based taint
- Rename user_id/user_id_hint in channels to break name-based taint
- Custom Debug impl for ComputerUseConfig to redact api_key field
- Break taint chain in provider credential factory via string reconstruction
- Remove client IP from gateway rate-limit log messages
- Break taint on auth token extraction and wizard credential flow
- Rename composio account ref variable to break name-based taint

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 20:12:45 -08:00
Alex Gorevski
9a784954f6 fix(security): replace hard-coded crypto test values with runtime-generated secrets
Replace hard-coded string literals used as cryptographic keys/secrets in
gateway webhook and WhatsApp signature verification tests with runtime-
generated random values. This resolves CodeQL rust/hard-coded-cryptographic-value
alerts while maintaining identical test coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 20:03:38 -08:00
Alex Gorevski
925a352454 fix(security): enforce HTTPS for sensitive data transmission
Add URL scheme validation before HTTP requests that transmit sensitive
data (account IDs, phone numbers, user IDs). All endpoints already use
HTTPS URLs, but this explicit check satisfies CodeQL rust/cleartext-
transmission analysis and prevents future regressions if URLs are
changed.

Affected files: composio.rs, whatsapp.rs, qq.rs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 20:03:02 -08:00
Chummy
8f7d879fd5 feat(onboard): add and harden Lark/Feishu wizard support
- add interactive Lark/Feishu setup in onboarding
- validate credentials with timeouts and clearer diagnostics
- add webhook/allowlist safety warnings for insecure defaults
- document interactive onboarding workflow in channels reference

Co-authored-by: HalcyonAzure <53591299+HalcyonAzure@users.noreply.github.com>
2026-02-19 10:37:47 +08:00
Chummy
606f2860a0 fix(matrix): send markdown replies and improve e2ee diagnostics
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.
2026-02-19 10:23:10 +08:00
Alex Gorevski
7f03ab77a9 test: add systematic test coverage for 7 bug pattern groups (#852)
Add ~105 test cases across 7 test groups identified in issue #852:

TG1 - Provider resolution (27 tests): Factory resolution, alias mapping,
      custom URLs, auth styles, credential wiring
TG2 - Config persistence (18 tests): Config defaults, TOML roundtrip,
      agent/memory config, workspace dirs
TG3 - Channel routing (14 tests): ChannelMessage identity contracts,
      SendMessage construction, Channel trait send/listen roundtrip
TG4 - Agent loop robustness (12 integration + 14 inline tests): Malformed
      tool calls, failing tools, iteration limits, empty responses, unicode
TG5 - Memory restart (14 tests): Dedup on same key, restart persistence,
      session scoping, recall, concurrent stores, categories
TG6 - Channel message splitting (8+8 inline tests): Code blocks at boundary,
      long words, emoji, CJK chars, whitespace edge cases
TG7 - Provider schema (21 tests): ChatMessage/ToolCall/ChatResponse
      serialization, tool_call_id preservation, auth style variants

Also fixes a bug in split_message_for_telegram() where byte-based indexing
could panic on multi-byte characters (emoji, CJK). Now uses char_indices()
consistent with the Discord split implementation.

Closes #852

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 15:28:34 -08:00
Youhana Sheriff
b43e9eb325 fix(provider): polish kimi-code wiring and onboarding parity 2026-02-19 01:15:02 +08:00
Youhana Sheriff
cb91a2f914 feat(provider): add dedicated kimi-code provider support 2026-02-19 01:15:02 +08:00
Chummy
e8e9c0ea6c Revert "feat(provider): add dedicated kimi-code provider support"
This reverts commit 88dcd17a30.
2026-02-19 01:15:02 +08:00
Chummy
5563b755dc Revert "fix(provider): polish kimi-code wiring and onboarding parity"
This reverts commit 0b66ed026c.
2026-02-19 01:15:02 +08:00
Chummy
dea5dcad36 fix(onboard): refine nvidia nim onboarding catalogs and docs 2026-02-18 23:13:18 +08:00
Chummy
e1aeabdb5f fix(providers): align compatible chat client and response test 2026-02-18 22:50:02 +08:00
Chummy
b4b379e3e7 fix(providers): harden tool fallback and refresh model catalogs 2026-02-18 22:50:02 +08:00
Chummy
43494f8331 fix(observability): remove duplicate no-op observer event arms 2026-02-18 22:47:22 +08:00
Chummy
18b6ea1e79 feat(matrix): enable e2ee flow and add channel operations docs 2026-02-18 22:45:11 +08:00
Chummy
e6029e8cec
test(channels): guard max_tool_iterations wiring for channel runtime (#817)
* test(channels): add regression coverage for configured tool iteration limits

* chore(ci): refresh checks after first-interaction workflow fix

* test(channels): reconcile merged runtime-route and iteration tests
2026-02-18 22:40:22 +08:00
Chummy
0bd2fbba2a feat(providers): add MiniMax OAuth credential flow 2026-02-18 22:31:20 +08:00
Chummy
8988a069a6 feat(channels): add runtime provider/model switching for telegram and discord 2026-02-18 22:23:13 +08:00
Chummy
0b66ed026c fix(provider): polish kimi-code wiring and onboarding parity 2026-02-18 22:22:10 +08:00
Chummy
88dcd17a30 feat(provider): add dedicated kimi-code provider support 2026-02-18 22:22:10 +08:00
Chummy
ce104bed45 feat(proxy): add scoped proxy configuration and docs runbooks
- 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
2026-02-18 22:10:42 +08:00
Chummy
13ee9e6398 test: cover deterministic HashMap ordering paths 2026-02-18 21:55:40 +08:00
Syeda Anshrah Gillani
58bb9fa9a7 refactor: sort HashMap keys for deterministic output in identity and doctor 2026-02-18 21:55:40 +08:00
Chummy
58acf1efd3 fix(provider): surface actionable custom-provider failure diagnostics 2026-02-18 21:50:14 +08:00
Chummy
fed8ba21b8 fix(mattermost): handle mention boundary scanning correctly 2026-02-18 21:25:28 +08:00
Vernon Stinebaker
d97866a640 feat(mattermost): add mention_only config for @-mention filtering
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
2026-02-18 21:25:28 +08:00
xj
65a12dd611 fix: resolve all clippy warnings and fix test compilation errors
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>
2026-02-18 21:06:54 +08:00
Lucien Loiseau
6062888d1b feat(providers): add OVHcloud AI Endpoints as native provider
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
2026-02-18 20:54:49 +08:00
Chummy
50fd5b81e1 fix(test): stabilize cron output capture and clippy cleanups 2026-02-18 20:29:26 +08:00
Chummy
483acccdb7 feat(memory): add configurable postgres storage backend 2026-02-18 20:29:26 +08:00
Chummy
e10d359cf9 fix(email): preserve legacy poll_interval alias and avoid lock across await 2026-02-18 20:18:39 +08:00
Kieran
b3d5284be1 refactor(channel): remove dead poll_interval_secs from EmailConfig
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.
2026-02-18 20:18:39 +08:00
Kieran
5d9e8705ac refactor(channel): replace hand-rolled IMAP with async-imap IDLE
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.
2026-02-18 20:18:39 +08:00
Chummy
cad7fb8f22 fix(channels): enforce reply_target naming consistency 2026-02-18 19:56:31 +08:00
Chummy
cfa7215688 fix(telegram): harden mention-only matching and retry cache 2026-02-18 19:51:42 +08:00
ZeroClaw Contributor
c0a80ad656 feat(channel): add mention_only option for Telegram groups
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)
2026-02-18 19:51:42 +08:00
xj
3b75c6cc42 fix(channel): remove HEARTBEAT.md from channel system prompt
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.
2026-02-18 19:36:46 +08:00
Chummy
c70d9b181d test: stabilize cron shell output capture and gemini warmup noop 2026-02-18 19:26:07 +08:00
Chummy
ecad19d512 fix(identity): normalize canonical AIEOS schema payloads 2026-02-18 19:25:12 +08:00
Vernon Stinebaker
3b0133596c feat(providers): add native tool calling for OpenAI-compatible providers
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.
2026-02-18 18:06:36 +08:00
Chummy
5e800c38f1 fix(channel): cancel and join scoped typing task safely 2026-02-18 18:01:29 +08:00