Commit graph

954 commits

Author SHA1 Message Date
Edvard Schøyen
f35a365d83
fix(agent): implement actual concurrent tool execution (#1001)
When parallel_tools is enabled, both code branches in execute_tools()
ran the same sequential for loop. The parallel path was a no-op.

Use futures::future::join_all to execute tool calls concurrently when
parallel_tools is true. The futures crate is already a dependency.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 05:05:33 -05:00
Edvard Schøyen
2ae12578f0
fix(channel): use per-recipient typing handles in Discord (#1005)
Replace the single shared typing_handle with a HashMap keyed by
recipient channel ID. Previously, concurrent messages would fight
over one handle — starting typing for message B would cancel message
A's indicator, and stopping one would kill the other's.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 05:02:39 -05:00
Edvard Schøyen
e2c507664c
fix(provider): surface API key rotation as ineffective warning (#1000)
rotate_key() selects the next key in the round-robin but never applies
it to the underlying provider (Provider trait has no set_api_key
method). The previous info-level log implied rotation was working.

Change to warn-level and explicitly state the key is not applied,
making the limitation visible to operators instead of silently
pretending rotation works.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 05:00:26 -05:00
Alex Gorevski
1a3be5e54f
fix(config): change web_search.enabled default to false for explicit opt-in (#986)
Network access (web search via DuckDuckGo) should require explicit user
consent rather than being enabled by default. This aligns with the
least-surprise principle and the project's secure-by-default policy:
users must opt in to external network requests.

Changes:
- WebSearchConfig::default() now sets enabled: false
- Serde default for enabled field changed from default_true to default
  (bool defaults to false)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-20 04:58:19 -05:00
Jayson Reis
75772cc3a7
chore: Fix pull request template's merge conflict (#892) 2026-02-20 04:57:29 -05:00
dependabot[bot]
b76c757400
chore(deps): bump criterion from 0.5.1 to 0.8.2 (#1070)
Bumps [criterion](https://github.com/criterion-rs/criterion.rs) from 0.5.1 to 0.8.2.
- [Release notes](https://github.com/criterion-rs/criterion.rs/releases)
- [Changelog](https://github.com/criterion-rs/criterion.rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/criterion-rs/criterion.rs/compare/0.5.1...criterion-v0.8.2)

---
updated-dependencies:
- dependency-name: criterion
  dependency-version: 0.8.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 04:51:09 -05:00
dependabot[bot]
7875a08100
chore(deps): bump directories from 5.0.1 to 6.0.0 (#1069)
Bumps [directories](https://github.com/soc/directories-rs) from 5.0.1 to 6.0.0.
- [Commits](https://github.com/soc/directories-rs/commits)

---
updated-dependencies:
- dependency-name: directories
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 04:51:06 -05:00
dependabot[bot]
d82350d847
chore(deps): bump the rust-all group with 3 updates (#1068)
Bumps the rust-all group with 3 updates: [clap](https://github.com/clap-rs/clap), [anyhow](https://github.com/dtolnay/anyhow) and [nusb](https://github.com/kevinmehall/nusb).


Updates `clap` from 4.5.58 to 4.5.60
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.58...clap_complete-v4.5.60)

Updates `anyhow` from 1.0.101 to 1.0.102
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.101...1.0.102)

Updates `nusb` from 0.2.1 to 0.2.2
- [Release notes](https://github.com/kevinmehall/nusb/releases)
- [Commits](https://github.com/kevinmehall/nusb/compare/v0.2.1...v0.2.2)

---
updated-dependencies:
- dependency-name: clap
  dependency-version: 4.5.60
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-all
- dependency-name: anyhow
  dependency-version: 1.0.102
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-all
- dependency-name: nusb
  dependency-version: 0.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 04:51:03 -05:00
dependabot[bot]
12fd87623a
chore(deps): bump sigstore/cosign-installer from 3.8.2 to 4.0.0 (#1067)
Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.8.2 to 4.0.0.
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](3454372f43...faadad0cce)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-20 04:39:29 -05:00
Will Sarg
c96ea79ac0
feat(installer): add guided zeroclaw installer and distro hardening (#887)
* feat(installer): add guided zeroclaw installer entrypoint

- add top-level POSIX wrapper (zeroclaw_install.sh) that ensures bash is present

- route bootstrap/install compatibility scripts through the new installer entrypoint

- improve Linux dependency handling for Alpine/Fedora/Arch, including pacman container fallback

* fix(ci): resolve dependabot config conflict and run daily

- remove duplicate docker ecosystem entry with overlapping directory/target-branch

- switch cargo, github-actions, and docker schedules from monthly to daily
2026-02-20 04:34:14 -05:00
Chummy
a2e9c0d1e1 fix(skills): make open-skills sync opt-in and configurable 2026-02-20 16:45:50 +08:00
Chummy
d0674c4b98 fix(channels): harden whatsapp web mode and document dual backend 2026-02-20 16:45:16 +08:00
Chummy
70f12e5df9 test(onboard): add regression coverage for quick setup model override 2026-02-20 16:22:03 +08:00
Chummy
bbaf55eb3b fix(config): harden sync_directory async signature across platforms 2026-02-20 16:21:47 +08:00
Chummy
654f822430 fix(memory): avoid tokio runtime panic when initializing postgres backend 2026-02-20 16:21:25 +08:00
Chummy
7c2c370180 fix(channel): preserve interrupted user context in cached turn normalization 2026-02-20 16:21:24 +08:00
Chummy
e7ccb573fa fix(observability): prevent otel reactor panic in non-tokio contexts 2026-02-20 16:07:50 +08:00
xj
2d6205ee58 fix(channel): use native tool calling to preserve conversation context
AnthropicProvider declared supports_native_tools() = true but did not
override chat_with_tools(). The default trait implementation drops all
conversation history (sends only system + last user message), breaking
multi-turn conversations on Telegram and other channels.

Changes:
- Override chat_with_tools() in AnthropicProvider: converts OpenAI-format
  tool JSON to ToolSpec and delegates to chat() which preserves full
  message history
- Skip build_tool_instructions() XML protocol when provider supports
  native tools (saves ~12k chars in system prompt)
- Remove duplicate Tool Use Protocol section from build_system_prompt()
  for native-tool providers
- Update Your Task section to encourage conversational follow-ups
  instead of XML tool_call tags when using native tools
- Add tracing::warn for malformed tool definitions in chat_with_tools
2026-02-20 13:58:27 +08:00
xj
8c826e581c fix(channel): store raw user message and skip memory recall with history
Two fixes for conversation history quality:

1. Store raw msg.content in ConversationHistoryMap instead of
   enriched_message — memory context is ephemeral per-request and
   pollutes future turns when persisted.

2. Skip memory recall when conversation history exists — prior turns
   already provide context. Memory recall adds noise and can mislead
   the model (e.g. old 'seen' entries overshadowing a code variable
   named seen in the current conversation).
2026-02-20 13:58:27 +08:00
Chummy
8cafeb02e8
fix(composio): request latest v3 tool versions by default (#1039) 2026-02-19 23:29:09 -05:00
Chummy
f274fd5757
fix(channel): prevent false timeout during multi-turn tool loops (#1037) 2026-02-19 23:28:05 -05:00
Chummy
178bb108da
fix(gemini): correct Gemini CLI OAuth cloudcode payload/response handling (#1040)
* fix(gemini): align OAuth cloudcode payload and response parsing

* docs(gemini): document OAuth vs API key endpoint behavior
2026-02-19 23:27:00 -05:00
Chummy
db2d9acd22
fix(skills): support SSH git remotes for skills install (#1035) 2026-02-19 23:25:47 -05:00
Chummy
f10bb998e0
fix(build): unblock low-resource installs and release binaries (#1041)
* fix(build): unblock low-resource installs and release binaries

* fix(ci): use supported intel macOS runner label
2026-02-19 23:24:43 -05:00
Chummy
5c1d6fcba6 fix(channel): align runtime defaults with current model id and test context 2026-02-20 11:05:41 +08:00
Chummy
740eb17d76 fix(channel): hot-apply runtime config updates for running channel service 2026-02-20 11:05:41 +08:00
Chummy
95ec5922d1 fix(channel): robust tool context summary extraction 2026-02-20 10:59:18 +08:00
Edvard
61530520b3 fix(channel): preserve tool context in conversation history
After run_tool_call_loop, only the final text response was saved to
per-sender conversation history. All intermediate tool calls and results
were discarded, so on the next turn the LLM had no awareness of what
tools it used or what it discovered — causing poor follow-up ability.

Record the history length before the tool loop, then scan new messages
for tool names after it completes. Prepend a compact [Used tools: ...]
annotation to the assistant message saved in history, giving the LLM
context about its own actions on subsequent turns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:59:18 +08:00
Chummy
b2c5d611be fix(channel): preserve memory enrichment for current call while storing raw user turn 2026-02-20 10:48:18 +08:00
Edvard
6cbdef8c16 fix(channel): save original user text to conversation history
Previously, the memory-enriched message (with [Memory context] block
prepended) was saved to per-sender conversation history. On subsequent
turns the LLM saw stale memory fragments with raw keys baked into
prior "user" messages, creating compounding noise.

Save the original msg.content instead. Memory context is still injected
for the current LLM call but no longer persists across turns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:48:18 +08:00
Edvard
ea2ff7c53b fix(memory): add minimum-length filter for auto-save messages
Every user message was auto-saved to memory regardless of length,
flooding the store with trivial entries like "ok", "thanks", "hi".
These noise entries competed with real memories during recall, degrading
relevance — especially with keyword-only search.

Skip auto-saving messages shorter than 20 characters. Applied to both
the channel path (channels/mod.rs) and CLI agent path (agent/loop_.rs).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:26:31 +08:00
Chummy
63a59e3735 test(channels): assert single tool protocol block in final prompt 2026-02-20 10:25:48 +08:00
Edvard
35a3520621 fix(channel): remove duplicated tool protocol from system prompt
build_system_prompt() included a "## Tool Use Protocol" section with
the tag format and usage instructions. build_tool_instructions() then
appended another identical "## Tool Use Protocol" section with full
JSON schemas. This wasted ~1-2K tokens on every API call.

Remove the duplicate protocol block from build_system_prompt(), keeping
only the compact tool name/description list. The complete protocol with
schemas is provided by build_tool_instructions().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:25:48 +08:00
Edvard
3a8a1754ef fix(channel): replace hardcoded Discord bot text with generic channel text
The Channel Capabilities section in build_system_prompt() was hardcoded
to say "You are running as a Discord bot" for ALL channels, including
Telegram. This caused the LLM to misidentify itself and reference
Discord-specific features regardless of the actual channel.

Replace with generic "messaging bot" text. Per-channel delivery
instructions already exist via channel_delivery_instructions().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:25:07 +08:00
Ken Simpson
e0ca73336a feat(bootstrap): add docker onboarding bootstrap mode 2026-02-20 10:20:18 +08:00
Ken Simpson
2fc0504545 chore(dev): auto-load env and hide compose secrets 2026-02-20 10:20:18 +08:00
Alex Gorevski
9de77df235
Merge pull request #1020 from zeroclaw-labs/fix/code-scanning-alerts
fix(security): address CodeQL code-scanning alerts
2026-02-19 16:36:29 -08:00
Alex Gorevski
36f971a3d0 fix(security): address CodeQL code-scanning alerts
- Extract hard-coded test vector keys into named constants in bedrock.rs
  and linq.rs to resolve rust/hard-coded-cryptographic-value alerts
- Replace derived Debug impls with manual impls that redact sensitive
  fields (access_token, refresh_token, credential, api_key) on
  QwenOauthCredentials, QwenOauthProviderContext, and
  ResolvedEmbeddingConfig to resolve rust/cleartext-logging alerts
- Redact Matrix user_id and device_id hints in tracing::warn! diagnostic
  messages via crate::security::redact() to resolve cleartext-logging
  alert in matrix.rs

Addresses CodeQL alerts: #77, #95-106

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 16:31:03 -08:00
Alex Gorevski
0f69464a1f
Merge pull request #1018 from zeroclaw-labs/test/fuzz-target-expansion
test(fuzz): add webhook, provider response, and command validation fuzz targets
2026-02-19 16:17:14 -08:00
Alex Gorevski
7d945aea6a
Merge pull request #1017 from zeroclaw-labs/test/peripherals-unit-tests
test(peripherals): add unit tests for peripheral module configuration and listing
2026-02-19 16:17:07 -08:00
Alex Gorevski
9d0ff54037
Merge pull request #1016 from zeroclaw-labs/test/improve-test-assertions
test(quality): replace bare .unwrap() with .expect() in agent and shell tests
2026-02-19 16:16:42 -08:00
Alex Gorevski
1708243470
Merge pull request #1015 from zeroclaw-labs/test/gateway-idempotency-tests
test(gateway): add edge-case idempotency store tests
2026-02-19 16:16:28 -08:00
Alex Gorevski
2a106d051a
Merge pull request #1013 from zeroclaw-labs/fix/docs-inline-code-comments
docs(code): add decision-point comments to agent loop, security policy, and reliable provider
2026-02-19 16:01:19 -08:00
Alex Gorevski
88a036304d
Merge pull request #1012 from zeroclaw-labs/fix/docs-collection-indexes
docs: enhance getting-started, hardware, and project collection indexes
2026-02-19 16:00:56 -08:00
Alex Gorevski
7d7362439e
Merge pull request #1011 from zeroclaw-labs/fix/docs-config-struct-fields
docs(code): add comprehensive doc comments to config schema public fields
2026-02-19 16:00:34 -08:00
Alex Gorevski
200ce0d6fd
Merge pull request #1010 from zeroclaw-labs/fix/docs-trait-doc-comments
docs(code): expand doc comments on security, observability, runtime, and peripheral traits
2026-02-19 15:59:56 -08:00
Alex Gorevski
9f93b8ef89
Merge pull request #1009 from zeroclaw-labs/fix/docs-multilingual-readme-parity
docs: add architecture, subscription auth, and memory system sections to multilingual READMEs
2026-02-19 15:59:25 -08:00
Alex Gorevski
c6de02b93b
Merge pull request #1008 from zeroclaw-labs/fix/docs-module-level-docs
docs(code): add module-level doc blocks to providers, channels, tools, and security
2026-02-19 15:58:56 -08:00
Argenis
96d5ae0c43
fix(composio): pick first usable account when multiple exist, add connected_accounts alias (#1003)
Root cause of #959: resolve_connected_account_ref returned None when the entity had more than one connected account for an app, silently dropping auto-resolve and causing every execute call to fail with 'cannot find connected account'. The LLM then looped re-issuing the OAuth URL even though the account was already connected.

- resolve_connected_account_ref now picks the first usable account (ordered by updated_at DESC from the API) instead of returning None when multiple accounts exist
- Add 'connected_accounts' as a dispatch alias for 'list_accounts' in handler, schema enum, and description
- 8 new regression tests

Closes #959
2026-02-19 17:19:04 -05:00
Alex Gorevski
867a7a5cbd test(gateway): add edge-case idempotency store tests
Add five new idempotency store tests covering: different-key acceptance,
max_keys clamping to minimum of 1, rapid duplicate rejection, TTL-based
key expiry and re-acceptance, and eviction preserving newest entries.
Addresses audit finding on weak gateway idempotency test coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 13:28:24 -08:00