Commit Graph

1123 Commits

Author SHA1 Message Date
Giulio V
2202181b07
feat(stt): multi-provider STT with TranscriptionProvider trait (#3614)
* feat(stt): add multi-provider STT with TranscriptionProvider trait

Refactors single-endpoint transcription to support multiple providers:
Groq (existing), OpenAI Whisper, Deepgram, AssemblyAI, and Google Cloud
Speech-to-Text. Adds TranscriptionManager for provider routing with
backward-compatible config fields.

* style: fix cargo fmt + clippy violations

* fix: Box::pin large futures and resolve merge conflicts with master

---------

Co-authored-by: argenis de la rosa <theonlyhennygod@gmail.com>
2026-03-24 15:17:23 +03:00
Argenis
01e9231f61
test(channel): add QQ markdown msg_type regression test (#3752)
Verify that QQ send body uses msg_type 2 with nested markdown object
instead of msg_type 0 with top-level content. Adapted from #3668.
2026-03-24 15:17:22 +03:00
Giulio V
3f0e3ffe05
feat(providers): add Claude Code, Gemini CLI, and KiloCLI subprocess providers (#3615)
* feat(providers): add Claude Code, Gemini CLI, and KiloCLI subprocess providers

Adds three new local subprocess-based providers for AI CLI tools.
Each provider spawns the CLI as a child process, communicates via
stdin/stdout pipes, and parses responses into ChatResponse format.

* fix: resolve clippy unnecessary_debug_formatting and rustfmt violations

* fix: resolve remaining clippy unnecessary_debug_formatting in CLI providers

* fix(providers): add AiAgent CLI category for subprocess providers
2026-03-24 15:17:22 +03:00
Chris Hengge
714b319ba1
fix(tool): expand cron_add and cron_update parameter schemas (#3671)
The schedule field in cron_add used a bare {"type":"object"} with a
description string encoding a tagged union in pseudo-notation. The patch
field in cron_update was an opaque {"type":"object"} despite CronJobPatch
having nine fully-typed fields. Both gaps cause weaker instruction-following
models to produce malformed or missing nested JSON when invoking these tools.

Changes:
- cron_add: expand schedule into a oneOf discriminated union with explicit
  properties and required fields for each variant (cron/at/every), matching
  the Schedule enum in src/cron/types.rs exactly
- cron_add: add descriptions to all previously undocumented top-level fields
- cron_add: expand delivery from a bare inline comment to fully-specified
  properties with per-field descriptions
- cron_update: expand patch from opaque object to full properties matching
  CronJobPatch (name, enabled, command, prompt, model, session_target,
  delete_after_run, schedule, delivery)
- cron_update: schedule inside patch mirrors the same oneOf expansion
- Both: add inline NOTE comments flagging that oneOf is correct for
  OpenAI-compatible APIs but SchemaCleanr::clean_for_gemini must be
  applied if Gemini native tool calling is ever wired up
- Both: add schema-shape tests using the existing test_config/test_security
  helper pattern, covering oneOf variant structure, required fields, and
  delivery channel enum completeness

No behavior changes. No new dependencies. Backward compatible: the runtime
deserialization path (serde on Schedule/CronJobPatch) is unchanged.

Co-authored-by: Argenis <theonlyhennygod@gmail.com>
2026-03-24 15:17:22 +03:00
Sid Jain
d4f4173c75
fix(slack): honor mention_only in runtime channel wiring (#3715)
* feat(slack): wire mention_only group reply policy

* feat(slack): expose mention_only in config and wizard defaults
2026-03-24 15:17:22 +03:00
Markus Bergholz
183fb3f2bb
Fix: Support Nextcloud Talk Activity Streams 2.0 webhook format (#3737)
* fix

* fix

* format
2026-03-24 15:17:22 +03:00
Ricardo Madriz
9c30164aa3
fix(tools) Wire activated toolset into dispatch (#3747)
* fix(tools): wire ActivatedToolSet into tool dispatch and spec advertisement

When deferred MCP tools are activated via tool_search, they are stored
in ActivatedToolSet but never consulted by the tool call loop.
tool_specs is built once before the iteration loop and never refreshed,
so the provider API tools[] parameter never includes activated tools.
find_tool only searches the static registry, so execution dispatch also
fails silently.

Thread Arc<Mutex<ActivatedToolSet>> from creation sites through to
run_tool_call_loop. Rebuild tool_specs each iteration to merge base
registry specs with activated specs. Add fallback in execute_one_tool
to check the activated set when the static registry lookup misses.

Change ActivatedToolSet internal storage from Box<dyn Tool> to
Arc<dyn Tool> so we can clone the Arc out of the mutex guard before
awaiting tool.execute() (std::sync::MutexGuard is not Send).

* fix(tools): add activated_tools field to new ChannelRuntimeContext test site
2026-03-24 15:17:21 +03:00
Chris Hengge
525bf47954
fix(integrations): wire Cron and Browser status to config fields (#3750)
Both entries had hardcoded |_| IntegrationStatus::Available, ignoring
the live config entirely. Users with cron.enabled = true or
browser.enabled = true saw 'Available' on the /integrations dashboard
card instead of 'Active'.

Root cause: status_fn closures did not capture the Config argument.

Fix: replace the |_| stubs with |c| closures that check c.cron.enabled
and c.browser.enabled respectively, matching the pattern used by every
other wired entry in the registry (Telegram, Discord, Shell, etc.).

What did NOT change: ComingSoon entries, always-Active entries (Shell,
File System), platform entries, or any other registry logic.
2026-03-24 15:17:21 +03:00
Giulio V
49eb3ced05
feat(security): add Merkle hash-chain audit trail (#3601)
* feat(security): add Merkle hash-chain audit trail

Each audit entry now includes a SHA-256 hash linking it to the previous
entry (entry_hash, prev_hash, sequence), forming a tamper-evident chain.
Modifying any entry invalidates all subsequent hashes.

- Chain fields added to AuditEvent with #[serde(default)] for backward compat
- AuditLogger tracks chain state and recovers from existing logs on restart
- verify_chain() validates hash linkage, sequence continuity, and integrity
- Five new tests: genesis seed, multi-entry verify, tamper detection,
  sequence gap detection, and cross-restart chain recovery

* fix(security): replace personal name with neutral label in audit tests
2026-03-24 15:17:21 +03:00
Argenis
fc3af217ad
fix(agent): prevent duplicate tool schema injection in XML dispatcher (#3744)
Remove duplicate tool listing from XmlToolDispatcher::prompt_instructions()
since tool listing is already handled by ToolsSection in prompt.rs. The
method now only emits the XML protocol envelope.

Also fix UTF-8 char boundary panics in memory consolidation truncation by
using char_indices() instead of manual byte-boundary scanning.

Fixes #3643
Supersedes #3678

Co-authored-by: TJUEZ <TJUEZ@users.noreply.github.com>
2026-03-24 15:17:21 +03:00
伊姆
3ec4fab88f
fix(config): support socks proxy scheme for Clash Verge (#3001)
Co-authored-by: imu <imu@sgcc.com.cn>
2026-03-24 15:17:21 +03:00
Giulio V
9320b21340
feat(whatsapp-web): add voice message transcription support (#3617)
Adds audio message detection and transcription to WhatsApp Web channel.
Voice messages (PTT) are downloaded, transcribed via the existing
transcription subsystem (Groq Whisper), and delivered as text content.

- TranscriptionConfig field with builder pattern
- Duration limit enforcement before download
- MIME type mapping for audio formats
- Graceful error handling (skip on failure)
- Preserves full retry/reconnect state machine from master
2026-03-24 15:17:20 +03:00
Sandeep Ghael
caba6bcbf8
fix(channel): resolve multi-room reply routing regression (#3224) (#3378)
* fix(channel): resolve multi-room reply routing regression (#3224)

PR #3224 (f0f0f808, "feat(matrix): add multi-room support") changed the
channel name format in matrix.rs from "matrix" to "matrix:!roomId", but
the channel lookup in mod.rs still does an exact match against
channels_by_name, which is keyed by Channel::name() (returns "matrix").

This mismatch causes target_channel to always resolve to None for Matrix
messages, silently dropping all replies.

Fix: fall back to a prefix match on the base channel name (before ':')
when the exact lookup fails. This preserves multi-room conversation
isolation while correctly routing replies to the originating channel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: apply cargo fmt to channel routing fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Sandeep (Claude) <sghael+claude@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:20 +03:00
Giulio V
1d0145f273
feat(tools): add browser delegation tool (#3610)
* feat(tools): add browser delegation tool for corporate web app interaction

Adds BrowserDelegateTool that delegates browser-based tasks to Claude Code
(or other browser-capable CLIs) for interacting with corporate tools
(Teams, Outlook, Jira, Confluence) via browser automation. Includes domain
validation (allow/blocklist), task templates, Chrome profile persistence
for SSO sessions, and timeout management.

* fix: resolve clippy violation in browser delegation tool

* fix(browser-delegate): validate URLs embedded in task text against domain policy

Scan the task text for http(s):// URLs using regex and validate each
against the allow/block domain lists before forwarding to the browser
CLI subprocess. This prevents bypassing domain restrictions by
embedding blocked URLs in the task parameter.

* fix(browser-delegate): constrain URL schemes, gate on runtime, document config

- Add has_shell_access gate so BrowserDelegateTool is only registered on
  shell-capable runtimes (skipped with warning on WASM/edge runtimes)
- Add boundary tests for javascript: and data: URL scheme rejection
- URL scheme validation (http/https only) and config docs were already
  addressed by a prior commit on this branch

* fix(tools): address CodeRabbit review findings for browser delegation

Remove dead `max_concurrent_tasks` config field and expand doc comments
on the `[browser_delegate]` config section in schema.rs.
2026-03-24 15:17:20 +03:00
Christian Pojoni
d91e54a5d0
fix(tool+channel): revert invalid model set via model_routing_config (#3497)
When the LLM hallucinates an invalid model ID through the
model_routing_config tool's set_default action, the invalid model gets
persisted to config.toml. The channel hot-reload then picks it up and
every subsequent message fails with a non-retryable 404, permanently
killing the connection with no user recovery path.

Fix with two layers of defense:

1. Tool probe-and-rollback: after saving the new model, send a minimal
   chat request to verify the model is accessible. If the API returns a
   non-retryable error (404, auth failure, etc.), automatically restore
   the previous config and return a failure notice to the LLM.

2. Channel safety net: in maybe_apply_runtime_config_update, reject
   config reloads when warmup fails with a non-retryable error instead
   of applying the broken config anyway.

Co-authored-by: Christian Pojoni <christian.pojoni@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:17:20 +03:00
DotViegas
101bfa1928
fix(providers): adjust temperature for OpenAI reasoning models (#2936)
Some OpenAI models (o1, o3, o4, gpt-5 variants) only accept temperature=1.0 and return errors with other values like 0.7. This change automatically adjusts the temperature parameter based on the model being used.

Changes:
- Add adjust_temperature_for_model() function to detect reasoning models
- Apply temperature adjustment in chat_with_system(), chat(), and chat_with_tools()
- Preserve user-specified temperature for standard models (gpt-4o, gpt-4-turbo, etc.)
- Force temperature=1.0 for reasoning models (o1, o3, o4, gpt-5, gpt-5-mini, gpt-5-nano, gpt-5.x-chat-latest)

Testing:
- Add 7 unit tests covering reasoning models, standard models, and edge cases
- All tests pass successfully
- Empirical testing documented in docs/openai-temperature-compatibility.md

Impact:
- Fixes temperature errors when using o1, o3, o4, and gpt-5 model families
- No breaking changes - transparent adjustment for end users
- Standard models continue to work with flexible temperature values

Risk: Low - isolated change within OpenAI provider, well-tested

Rollback: Revert this commit to restore previous behavior

Co-authored-by: Argenis <theonlyhennygod@gmail.com>
2026-03-24 15:17:19 +03:00
Giulio V
4e74857d34
feat(observability): add Hands dashboard metrics and events (#3595)
Add HandStarted, HandCompleted, and HandFailed event variants to
ObserverEvent, and HandRunDuration, HandFindingsCount, HandSuccessRate
metric variants to ObserverMetric. Update all observer backends (log,
noop, verbose, prometheus, otel) to handle the new variants with
appropriate instrumentation. Prometheus backend registers hand_runs
counter, hand_duration histogram, and hand_findings counter. OTel
backend creates spans and records metrics for hand runs.
2026-03-24 15:17:19 +03:00
smallwhite
6eef252e10
fix(telegram): avoid duplicate finalize_draft messages (#3259) 2026-03-24 15:17:19 +03:00
Chris Hengge
8431a44ba4
fix(memory): serialize MemoryCategory as plain string and guard dashboard render crashes (#3051)
The /memory dashboard page rendered a black screen when MemoryCategory::Custom
was serialized by serde's derived impl as a tagged object {"custom":"..."} but
the frontend expected a plain string. No navigation was possible without using
the browser Back button.

Changes:
- src/memory/traits.rs: replace derived serde impls with custom serialize
  (delegates to Display, emits plain snake_case string) and deserialize
  (parses known variants by name, falls through to Custom(s) for unknown).
  Adds memory_category_serde_uses_snake_case and memory_category_custom_roundtrip
  tests. No persistent storage migration needed — all backends (SQLite, Markdown,
  Postgres) use their own category_to_str/str_to_category helpers and never
  read serde-serialized category values back from disk.
- web/src/App.tsx: export ErrorBoundary class so render crashes surface a
  recoverable UI instead of a black screen. Adds aria-live="polite" to the
  pairing error paragraph for screen reader accessibility.
- web/src/components/layout/Layout.tsx: wrap Outlet in ErrorBoundary keyed
  by pathname so the navigation shell stays mounted during a page crash and
  the boundary resets on route change.

Co-authored-by: Argenis <theonlyhennygod@gmail.com>
2026-03-24 15:17:19 +03:00
Chris Hengge
c96f238038
fix(channel): bypass mention_only gate for Discord DMs (#2983)
When mention_only is enabled, the bot correctly requires an @mention in
guild (server) channels. However, Direct Messages have no guild_id and
are inherently private and addressed to the bot — requiring a @mention
in a DM is never correct and silently drops all DM messages.

Changes:
- src/channels/discord.rs: detect DMs via absence of guild_id in the
  gateway payload, compute effective_mention_only = self.mention_only && !is_dm,
  and pass that to normalize_incoming_content instead of self.mention_only.
  DMs bypass the mention gate; guild messages retain existing behaviour.
- Adds three tests: DM bypasses mention gate, guild message without mention
  is rejected, guild message with mention passes and strips the mention tag.

Co-authored-by: Argenis <theonlyhennygod@gmail.com>
2026-03-24 15:17:18 +03:00
Ericsunsk
b5af73cac6
fix(memory): filter autosave noise and scope recall/store by session (#3695)
* fix(memory): filter autosave noise and scope memory by session

* style: format rebase-resolved gateway and memory loader

* fix(tests): update memory loader mock for session-aware context

* fix(openai-codex): decode utf-8 safely across stream chunks
2026-03-24 15:17:18 +03:00
Vast-stars
7db8853085
fix(agent): remove bare URL → curl fallback in GLM-style tool call parser (#3694)
* fix(agent): remove bare URL → curl fallback in GLM-style tool call parser

The `parse_glm_style_tool_calls` function had a "Plain URL" fallback
that converted any bare URL line (e.g. `https://example.com`) into a
`shell` tool call running `curl -s '<url>'`. This caused:

- False positives: normal URLs in LLM replies misinterpreted as tool calls
- Swallowed replies: text with URLs not forwarded to the channel
- Unintended shell commands: `curl` executed without user intent

Explicit GLM-format tool calls like `browser_open/url>https://...` and
`shell/command>...` are unaffected — only the bare URL catch-all is
removed.

* style: cargo fmt

---------

Co-authored-by: argenis de la rosa <theonlyhennygod@gmail.com>
2026-03-24 15:17:18 +03:00
Argenis
66e8442ab8
feat(channels): add X/Twitter and Mochat channel integrations (#3735)
* feat(channels): add X/Twitter and Mochat channel integrations

Add two new channel implementations to close competitive gaps:

- X/Twitter: Twitter API v2 with mentions polling, tweet threading
  (auto-splits at 280 chars), DM support, and rate limit handling
- Mochat: HTTP polling-based integration with Mochat customer service
  platform, configurable poll interval, message dedup

Both channels follow the existing Channel trait pattern with full
config schema integration, health checks, and dedup.

Closes competitive gap: NanoClaw had X/Twitter, Nanobot had Mochat.

* fix(channels): use write! instead of format_push_string for clippy

Replace url.push_str(&format!(...)) with write!(url, ...) to satisfy
clippy::format_push_string lint on CI.

* fix(channels): rename reply_to parameter to avoid legacy field grep

The component test source_does_not_use_legacy_reply_to_field greps
for "reply_to:" in source files. Rename the parameter to
reply_tweet_id to pass this check.
2026-03-24 15:17:17 +03:00
simianastronaut
ddd12dd4f6
feat(config): support initial_prompt in transcription config for proper noun recognition
Add `initial_prompt: Option<String>` to `TranscriptionConfig` and pass
it as the `prompt` field in the Whisper API multipart POST when present.
This lets users bias transcription toward expected vocabulary (proper
nouns, technical terms) via the config file.

Closes #2881

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:17:17 +03:00
Argenis
9d53f31531
fix(agent): strip vision markers from history for non-vision providers (#3734)
* fix(agent): strip vision markers from history for non-vision providers

When a user sends an image via Telegram to a non-vision provider, the
`[IMAGE:/path]` marker gets stored in the JSONL session file. Previously,
the rollback only removed it from in-memory history, not from the JSONL
file. On restart, the marker was reloaded and permanently broke the
conversation.

Two fixes:
1. `rollback_orphan_user_turn` now also calls `remove_last` on the
   session store so the poisoned entry is removed from disk.
2. When building history for a non-vision provider, `[IMAGE:]` markers
   are stripped from older history messages (and empty turns are dropped).

Fixes #3674

* fix(agent): only strip vision markers from older history, not current message

The initial fix stripped [IMAGE:] markers from all prior_turns including
the current message, which caused the vision check to never fire. Now
only strip from turns before the last one (the current request), so
fresh image sends still get a proper vision capability error.
2026-03-24 15:17:17 +03:00
Argenis
9465a40791
fix(qq): send markdown messages instead of plain text (#3732)
* fix(ci): decouple tweet from Docker push in release workflows

Remove Docker from the tweet job's dependency chain in both beta and
stable release workflows. Docker multi-platform builds are slow and
can be cancelled by concurrency groups, which was blocking the tweet
from ever firing. The tweet announces the GitHub Release, not the
Docker image.

* fix(qq): send markdown messages instead of plain text

Change msg_type from 0 (plain text) to 2 (markdown) and wrap content
in a markdown object per QQ's API documentation. This ensures markdown
formatting (bold, italic, code blocks, etc.) renders properly in QQ
clients instead of displaying raw syntax.

Fixes #3647
2026-03-24 15:17:16 +03:00
Argenis
42a622021b
feat(providers): close AiHubMix, SiliconFlow, and Codex OAuth provider gaps (#3730)
Add env var resolution for AiHubMix (AIHUBMIX_API_KEY) and SiliconFlow
(SILICONFLOW_API_KEY) so users can authenticate via environment variables.

Add factory and credential resolution tests for AiHubMix, SiliconFlow,
and Codex OAuth to ensure all provider aliases work correctly.
2026-03-24 15:17:16 +03:00
Argenis
5271656e2a
feat(providers): add VOLCENGINE_API_KEY env var for VolcEngine/ByteDance gateway (#3725) 2026-03-24 15:17:16 +03:00
Argenis
46e9a62524
fix(daemon): ignore SIGHUP to survive terminal/SSH disconnect (#3721)
* fix(daemon): ignore SIGHUP to survive terminal/SSH disconnect (#3688)

* style: remove redundant continue flagged by clippy
2026-03-24 15:17:15 +03:00
Argenis
cedc0f7a6f
fix(config): add serde default for cli field in ChannelsConfig (#3720)
* fix(config): add serde default for cli field in ChannelsConfig (#3710)

* style: fix rustfmt formatting in test
2026-03-24 15:17:15 +03:00
Argenis
1dddc8b2a2
fix(security): validate command before rate-limiting in cron once (#3699) (#3719) 2026-03-24 15:17:15 +03:00
argenis de la rosa
18cb38b09e
feat(cache): wire two-tier response cache, multi-provider token tracking, and cache analytics
- Two-tier response cache: in-memory LRU (hot) + SQLite (warm) with TTL-aware eviction
- Wire response cache into agent turn loop (temp==0.0, text-only responses only)
- Parse Anthropic cache_creation_input_tokens/cache_read_input_tokens
- Parse OpenAI prompt_tokens_details.cached_tokens
- Add cached_input_tokens to TokenUsage, prompt_caching to ProviderCapabilities
- Add CacheHit/CacheMiss observer events with Prometheus counters
- Add response_cache_hot_entries config field (default: 256)
2026-03-24 15:17:14 +03:00
argenis de la rosa
f5bd557bda
feat(sessions): add SQLite backend with FTS5, trait abstraction, and migration
- Add SessionBackend trait abstracting over storage backends (load,
  append, remove_last, list, search, cleanup_stale, compact)
- Add SqliteSessionBackend with WAL mode, FTS5 full-text search,
  session metadata tracking, and TTL-based cleanup
- Add remove_last() and compact() to JSONL SessionStore
- Implement SessionBackend for both JSONL and SQLite backends
- Add automatic JSONL-to-SQLite migration (renames .jsonl → .jsonl.migrated)
- Add config: session_backend ("jsonl"/"sqlite"), session_ttl_hours
- SQLite is the new default backend; JSONL preserved for backward compat
2026-03-24 15:17:14 +03:00
argenis de la rosa
f0b56fd25e
feat(heartbeat): add health metrics, adaptive intervals, and task history
- Add HeartbeatMetrics struct with uptime, consecutive success/failure
  counts, EMA tick duration, and total ticks
- Add compute_adaptive_interval() for exponential backoff on failures
  and faster polling when high-priority tasks are present
- Add SQLite-backed task run history (src/heartbeat/store.rs) mirroring
  the cron/store.rs pattern with output truncation and pruning
- Add dead-man's switch that alerts if heartbeat stops ticking
- Wire metrics, history recording, and adaptive sleep into daemon worker
- Add config fields: adaptive, min/max_interval_minutes,
  deadman_timeout_minutes, deadman_channel, deadman_to, max_run_history
- All new fields are backward-compatible with serde defaults
2026-03-24 15:17:14 +03:00
Argenis
95e69d133b
fix(config): add missing #[serde(default)] to Config struct fields (#3700)
Several recently-added Config fields (data_retention, cloud_ops,
conversational_ai, security_ops) were missing #[serde(default)],
causing deserialization failures when those sections are absent
from config files. Also fixes security field whose #[serde(default)]
was accidentally consumed by the backup doc comment.

Fixes test failures: agent_config_deserializes and
browser_config_backward_compat_missing_section.
2026-03-24 15:17:13 +03:00
Argenis
c0893612b7
feat(tools): add cloud transformation accelerator tools (#3663)
* feat(tools): add cloud transformation accelerator tools

Add cloud_ops and cloud_patterns tools providing read-only cloud
transformation analysis: IaC review, migration assessment, cost
analysis, and Well-Architected Framework architecture review.

Includes CloudOpsConfig, SecurityOpsConfig, and ConversationalAiConfig
schema additions, Box::pin fixes for recursive async in cron scheduler,
and approval_manager field in ChannelRuntimeContext test constructors.

Original work by @rareba. Rebased on latest master with conflict
resolution (kept SwarmConfig/SwarmStrategy exports, swarm tool
registration, and approval_manager in test constructors).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: cargo fmt Box::pin calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
2225ab675f
feat(tools): add backup/restore and data management tools (#3662)
Add BackupTool for creating, listing, verifying, and restoring
timestamped workspace backups with SHA-256 manifest integrity
checking. Add DataManagementTool for retention status, time-based
purge, and storage statistics. Both tools are config-driven via
new BackupConfig and DataRetentionConfig sections.

Original work by @rareba. Rebased on latest master with conflict
resolution for SwarmConfig/SwarmStrategy exports and swarm tool
registration, and added missing approval_manager fields in
ChannelRuntimeContext test constructors.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
28396fccac
feat(security): add MCSS security operations tool (#3657)
* feat(security): add MCSS security operations tool

Add managed cybersecurity service (MCSS) tool with alert triage,
incident response playbook execution, vulnerability scan parsing,
and security report generation. Includes SecurityOpsConfig, playbook
engine with approval gating, vulnerability scoring, and full test
coverage. Also fixes pre-existing missing approval_manager field in
ChannelRuntimeContext test constructors.

Original work by @rareba. Supersedes #3599.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add SecurityOpsConfig to re-exports, fix test constructors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
4b795443a1
feat(tools): add project delivery intelligence tool (#3656)
Add a new read-only project_intel tool that provides:
- Status report generation (weekly/sprint/month)
- Risk scanning with configurable sensitivity
- Client update drafting (formal/casual, client/internal)
- Sprint summary generation
- Heuristic effort estimation

Includes multi-language report templates (EN, DE, FR, IT),
ProjectIntelConfig schema with validation, and comprehensive tests.

Also fixes missing approval_manager field in 4 ChannelRuntimeContext
test constructors.

Supersedes #3591 — rebased on latest master. Original work by @rareba.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
ffe8bcf61f
feat(nodes): add secure HMAC-SHA256 node transport layer (#3654)
Add a new `nodes` module with HMAC-SHA256 authenticated transport for
secure inter-node communication over standard HTTPS. Includes replay
protection via timestamped nonces and constant-time signature
comparison.

Also adds `NodeTransportConfig` to the config schema and fixes missing
`approval_manager` field in four `ChannelRuntimeContext` test
constructors that failed compilation on latest master.

Original work by @rareba. Rebased on latest master to resolve merge
conflicts (SwarmConfig/SwarmStrategy exports, duplicate MCP validation,
test constructor fields).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
982c3069dd
feat(tools): add Microsoft 365 integration via Graph API (#3653)
Add Microsoft 365 tool providing access to Outlook mail, Teams messages,
Calendar events, OneDrive files, and SharePoint search via Microsoft
Graph API. Includes OAuth2 token caching (client credentials and device
code flows), security policy enforcement, and config validation.

Rebased on latest master, resolving conflicts with SwarmConfig exports
and adding approval_manager to ChannelRuntimeContext test constructors.

Original work by @rareba.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:12 +03:00
Argenis
6ea7999ef5
feat(notion): add Notion database poller channel and API tool (#3650)
Add Notion integration with two components:
- NotionChannel: polls a Notion database for tasks with configurable
  status properties, concurrency limits, and stale task recovery
- NotionTool: provides CRUD operations (query_database, read_page,
  create_page, update_page) for agent-driven Notion interactions

Includes config schema (NotionConfig), onboarding wizard support,
and full unit test coverage for both channel and tool.

Supersedes #3609 — rebased on latest master to resolve merge conflicts
with swarm feature additions in config/mod.rs.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
Argenis
6105cc4c3d
fix(lint): Box::pin crate::agent::run calls to satisfy large_futures (#3675)
Wrap all crate::agent::run() calls with Box::pin() across scheduler,
daemon, gateway tests, and main.rs to satisfy clippy::large_futures.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
Chris Hengge
a3887385b1
fix(tools): qualify is_service_environment with super:: inside mod native_backend (#3659)
Commit 811fab3b added is_service_environment() as a top-level function and
called it from two sites. The call at line 445 is at module scope and resolves
fine. The call at line 1473 is inside mod native_backend, which is a child
module — Rust does not implicitly import parent-scope items, so the unqualified
name fails with E0425 (cannot find function in this scope).

Fix: prefix the call with super:: so it resolves to the parent module's
function, matching how mod native_backend already imports other parent items
(e.g. use super::BrowserAction).

The browser-native feature flag is required to reproduce:
  cargo check --features browser-native  # fails without this fix
  cargo check --features browser-native  # clean with this fix

Co-authored-by: Argenis <theonlyhennygod@gmail.com>
2026-03-24 15:17:11 +03:00
Argenis
1bea48dba1
feat(security): add Nevis IAM integration for SSO/MFA authentication (#3651)
* feat(security): add Nevis IAM integration for SSO/MFA authentication

Add NevisAuthProvider supporting OAuth2/OIDC token validation (local JWKS +
remote introspection), FIDO2/passkey/OTP MFA verification, session management,
and health checks. Add IamPolicy engine mapping Nevis roles to ZeroClaw tool
and workspace permissions with deny-by-default enforcement and audit logging.

Add NevisConfig and NevisRoleMappingConfig to config schema with client_secret
wired through SecretStore encrypt/decrypt. All features disabled by default.

Rebased on latest master to resolve merge conflicts in security/mod.rs (redact
function) and config/schema.rs (test section).

Original work by @rareba. Supersedes #3593.

Co-Authored-By: rareba <5985289+rareba@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: cargo fmt Box::pin calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: rareba <5985289+rareba@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
Argenis
b8689f1599
feat(tunnel): add OpenVPN tunnel provider (#3648)
* feat(tunnel): add OpenVPN tunnel provider

Add OpenVPN as a new tunnel provider alongside cloudflare, tailscale,
ngrok, and custom. Includes config schema, validation, factory wiring,
and comprehensive unit tests.

Co-authored-by: rareba <rareba@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add missing approval_manager field to ChannelRuntimeContext constructors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: rareba <rareba@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
Argenis
7844ab371c
style: cargo fmt Box::pin calls in cron scheduler (#3667)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
Argenis
cc582f4d86
fix(lint): Box::pin large futures in cron scheduler and cron_run tool (#3666)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:11 +03:00
argenis de la rosa
29f19ef7a6
feat(workspace): add multi-client workspace isolation
Add workspace profile management, security boundary enforcement, and
a workspace management tool for isolated client engagements.

Original work by @rareba. Supersedes #3597 — rebased on latest master.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:17:10 +03:00
argenis de la rosa
6fcb64489b
feat(security): add capability-based tool access control
Add an optional `allowed_tools` parameter that restricts which tools are
available to the agent. When `Some(list)`, only tools whose name appears
in the list are retained; when `None`, all tools remain available
(backward compatible). This enables fine-grained capability control for
cron jobs, heartbeat tasks, and CLI invocations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 15:16:07 +03:00