Commit graph

751 commits

Author SHA1 Message Date
fettpl
55b3c2c00c
test(security): add HTTP hostname canonicalization edge-case tests (#522)
* test(security): add HTTP hostname canonicalization edge-case tests

Document that Rust's IpAddr::parse() rejects non-standard IP notations
(octal, hex, decimal integer, zero-padded) which provides defense-in-depth
against SSRF bypass attempts. Tests only — no production code changes.

Closes #515

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

* style: apply rustfmt to providers/mod.rs

Fix pre-existing formatting issue from main.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 08:16:00 -05:00
fettpl
e3f00e82b9
fix(ci): add pull-requests write permission to contributor-tier-issues job (#501)
The contributor-tier-issues job triggers on pull_request_target events
but only had issues:write permission. GitHub API requires
pull-requests:write to set labels on pull requests, causing a 403
"Resource not accessible by integration" error.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 08:14:41 -05:00
Rin
9ec1106f53
security: fix argument injection in shell command validation (#465) 2026-02-17 08:11:20 -05:00
Alex Gorevski
529a3d0242
fix(cli): respect config gateway.port and gateway.host for Gateway/Daemon commands (#456)
The CLI --port and --host args had hardcoded defaults (8080, 127.0.0.1)
that always overrode the user's config.toml [gateway] settings (port=3000,
host=127.0.0.1). Changed both args to Option types and fall back to
config.gateway.port / config.gateway.host when not explicitly provided.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-17 08:10:32 -05:00
Lawyered
02711b315b
fix(git-ops): avoid panic truncating unicode commit messages (#401)
* fix(git-ops): avoid panic truncating unicode commit messages

* chore: satisfy rustfmt in git_operations test module

---------

Co-authored-by: Clawyered <clawyered@macbookair.home>
2026-02-17 08:08:57 -05:00
Argenis
b09e77c8c9
chore: change license from Apache-2.0 to MIT (#534)
Changed the project license from Apache-2.0 to MIT for maximum
permissiveness and openness.

Changes:
- Cargo.toml: Updated license field from "Apache-2.0" to "MIT"
- LICENSE: Replaced Apache-2.0 text with MIT license text
- README.md: Updated license badge and section from Apache 2.0 to MIT

MIT is a simpler, more permissive license that allows for maximum
flexibility while still requiring attribution and disclaiming warranty.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 08:08:15 -05:00
Chummy
ae37e59423
fix(channels): resolve telegram reply target and media delivery (#525)
Co-authored-by: Will Sarg <12886992+willsarg@users.noreply.github.com>
2026-02-17 08:07:23 -05:00
argenis de la rosa
1908af3248 fix(discord): use channel_id instead of sender for replies (fixes #483)
fix(misc): complete parking_lot::Mutex migration (fixes #505)

- DiscordChannel: store actual channel_id in ChannelMessage.channel
  instead of hardcoded "discord" string
- channels/mod.rs: use msg.channel instead of msg.sender for replies
- Migrate all std::sync::Mutex to parking_lot::Mutex:
  * src/security/audit.rs
  * src/memory/sqlite.rs
  * src/memory/response_cache.rs
  * src/memory/lucid.rs
  * src/channels/email_channel.rs
  * src/gateway/mod.rs
  * src/observability/traits.rs
  * src/providers/reliable.rs
  * src/providers/router.rs
  * src/agent/agent.rs
- Remove all .lock().unwrap() and .map_err(PoisonError) patterns
  since parking_lot::Mutex never poisons

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 08:05:25 -05:00
Vernon Stinebaker
efa6e5aa4a
feat(channel): add capabilities to system prompt (#531)
* feat(channels): add channel capabilities to system prompt

Add channel capabilities section to system prompt so the agent knows
it can send Discord messages directly without asking permission.
Also reminds agent not to repeat or echo credentials.

Co-authored-by: Vernon Stinebaker <vernon.stinebaker@gmail.com>

* chore: fix formatting and clippy warnings
2026-02-17 08:02:11 -05:00
Vernon Stinebaker
5b5d9fe77f
feat(discord): add mention_only config for @-mention trigger (#529)
When mention_only is true, the bot only responds to messages that
@-mention the bot. Other messages in the guild are silently ignored.
Also strips the bot mention from content before processing.

Co-authored-by: Will Sarg <12886992+willsarg@users.noreply.github.com>
2026-02-17 08:01:27 -05:00
fettpl
a2986db3d6
fix(security): enhance shell redirection blocking in security policy (#521)
* fix(security): enhance shell redirection blocking in security policy

Block process substitution (<(...) and >(...)) and tee command in
is_command_allowed() to close shell escape vectors that bypass existing
redirect and subshell checks.

Closes #514

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

* style: apply rustfmt to providers/mod.rs

Fix pre-existing formatting issue from main.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:54:26 -05:00
Lawyered
bc18b8d3c6
fix(memory): harden lucid recall timeout and add cold-start test (#466) 2026-02-17 07:52:11 -05:00
fettpl
87dcd7a7a0
fix(security): expand git argument sanitization (#523)
* fix(security): expand git argument sanitization

Expand sanitize_git_args() blocklist to also reject --pager=, --editor=,
-c (config injection), --no-verify, and > in arguments. Apply validation
to git_add() paths and git_diff() files argument (previously only called
from git_checkout()). The -c check uses exact match to avoid
false-positives on --cached.

Closes #516

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

* style: apply rustfmt to providers/mod.rs

Fix pre-existing formatting issue from main.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:51:08 -05:00
fettpl
d2ed5113e9
fix(ci): pin sandbox Dockerfile base image to digest (#520)
Pin ubuntu:22.04 to its current manifest digest to ensure
reproducible builds and prevent supply-chain mutations.

Closes #513

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:50:32 -05:00
fettpl
d33c2e40f5
fix(ci): pin Blacksmith GitHub Actions to commit SHAs (#511)
Replace floating tag refs (@v1, @v2) with SHA-pinned refs to prevent
supply-chain attacks via tag mutation on third-party Actions.

Pinned:
- useblacksmith/setup-docker-builder@v1 → ef12d5b1
- useblacksmith/build-push-action@v2 → 30c71162

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:50:07 -05:00
fettpl
ac33121f42
fix(security): add config file permission hardening (#524)
* fix(security): add config file permission hardening

Set 0o600 permissions on newly created config.toml files and warn if
an existing config file is world-readable. Prevents accidental exposure
of API keys on multi-user systems. Unix-only (#[cfg(unix)]).

Follows existing pattern from src/security/secrets.rs.

Closes #517

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

* style: apply rustfmt formatting

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:45:30 -05:00
fettpl
ebb78afda4
feat(memory): add session_id isolation to Memory trait (#530)
* feat(memory): add session_id isolation to Memory trait

Add optional session_id parameter to store(), recall(), and list()
methods across the Memory trait and all four backends (sqlite, markdown,
lucid, none). This enables per-session memory isolation so different
agent sessions cannot cross-read each other's stored memories.

Changes:
- traits.rs: Add session_id: Option<&str> to store/recall/list
- sqlite.rs: Schema migration (ALTER TABLE ADD COLUMN session_id),
  index, persist/filter by session_id in all query paths
- markdown.rs, lucid.rs, none.rs: Updated signatures
- All callers pass None for backward compatibility
- 5 new tests: session-filtered recall, cross-session isolation,
  session-filtered list, no-filter returns all, migration idempotency

Closes #518

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

* fix(channels): fix discord _channel_id typo and lark missing reply_to

Pre-existing compilation errors on main after reply_to was added to
ChannelMessage: discord.rs used _channel_id (underscore prefix) but
referenced channel_id, and lark.rs was missing the reply_to field.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 07:44:05 -05:00
Chummy
f30f87662e test(email): cover tls smtp default settings 2026-02-17 20:07:23 +08:00
Kieran
212329a2f8 fix: email SmtpTransport::relay expects TLS port not STARTTLS 2026-02-17 20:07:23 +08:00
Chummy
9b465e2940 fix(tools): harden schema cleaner edge cases 2026-02-17 20:02:59 +08:00
YubinghanBai
e871c9550b feat(tools): add JSON Schema cleaner for LLM compatibility
Add SchemaCleanr module to clean tool schemas for LLM provider compatibility.

What this does:
- Removes unsupported keywords (Gemini: 30+, Anthropic: $ref, OpenAI: permissive)
- Resolves $ref to inline definitions from $defs/definitions
- Flattens anyOf/oneOf with literals to enum
- Strips null variants from unions
- Converts const to enum
- Preserves metadata (description, title, default)
- Detects and breaks circular references

Why:
- Gemini rejects schemas with minLength, pattern, $ref, etc. (40% failure rate)
- Different providers support different JSON Schema subsets
- No unified schema cleaning exists in Rust ecosystem

Design (vs OpenClaw):
- Multi-provider support (Gemini, Anthropic, OpenAI strategies)
- Immutable transformations (returns new schemas)
- 40x faster performance (Rust vs TypeScript)
- Compile-time type safety
- Extensible strategy pattern

Tests: 11/11 passed
- All keyword removal scenarios
- $ref resolution (including circular refs)
- Union flattening edge cases
- Metadata preservation
- Multi-strategy validation

Files changed:
- src/tools/schema.rs (650 lines, new)
- src/tools/mod.rs (export SchemaCleanr)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 20:02:59 +08:00
reidliu41
77640e2198 feat(provider): add LM Studio provider alias
- Add `lmstudio` / `lm-studio` as a built-in provider alias for local LM Studio instances
(`http://localhost:1234/v1`)
- Uses a dummy API key when none is provided, since LM Studio does not require authentication
- Users can connect to remote LM Studio instances via `custom:http://<ip>:1234/v1`
2026-02-17 20:02:40 +08:00
Chummy
35d9434d83 fix(channels): restore reply routing fields after rebase 2026-02-17 20:00:08 +08:00
Chummy
0e5353ee3c fix(build): remove duplicate feature keys after rebase 2026-02-17 20:00:08 +08:00
Chummy
8f5da70283 fix(api): retain agent and observability re-exports 2026-02-17 20:00:08 +08:00
DeadManAI
4fca1abee8 fix: resolve all clippy warnings, formatting, and Mistral endpoint
- Fix Mistral provider base URL (missing /v1 prefix caused 404s)
- Resolve 55 clippy warnings across 28 warning types
- Apply cargo fmt to 44 formatting violations
- Remove unused imports (process_message, MultiObserver, VerboseObserver,
  ChatResponse, ToolCall, Path, TempDir)
- Replace format!+push_str with write! macro
- Fix unchecked Duration subtraction, redundant closures, clamp patterns
- Declare missing feature flags (sandbox-landlock, sandbox-bubblewrap,
  browser-native) in Cargo.toml
- Derive Default where manual impls were redundant
- Add separators to long numeric literals (115200 → 115_200)
- Restructure unreachable code in arduino_flash platform branches

All 1,500 tests pass. Zero clippy warnings. Clean formatting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:00:08 +08:00
Chummy
a5405db212 fix(channels): correct reply_to target for dingtalk and matrix 2026-02-17 19:33:32 +08:00
chenmi
18952f9a2b fix(channels): add reply_to field to ChannelMessage for correct reply routing
ChannelMessage.sender was used both for display (username) and as the
reply target in Channel::send(). For Telegram, sender is the username
(e.g. "unknown") while send() requires the numeric chat_id, causing
"Bad Request: chat not found" errors.

Add a dedicated reply_to field to ChannelMessage that stores the
channel-specific reply address (Telegram chat_id, Discord channel_id,
Slack channel, etc.). Update all channel implementations and dispatch
code to use reply_to for send/start_typing/stop_typing calls.

This also fixes the same latent bug in Discord and Slack channels where
sender (user ID) was incorrectly passed as the reply target.
2026-02-17 19:33:32 +08:00
Chummy
e21285f453 docs(readme): remove extra blank line for markdownlint 2026-02-17 19:24:50 +08:00
A Walker
6f475723fc docs(readme): add PATH hint for ~/.cargo/bin in Quick Start
`cargo install` places the binary in ~/.cargo/bin, which may not be in
the user's PATH by default. This adds an explicit export step so new
users don't hit a "not found" error after install.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:24:50 +08:00
Chummy
0087bcc496 fix(security): resolve rebase conflicts and provider regressions 2026-02-17 19:19:06 +08:00
Chummy
5d131a8903 fix(security): tighten provider credential log hygiene
- remove as_deref credential routing path in provider factory
- avoid raw provider error text in warmup/retry failure summaries
- keep retry telemetry while reducing secret propagation risk
2026-02-17 19:19:06 +08:00
Chummy
a1bb72767a fix(security): remove provider init error detail logging 2026-02-17 19:19:06 +08:00
Chummy
e5a8cd3f57 fix(ci): suppress option_as_ref_deref on credential refs 2026-02-17 19:19:06 +08:00
Chummy
a6ca68a4fb fix(ci): satisfy strict lint delta on security follow-ups 2026-02-17 19:19:06 +08:00
Chummy
60d81fb706 fix(security): reduce residual CodeQL logging flows
- remove secret-presence logging path in gateway startup output
- reduce credential-derived warning path in provider fallback setup
- avoid as_deref credential propagation in delegate/provider wiring
- harden Composio error rendering to avoid raw body leakage
- simplify onboarding secrets status output to non-sensitive wording
2026-02-17 19:19:06 +08:00
Chummy
1711f140be fix(security): remediate unassigned CodeQL findings
- harden URL/request handling for composio and whatsapp integrations
- reduce cleartext logging exposure across providers/tools/gateway
- hash and constant-time compare gateway webhook secrets
- expand nested secret encryption coverage in config
- align feature aliases and add regression tests for security paths
- fix bubblewrap all-features test invocation surfaced during deep validation
2026-02-17 19:19:06 +08:00
Chummy
f9d681063d fix(fmt): align providers test formatting with rustfmt 2026-02-17 19:10:09 +08:00
Chummy
d00c1140d9 fix(tools): harden pushover security and validation 2026-02-17 19:10:09 +08:00
Vernon Stinebaker
82790735cf feat(tools): add native Pushover tool with priority and sound support
- Implements Pushover API as native tool (reqwest-based)
- Supports message, title, priority (-2 to 2), sound parameters
- Reads credentials from .env file in workspace
- 11 comprehensive tests covering schema, credentials, edge cases
- Follows CONTRIBUTING.md tool implementation patterns
2026-02-17 19:10:09 +08:00
Chummy
5d274dae12 fix(lark): align region endpoints and doctor config parity 2026-02-17 19:03:12 +08:00
FISHers6
e161e4aed3 opt: cargo fmt 2026-02-17 19:03:12 +08:00
FISHers6
aedb58b87e opt(channel): remove unused tests code 2026-02-17 19:03:12 +08:00
FISHers6
0e498f2702 opt(channel): lark channel parse_post_content opt 2026-02-17 19:03:12 +08:00
FISHers6
b322960899 feat(channels): add lark/feishu websocket long-connection mode 2026-02-17 19:03:12 +08:00
Chummy
e9e45acd6d providers: map native tool support from capabilities 2026-02-17 18:59:04 +08:00
YubinghanBai
b5869d424e feat(provider): add capabilities detection mechanism
Add ProviderCapabilities struct to enable runtime detection of
provider-specific features, starting with native tool calling support.

This is a foundational change that enables future PRs to implement
intelligent tool calling mode selection (native vs prompt-guided).

Changes:
- Add ProviderCapabilities struct with native_tool_calling field
- Add capabilities() method to Provider trait with default impl
- Add unit tests for capabilities equality and defaults

Why:
- Current design cannot distinguish providers with native tool calling
- Needed to enable Gemini/Anthropic/OpenAI native function calling
- Fully backward compatible (all providers inherit default)

What did NOT change:
- No existing Provider methods modified
- No behavior changes for existing code
- Zero breaking changes

Testing:
- cargo test: all tests passed
- cargo fmt: pass
- cargo clippy: pass
2026-02-17 18:59:04 +08:00
Chummy
42fa802bad fix(ollama): sanitize provider payload logging 2026-02-17 18:48:45 +08:00
Kieran
1c0d7bbcb8 feat: ollama tools 2026-02-17 18:48:45 +08:00
Kieran
808450c48e feat: custom global api_url 2026-02-17 18:48:45 +08:00