Commit graph

327 commits

Author SHA1 Message Date
Mauro
d8c5183d9a
feat(mcp): store oversized text results as artifacts (#2308)
* feat(mcp): store oversized text results as artifacts

* feat(mcp): fix doc

* fix(mcp): preserve raw MCP payload in text artifacts

* fix(mcp): avoid leaking large text when artifact persistence fails

* chore(mcp): clarify inline text limit and cover artifact edge cases
2026-04-04 01:30:36 +08:00
Mauro
bae4342af1
Feat/tool read_file by lines (#1981)
* feat(tool): read_file tool by lines

* fix test

* restore old bytes read_file tool

* unified read_file tool

* revert

* fix doc

* fix test

* fix doc

* fix offset

* fix default start_line

* fix line format

* fix bug

* removed legacy test

* enhanced infos

* improvements

* feat(tool): read_file tool by lines
2026-04-02 18:49:08 +08:00
Cytown
e2a9bb97c7
unify all panic event to panic log file (#2250) 2026-04-01 23:26:49 +08:00
reusu
31afad6e87
feat: add load_image tool for local file vision (#2116)
* feat: add load_image tool for local file vision

* fix: address load_image PR review feedback

- Exclude load_image from sub-agent tools via Unregister after Clone,
  since RunToolLoop does not call resolveMediaRefs
- Add ToolRegistry.Unregister() method
- Fix scope collision: use channel:chatID instead of filename
- Add channel/chatID context resolution matching send_file pattern
- Add comment explaining iteration > 1 guard on resolveMediaRefs
- Remove emoji from ForUser for consistency with send_file
- Add load_image_test.go

* feat: enable load_image for subagents via MediaResolver in RunToolLoop

Instead of removing load_image from sub-agent tools (28f69e71), inject a
MediaResolver into the legacy RunToolLoop fallback path so media:// refs
are resolved to base64 before each LLM call — matching the main agent
loop behavior.

- Add MediaResolver field to ToolLoopConfig and call it on iteration > 1
- Add SubagentManager.SetMediaResolver() and wire it through runTask
- Remove ToolRegistry.Unregister() (no longer needed)
- Restore load_image in sub-agent tool set (revert Clone+Unregister)
- Add TestSubagentManager_SetMediaResolver_StoresResolver

* refactor(load_image): remove prompt parameter from tool schema

* test(tools): add success-path test for LoadImageTool

Add TestLoadImage_SuccessPath that creates a real PNG file with valid
magic bytes, calls Execute with WithToolContext, and verifies:
- result.IsError == false
- ToolResult.Media contains a media:// ref
- ToolResult.ForLLM contains the [image: marker
- media ref is resolvable in the store

Add explanatory comment in loop.go for why Media and ArtifactTags
coexist on non-ResponseHandled tool results (e.g. load_image).

* fix: preallocate slice in tests and add ResponseHandled guard in toolloop

Fix prealloc linter failure in load_image_test.go.

Prevent double-resolving media by checking ResponseHandled in toolloop.go.

* Register TTS tool if provider is available

---------

Co-authored-by: Reusu <admin@yumao.name>
Co-authored-by: 美電球 <hoshina@evaz.org>
2026-04-01 21:32:10 +08:00
Hoshina
59dee895fc refactor(runtime): drop non-session legacy context compatibility 2026-04-01 20:56:48 +08:00
Hua Audio
0f395ce110
Refactor/asr tts (#1939)
* refactor: update ASR and TTS implementations

* fix lint

* Integrating asr/tts models w/ new security config

* update documents

* add arbitrary whisper transcriptor support

* update documents

* fix lint

* add mimo tts
2026-04-01 12:21:21 +08:00
Mauro
ffa65b53ed
Merge pull request #1982 from Kathent/fix-deny-pattern
fix: more accurate deny pattern for disk wiping
2026-03-30 14:24:17 +02:00
Alix-007
e88df4ff9c
feat(tools): add reaction tool and reply-aware message sends (#2156)
- Add `reaction` tool that reacts to a message (defaults to current inbound message via context)
- Extend `message` tool with optional `reply_to_message_id` parameter
- Introduce `WithToolInboundContext` to inject inbound message IDs into tool execution context
- Surface `MessageID` and `ReplyToMessageID` in `processOptions` for tool-surface consumption

Refs #2137
2026-03-30 16:31:34 +08:00
smallwhite
89af3b2511 fix(tools): message tool no longer suppresses reply to originating chat
When the message tool sent to a different chat (e.g., a group), the
agent's final response to the originating chat was incorrectly skipped
because HasSentInRound() was a simple bool that didn't distinguish
targets. Replace with HasSentTo(channel, chatID) that tracks all
send targets per round and only suppresses when the target matches.

Fixes cross-conversation message causing "Processing..." to hang.
2026-03-30 15:06:22 +08:00
afjcjsbx
6429f6af9a refactor(agent): source discovery identity from AGENT.md frontmatter 2026-03-29 22:43:20 +02:00
daming大铭
1fc5345857
refactor(cron): remove deliver and type params, unify agent execution path (#2147)
The agent path now publishes to outbound bus directly (since #2100),
making the deliver=true direct-to-bus shortcut and the directive type
prompt wrapping redundant. All cron jobs now uniformly route through
the agent. This is an intentional behavior change: old jobs with
deliver=true will execute through the agent instead of bypassing it.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 22:52:34 +08:00
afjcjsbx
07748bf076 chore: revert unrelated golines formatting 2026-03-29 14:06:19 +02:00
afjcjsbx
3b173c0bee feat(agent): add multi-agent discovery prompt and per-agent 2026-03-29 13:58:19 +02:00
沈青川
e414b82ac3
fix(cron): publish agent response to outbound bus for cron-triggered jobs (#2100)
* fix(cron): publish agent response to outbound bus for cron-triggered jobs

When a cron job triggers agent execution via ProcessDirectWithChannel,
the agent response was silently discarded — the code assumed AgentLoop
would auto-publish it, but SendResponse is false on this path.

Delegate to PublishResponseIfNeeded (exported from AgentLoop) so the
response reaches the originating channel (e.g. Telegram) only when the
message tool did not already deliver content in the same round.

Also adds a "directive" message type to CronPayload, allowing cron jobs
to instruct the agent to execute a task rather than echo static text.

* fix(cron): add type validation and directive test coverage

Address reviewer blocking feedback:

1. Server-side whitelist for `type` parameter — the `enum` in
   Parameters() is only an LLM schema hint; any string was persisted.
   Now `addJob` rejects values other than "message" and "directive".

2. Comprehensive test coverage for the directive code path:
   - directive adds prompt prefix to ProcessDirectWithChannel
   - deliver=true + directive routes through agent (not direct publish)
   - directive prompt content, sessionKey, channel, chatID are correct
   - invalid type is rejected; valid types ("", "message", "directive") pass
   - deliver=true message type goes directly to bus (regression)
   - agent error path does not trigger publish (regression)

Also merge the two UpdateJob calls in addJob into one to avoid
redundant disk I/O (non-blocking suggestion from review).

* fix(cron): remove omitempty from CronPayload.Type for consistent JSON

Empty string and "message" are semantically equivalent defaults;
always serializing the field avoids asymmetric JSON output.

* test(cron): remove redundant test, strengthen error path coverage

- Remove ExecuteJobDirectivePassesCorrectContent: its assertions on
  sessionKey/channel/chatID duplicate ExecuteJobPublishesAgentResponse;
  its prompt check duplicates DirectiveAddsPromptPrefix.
- Strengthen DirectiveAddsPromptPrefix with exact prompt match and
  publish response assertion.
- Fix ReturnsErrorWithoutPublish: set non-empty stub response so the
  test verifies the error branch early-return, not the response==""
  guard.

* fix(ci): satisfy golines and gosmopolitan in cron code
2026-03-29 13:47:28 +08:00
afjcjsbx
e2018c4aa7 fix lint 2026-03-26 21:33:43 +01:00
afjcjsbx
48c04e050d feat(tools) range in web_search 2026-03-26 21:02:46 +01:00
Liu Yuan
3f1ac297d4 feat(tools): add exec tool enhancement with background execution and PTY support (#1752)
- Unified exec tool with actions: run/list/poll/read/write/send-keys/kill
- PTY support using creack/pty library
- Process session management with background execution
- Process group kill for cleaning up child processes
- Session cleanup: 30-minute TTL for old sessions
- Output buffer: 100MB limit with truncation

Actions:
- run: execute command (sync or background)
- list: list all sessions
- poll: check session status
- read: read session output
- write: send input to session stdin
- send-keys: send special keys (up, down, ctrl-c, enter, etc.)
- kill: terminate session

Tests:
- PTY: allowed commands, write/read, poll, kill, process group kill
- Non-PTY: background execution, list, read, write, poll, kill, process group kill
- Session management: add/get/remove/list/cleanup
2026-03-25 21:02:49 +08:00
kathent
ae021ef843 fix: more accurate deny pattern for disk wiping 2026-03-25 10:14:16 +08:00
Mauro
2a0efb6e52
Merge pull request #1889 from afjcjsbx/fix/binary-tool-output-handling
fix(tool): route binary outputs through the media pipeline
2026-03-24 15:37:06 +01:00
Sabyasachi Patra
fcc20ec72c
feat(tools): add tool argument schema validation before execution (#1877)
Validate tool call arguments against each tool's Parameters() JSON Schema
in ExecuteWithContext() before calling Execute(). This prevents type
confusion, argument injection, and missing-field errors from reaching tools.

Validates: required fields, type matching (string/integer/number/boolean/
array/object), enum membership, nested objects (recursive), array element
types. Rejects unexpected extra properties unless additionalProperties is
set to true (for MCP tool compatibility).

Returns ToolResult{IsError: true} on failure so the LLM can self-correct.

Ref: Security Hardening > Tool abuse prevention via strict parameter validation
2026-03-24 18:35:56 +08:00
afjcjsbx
fddfd56b50 Merge branch 'main' into fix/binary-tool-output-handling
# Conflicts:
#	pkg/agent/loop.go
#	pkg/agent/loop_test.go
#	pkg/commands/builtin_test.go
#	pkg/tools/send_file_test.go
2026-03-23 13:16:23 +01:00
美電球
75270c4777
Fix 1886 media cleanup policy (#1887)
* fix(media): track cleanup ownership per path

Add explicit cleanup policy handling to MediaStore and count refs by path before deleting the underlying file. This prevents cleanup from removing shared files until the final ref is gone.

Refs #1886

* fix(tools): keep send_file refs forget-only

Mark send_file media registrations as forget-only so cleanup drops the ref without deleting the original workspace file.

Refs #1886

* fix(channels): declare managed media cleanup policy

Explicitly mark downloaded and managed channel media as delete-on-cleanup so media ownership is visible at each registration site.

Refs #1886
2026-03-23 12:13:59 +08:00
BeaconCat
48cba906cd fix: restore missing assets and address Copilot review comments
- Add hardware-banner.jpg, launcher-webui.jpg, launcher-tui.jpg (lost in
  previous force push)
- Add io.LimitReader (1MB) to BaiduSearchProvider response body read
- Add no-results fallback and "Results for: ... (via Baidu Search)" header
- Add api_keys field to Brave and Perplexity tables in fr/ja/pt-br/vi
  tools_configuration.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 10:21:06 +08:00
afjcjsbx
14a4983af3 Merge branch 'main' into fix/binary-tool-output-handling
# Conflicts:
#	pkg/agent/loop.go
#	pkg/tools/result.go
2026-03-22 23:08:27 +01:00
BeaconCat
60a7098fd3 feat(search): add Baidu Qianfan AI Search provider with i18n docs
- Add BaiduSearchConfig struct and register in WebToolsConfig/defaults
- Insert Baidu Search in priority chain: DuckDuckGo > Baidu > GLM Search
- Use perplexityTimeout (30s) — Qianfan is LLM-based
- Fix response parsing: use references[] field per API spec
- Add baidu_search block to config.example.json

docs: sync configuration.md and README Documentation table across all languages

- Complete truncated configuration.md for fr/ja/pt-br/vi/zh: add Spawn
  async flow diagram, Providers table, Model Configuration (all vendors,
  examples, load balancing, migration), Provider Architecture, Scheduled
  Tasks, and Advanced Topics links
- Add Hooks/Steering/SubTurn entries to Documentation table in all 8
  READMEs (en/zh/fr/id/it/ja/pt-br/vi), ordered before Troubleshooting
- Add Baidu Search row to web search table in all 8 READMEs and
  tools_configuration.md (en + 5 i18n); zh README reorders search
  engines with China-friendly options first
- Add Matrix channel docs translations (fr/ja/pt-br/vi)
- Add Weixin channel to chat-apps.md and all README Channels tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 00:51:27 +08:00
Administrator
f7f27e237a merge: resolve conflicts between refactor/agent and main 2026-03-22 19:21:58 +08:00
afjcjsbx
df4f322f09 fix(tool): route binary outputs through the media pipeline. 2026-03-22 12:05:28 +01:00
Administrator
88d754b172 merge main 2026-03-22 13:47:14 +08:00
daming大铭
ebcd5645f1
Revert "feat(tools): add exec tool enhancement with background execution and …"
This reverts commit f901af8cbc.
2026-03-22 00:39:47 +08:00
Administrator
24d6cb5272 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-21 23:42:25 +08:00
Liu Yuan
f901af8cbc
feat(tools): add exec tool enhancement with background execution and PTY support (#1752)
- Unified exec tool with actions: run/list/poll/read/write/send-keys/kill
- PTY support using creack/pty library
- Process session management with background execution
- Process group kill for cleaning up child processes
- Session cleanup: 30-minute TTL for old sessions
- Output buffer: 100MB limit with truncation

Actions:
- run: execute command (sync or background)
- list: list all sessions
- poll: check session status
- read: read session output
- write: send input to session stdin
- send-keys: send special keys (up, down, ctrl-c, enter, etc.)
- kill: terminate session

Tests:
- PTY: allowed commands, write/read, poll, kill, process group kill
- Non-PTY: background execution, list, read, write, poll, kill, process group kill
- Session management: add/get/remove/list/cleanup
2026-03-21 22:38:03 +08:00
Administrator
087e8519c5 refactor: improve code readability and consistency across multiple files 2026-03-21 17:12:45 +08:00
Administrator
54889f21a7 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 17:05:09 +08:00
Mauro
ff975abec2
feat(tool): anti cloudflare challenge in web_fetch (#1762)
* feat(tool): anti-cloudflare-challenge

* fix lint
2026-03-19 17:01:45 +08:00
Administrator
29a161e757 fix(tools): prevent nil pointer dereference in spawn tools
Add nil checks in NewSpawnTool and NewSubagentTool constructors to
handle nil manager gracefully. Fix spelling errors (cancelled->canceled)
and remove unused test code. Update tests to use mock spawner.
2026-03-19 13:51:11 +08:00
Administrator
e801ccb674 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 13:09:05 +08:00
Administrator
99b189d3fb feat(subturn): implement token budget tracking for SubTurns 2026-03-19 12:38:18 +08:00
Mauro
e931756fee
feat(tool): overwrite flag in write_file (#1761)
* feat: overwrite flag in write file tool

* fix error message
2026-03-19 11:22:52 +08:00
Administrator
53404f18ca feat(subturn): support stateful iteration for evaluator-optimizer pattern
Add ActualSystemPrompt and InitialMessages fields to SubTurnConfig to enable
stateful worker context passing across multiple evaluation iterations.

Changes:
- Add ActualSystemPrompt field to separate system role from user task description
- Add InitialMessages field to preload ephemeral session history before agent loop starts
- Add Messages field to ToolResult for carrying session history (internal use, not serialized)
- Update runTurn to inject system prompt and preload history from InitialMessages
- Update AgentLoopSpawner to map new fields from tools.SubTurnConfig to agent.SubTurnConfig

This enables the evaluator-optimizer execution strategy in team tool to maintain
worker context across iterations while keeping SubTurn isolation intact.
2026-03-19 10:15:00 +08:00
Administrator
c732e63650 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 09:16:38 +08:00
Paolo Anzani
eb86e10e5c
fix(tools): propagate tool registry to subagents (#1711)
* fix(tools): propagate tool registry to subagents via Clone

SubagentManager was created with an empty ToolRegistry and SetTools()
was never called, causing all subagent tool invocations to fail with
"tool not found". This was a regression from the multi-agent refactor.

Fix: clone the parent agent's tool registry into the subagent manager
after creation but before spawn/spawn_status registration — giving
subagents access to file, exec, web, and other tools while preventing
recursive subagent spawning.

- Add ToolRegistry.Clone() for independent shallow copies
- Call subagentManager.SetTools(agent.Tools.Clone()) in registerSharedTools
- Add tests for Clone isolation, empty clone, and hidden tool state

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

* fix(tools): fix cron_test build error and add TTL clone test

- Fix cron_test.go:229 — replace non-existent SubscribeOutbound(ctx)
  with select on OutboundChan(), matching the MessageBus channel API
- Add TestToolRegistry_Clone_PreservesTTLValue per reviewer feedback
- Add version reset note to Clone() doc comment

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 00:17:16 +08:00
linhaolin1
f93d2b4533
fix: Avoid failure of the main agent process due to tool call failures (#1023)
* Avoid failure of the main agent process due to tool call failures or abnormal returns

* rename recover
2026-03-19 00:10:26 +08:00
Administrator
431a53cbb1 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-18 22:57:01 +08:00
Administrator
3611034795 fix(agent): implement Critical flag, complete tools.SubTurnConfig, remove redundant subTurnResults
- Critical flag was declared but never acted on; non-critical SubTurns
  now break out of the iteration loop when IsParentEnded() returns true
- tools.SubTurnConfig was missing Critical/Timeout/MaxContextRunes,
  making those fields unreachable from the tools layer; added fields and
  wired them through AgentLoopSpawner.SpawnSubTurn
- Removed subTurnResults sync.Map from AgentLoop — it was a redundant
  alias for the same channel already stored in turnState.pendingResults;
  dequeuePendingSubTurnResults now reads directly via activeTurnStates
- Replace hardcoded concurrencySem size 5 with maxConcurrentSubTurns constant
- Update affected tests to match new dequeuePendingSubTurnResults API
2026-03-18 18:22:06 +08:00
afjcjsbx
9835e821d7 Merge branch 'main' into feat/markdown-output-format-web-fetch 2026-03-17 21:45:18 +01:00
Liu Yuan
61a899cfbc fix(cron): update test to use OutboundChan instead of removed SubscribeOutbound
The SubscribeOutbound method was removed in commit 9c31b0c but cron_test.go
was not updated to use the new OutboundChan() API.
2026-03-18 01:37:07 +08:00
afjcjsbx
8f460726cc fix lint + error check 2026-03-17 17:14:23 +01:00
Mauro
3791f06faf
Merge branch 'main' into feat/markdown-output-format-web-fetch 2026-03-17 16:37:22 +01:00
Alix-007
b4468313e4
feat(web): whitelist private fetch targets (#1688)
* feat(web): whitelist private fetch targets

* test(web): avoid accept error shadowing

---------

Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
2026-03-17 23:22:05 +08:00
Administrator
e00a3d9017 Merge upstream/main into feat/subturn-poc
Includes JSONL session persistence (#1170), spawn_status tool, Azure provider,
credential encryption, and various fixes. SubTurn features preserved and
integrated with new spawn_status functionality.
2026-03-17 21:55:20 +08:00
wenjie
7b9fdaec32
feat(config): add exec controls and gate cron commands on exec settings (#1685)
- add a dedicated exec settings section in the config page
- support timeout and custom allow/deny regex patterns for exec
- validate custom exec regex patterns in the config API
- block cron command scheduling and execution when exec is disabled
- update tests and i18n strings for the new command settings
2026-03-17 18:56:52 +08:00
Desmond Foo
b402888bfa
feat(tools): add SpawnStatusTool for reporting subagent statuses (#1540)
* feat(tools): add SpawnStatusTool for reporting subagent statuses

* feat(tools): enhance SpawnStatusTool to restrict task visibility by conversation context

* feat(tests): add Unicode result truncation and channel filtering tests for SpawnStatusTool

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* feat(tools): enhance SpawnStatusTool with task ID validation and sorting by creation timestamp

* feat(tools): update SpawnStatusTool description and parameter documentation for clarity

* refactor(tests): improve comments for clarity in ChannelFiltering test case

* fix(tools): update no subagents message for clarity and remove unnecessary locking in runTask

* fix(tools): improve description clarity for SpawnStatusTool regarding task context

* feat(tools): add spawn_status tool configuration and registration

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(agent): improve subagent management for spawn and spawn_status tools

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(tests): update ResultTruncation_Unicode test to use valid CJK character

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: lxowalle <83055338+lxowalle@users.noreply.github.com>
2026-03-17 14:41:43 +08:00
wenjie
cef0f28881
fix(tools): normalize whitelist path checks for symlinked allowed roots (#1660)
- keep regex whitelist matching for existing configs
- add normalized directory-prefix checks for literal allow-path patterns
- support allowed roots that resolve through symlinks
- add regression coverage for symlink-backed whitelist paths
2026-03-17 14:10:11 +08:00
Administrator
12a8590ada fix(agent): enhance SubTurn robustness and fix race conditions
Major improvements to SubTurn implementation:

**Fixes:**
- Channel close race condition (sync.Once)
- Semaphore blocking timeout (30s)
- Redundant context wrapping
- Memory accumulation (auto-truncate at 50 msgs)
- Channel draining on Finish()
- Missing depth limit logging
- Model validation

**Enhancements:**
- Comprehensive documentation (150+ lines)
- 11 new tests covering edge cases
- Improved error messages

All tests pass. Production-ready.

Related: #1316
2026-03-17 12:50:32 +08:00
wenjie
fcb69860c4
feat(web): add configurable cron command execution settings (#1647)
- add tools.cron.allow_command config with a default value of true
- require command_confirm only when cron command execution is disabled
- expose cron command permission and timeout settings in the config UI
- add backend tests and update i18n strings
2026-03-17 09:44:32 +08:00
Mauro
79b0568d75
Merge pull request #1536 from alexhoshina/fix/allow-picoclaw-media-tempdir
Fix: allow picoclaw media tempdir
2026-03-16 21:30:42 +01:00
Administrator
ceeae15d8a feat(agent): wire SubTurn into AgentLoop and Spawn Tool
- Add subTurnResults sync.Map to AgentLoop for per-session channel tracking
- Add register/unregister/dequeue methods in steering.go
- Poll SubTurn results in runLLMIteration at loop start and after each tool,
  injecting results as [SubTurn Result] messages into parent conversation
- Initialize root turnState in runAgentLoop, propagate via context
  (withTurnState/turnStateFromContext), call rootTS.Finish() on completion
- Wire Spawn Tool to spawnSubTurn via SetSpawner in registerSharedTools,
  recovering parentTS from context for proper turn hierarchy
- Refactor subagent.go to use SetSpawner pattern
- Add TestSubTurnResultChannelRegistration and TestDequeuePendingSubTurnResults
2026-03-16 20:44:04 +08:00
afjcjsbx
de68688c75 fix lint 2026-03-15 22:30:02 +01:00
afjcjsbx
d5c2bc538a feat(tool): markdown format in output web_fetch tool 2026-03-15 22:12:03 +01:00
Hoshina
f71eaaf7f8 fix(cron): default scheduled jobs to agent execution 2026-03-14 21:03:23 +08:00
Hoshina
bb1a414527 fix(tools): harden whitelist path resolution 2026-03-14 19:58:23 +08:00
Hoshina
345452fba8 refactor(tools): remove unused validatePath wrapper 2026-03-14 12:08:11 +08:00
Hoshina
1bc05e8392 fix(tools): allow sandbox access to temp media files 2026-03-14 12:02:06 +08:00
Hakancan
6b72326be1
fix: safety guard incorrectly blocks commands with URLs (#1254)
* fix: safety guard incorrectly blocks commands with URLs

The absolutePathPattern regex was matching URL path components like
//github.com as file system paths, causing commands containing URLs
to be incorrectly blocked by the workspace restriction safety guard.

For example, 'agent-browser open https://github.com' would be blocked
because //github.com was treated as an absolute file path outside
the working directory.

The fix adds a check to skip any path match that starts with '//',
as these are URL path components, not file system paths.

Fixes #1203

* fix: handle file:// URIs correctly in safety guard

The previous fix skipped all paths starting with '//', which incorrectly
also skipped file:// URIs that could escape the workspace sandbox.

Changes:
- Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.)
- file:// URIs are now properly checked against workspace boundaries
- Added TestShellTool_FileURISandboxing to verify the fix

Fixes security issue raised by @alexhoshina in PR #1254

* style: fix gofumpt formatting

* fix(safety-guard): use exact match position to prevent URL exemption bypass

Using strings.Index(cmd, raw) always returned the first occurrence of the
matched substring, allowing a bypass where the same //path appeared both
inside a URL and as a standalone shell path (e.g. echo https://etc/passwd
&& cat //etc/passwd would skip the second match).

Switch to FindAllStringIndex so each match is evaluated at its actual
position in the command string.

Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
2026-03-13 17:16:05 +08:00
leamon
0fb92b21b6
enhance skill installer (#1252)
* enhance skill installer

* enhance install skills v2

* go file formate

* fix:use proxy download skills;many chunck download;simple code

* add default config to config.example.json, download skill from github use proxy and token

---------

Co-authored-by: FantasticCode2019 <1443996278@qq.com>
2026-03-13 14:04:02 +08:00
wenjie
8c2a9332c6
fix(security): harden unauthenticated tool-exec paths (#1360)
* fix(security): harden unauthenticated tool-exec paths (GHSA-pv8c-p6jf-3fpp)

- Exec tool: channel-based access control (default deny remote)
- Cron tool: command scheduling restricted to internal channels
- Web fetch: SSRF defense-in-depth (pre-flight + dial-time + redirect checks)
- File permissions: session/state dirs 0700, files 0600
- Registry: inject __channel/__chat_id into tool args (replaces racy SetContext)

28 new security regression tests.

(cherry picked from commit 191446ae19021604d3d5b0d9376b9655ab749105)

* fix(exec): revalidate working_dir before command start

* test(web): allow local oversized payload fixture

---------

Co-authored-by: xj <gh-xj@users.noreply.github.com>
2026-03-11 19:22:20 +08:00
yanhool
95716b106b
feat(web_search): add load balance and failover for api keys (#982)
* feat(web_search): add load balance and failover for api keys

* feat(web_search): add load balance and failover for api keys

* lint

* new iter to get api key

* deleted conflicts
2026-03-10 19:34:11 +11:00
Mauro
b89f6445d1
feat(mcp): tool search tools (#1243)
* feat(mcp): tool search tools

* removed unused call_discovered_tool

* improvements and optimizations

* fix gate mcp enabled

* fix TOCTOU race BM25 cache version check

* fix encapsulation bypass on registry internals

* safety comment on TickTTL

* added more unit tests

* enhanced logs
2026-03-09 18:21:49 +01:00
afjcjsbx
584564af63 fix lint 2026-03-09 11:02:31 +01:00
afjcjsbx
ff54128ab4 refined code 2026-03-09 09:32:21 +01:00
afjcjsbx
c69095457f Merge remote-tracking branch 'refs/remotes/origin/main' into fix/deny-reading-binary-files 2026-03-09 00:30:37 +01:00
Mauro
a32a4e007d
Merge pull request #1143 from blib/bug/parallel-execution
fix: background task results silently dropped
2026-03-07 11:09:19 +01:00
afjcjsbx
674f00ec63 set offset and length in read_file tool 2026-03-07 00:33:27 +01:00
Qiaochu Hu
7f6d95c026
fix: handle zero values in cron schedule type assertions (#1147)
Fixes #1126

Go type assertions return true for zero values, which caused recurring
cron jobs (every_seconds/cron_expr) to silently become one-time 'at' tasks
when LLMs filled unused optional parameters with default values (0).

Changes:
- Add validity checks after type assertions: atSeconds > 0, everySeconds > 0, cronExpr != ""
- This ensures zero values are treated as 'not set' rather than valid schedule values
- Recurring tasks like "remind me every 2 hours" now correctly create recurring jobs
2026-03-06 20:11:08 +08:00
shikihane
c368b5b359
feat(feishu,tools): add outbound media delivery via send_file tool (#1156)
* feat(feishu): implement SendMedia and add send_file tool

Add outbound media support for the Feishu channel so the agent can send
images and files to users via the MediaStore pipeline.

Feishu channel:
- SendMedia dispatches media parts as image or file uploads
- sendImage uploads via Image.Create then sends image message
- sendFile uploads via File.Create then sends file message
- feishuFileType maps extensions to Feishu file_type values

send_file tool:
- New tool lets the LLM send a local file to the current chat
- Validates path, registers file in MediaStore, returns media ref
- Agent loop wires tool registration, MediaStore propagation, and
  context updates

Tested on Radxa Cubie A7A (arm64) with Feishu websocket channel.

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

* fix(agent): publish outbound media regardless of SendResponse flag

The SendResponse flag controls whether the agent loop publishes the
final text response (callers that publish it themselves set this to
false). However, the media publish path was also gated behind this
flag, which meant tool-produced media was silently dropped for normal
channel messages.

Media should be published immediately when a tool returns media refs,
independent of how the text response is delivered.

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

* fix(tools): use magic-bytes MIME detection and add file size limit to send_file

- Replace hardcoded extension-to-MIME map with h2non/filetype (magic
  bytes) + mime.TypeByExtension fallback, consistent with the vision
  pipeline in resolveMediaRefs
- Add configurable max file size check (defaults to config.DefaultMaxMediaSize,
  20 MB) to prevent oversized uploads
- Add tests for magic-bytes detection, extension fallback, size limit,
  and default max size

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

* refactor(agent): add ForEachTool to AgentRegistry for cross-agent tool lookup

Extract the pattern of iterating agents to find a named tool into
AgentRegistry.ForEachTool, simplifying SetMediaStore propagation.

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

* fix(agent,tools): adapt send_file to ctx-based channel injection after upstream refactor

Replace ContextualTool interface (removed upstream) with direct ctx
reading in SendFileTool.Execute, using ToolChannel/ToolChatID helpers.
Remove updateToolContexts which is no longer needed since ExecuteWithContext
already injects channel/chatID into ctx for all tools.

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

* feat(tools): support toggling send_file tool via config

Add SendFileConfig with Enabled field to ToolsConfig, defaulting to
true. Wrap send_file tool registration in loop.go with the config
check, consistent with the pattern used by other tools.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 19:42:52 +08:00
mosir
aa2d6b39f5 refactor(tools): remove redundant kill -9 pattern 2026-03-06 18:34:46 +08:00
mosir
d0f627697e
Merge branch 'sipeed:main' into fix/reload-config-selfkill-guard 2026-03-06 18:27:46 +08:00
wangyanfu2
e0d2be35c2 fix(tools): make exec tool timeout configurable via config
Add TimeoutSeconds field to ExecConfig so the shell command execution
timeout can be configured instead of being hardcoded to 60s.

- Add TimeoutSeconds int field to ExecConfig in pkg/config/config.go
  with json/env tags (PICOCLAW_TOOLS_EXEC_TIMEOUT_SECONDS)
- Set default value of 60s in DefaultConfig() in pkg/config/defaults.go
- Read TimeoutSeconds from config in NewExecToolWithConfig() in
  pkg/tools/shell.go; falls back to 60s when value is 0 or unset
2026-03-06 09:51:58 +08:00
Truong Vinh Tran
4599064f2a Merge upstream/main into feat/searxng
Resolved conflicts in 3 files:
- config/config.example.json: keep both searxng and glm_search configs
- pkg/agent/loop.go: adopt upstream's IsToolEnabled guard + keep searxng fields
- pkg/config/config.go: adopt upstream's ToolConfig embed + keep SearXNG field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:36:05 +01:00
Boris Bliznioukov
968fff07b9
fix: background task results silently dropped
Signed-off-by: Boris Bliznioukov <blib@mail.com>
2026-03-05 13:07:17 +01:00
mosir
5c599d2dac fix(exec): block kill command pattern in safety guard 2026-03-05 12:45:53 +08:00
Boris Bliznioukov
aef1e8e8c4
fix: eliminate data races on shared tool instances (#1080)
* fix: eliminate data races on shared tool instances

Signed-off-by: Boris Bliznioukov <blib@mail.com>

* fix: remove unused indirect dependency on github.com/gdamore/tcell/v2

Signed-off-by: Boris Bliznioukov <blib@mail.com>

* fix: reviewer comments improve context handling for tool execution and ensure defaults for non-conversation callers

Signed-off-by: Boris Bliznioukov <blib@mail.com>

---------

Signed-off-by: Boris Bliznioukov <blib@mail.com>
2026-03-05 09:57:33 +08:00
afjcjsbx
47d7b9b04c resolve makezero linter error 2026-03-04 23:05:52 +01:00
afjcjsbx
1b990d9acd fix lint 2026-03-04 22:59:58 +01:00
afjcjsbx
c87375588e prevent read binary file in tool 2026-03-04 22:39:08 +01:00
Truong Vinh Tran
e4daab8b09 Merge upstream/main into feat/searxng
Resolve merge conflicts to keep both SearXNG and GLM Search
providers. Updated search priority order to:
Perplexity > Brave > SearXNG > Tavily > DuckDuckGo > GLM Search

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:42:03 +01:00
Guoguo
028605cfd0
feat: execute LLM tool calls in parallel for faster response (#1070)
When the LLM returns multiple tool calls, they are now executed
concurrently using goroutines + sync.WaitGroup instead of sequentially.
Results are collected in an indexed slice and processed in original order
to preserve message ordering. MessageTool.sentInRound is changed to
atomic.Bool for thread safety.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:17:28 +08:00
shikihane
b82bb9acc0
feat(tools): add GLM Search (智谱) web search provider (#1057)
* feat(config): add GLMSearchConfig for GLM Search provider

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

* test(tools): add failing tests for GLM Search provider

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

* feat(tools): add GLMSearchProvider for web search

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

* feat(agent): wire GLM Search config into web search tool registration

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:58:12 +08:00
wangyanfu2
7de4cc5ebd fix: add HTTP status code check in BraveSearchProvider
- Add status code validation after reading response body, consistent
  with TavilySearchProvider and PerplexitySearchProvider
2026-03-03 17:54:43 +08:00
daming大铭
4e348e39ac
Merge branch 'main' into mcp-tools-support 2026-03-03 00:17:39 +08:00
Huang Rui
d5370c9605
fix(tools): allow /dev/null redirection and add read/write sandbox split (#967)
* fix(tools): allow /dev/null redirection and add read/write sandbox split

- Remove deny pattern that incorrectly blocked redirects to /dev/null
- Expand block device write pattern to cover nvme, mmcblk, vd, xvd,
  hd, loop, dm-, md, sr and nbd in addition to sd
- Add safe path whitelist for kernel pseudo-devices so workspace path
  check does not reject /dev/null, /dev/zero, /dev/random, /dev/urandom,
  /dev/stdin, /dev/stdout and /dev/stderr
- Add allow_read_outside_workspace config option (default true) so file
  read and list tools are unrestricted while write tools stay sandboxed

Closes https://github.com/sipeed/picoclaw/issues/964
Closes https://github.com/sipeed/picoclaw/issues/965

Signed-off-by: Huang Rui <vowstar@gmail.com>

* feat(tools): add configurable allow patterns and path whitelists

- Add custom_allow_patterns to exec config so users can exempt specific
  commands from deny pattern checks
- Add allow_read_paths and allow_write_paths regex lists to tools config
  for whitelisting specific paths outside the workspace
- Introduce whitelistFs that wraps sandboxFs and falls through to hostFs
  for paths matching whitelist patterns
- Use variadic constructor signatures to keep backward compatibility

Suggested-by: lxowalle
Signed-off-by: Huang Rui <vowstar@gmail.com>

---------

Signed-off-by: Huang Rui <vowstar@gmail.com>
2026-03-02 12:22:02 +08:00
afjcjsbx
e0667304d1 fixed conflicts 2026-03-01 23:44:21 +01:00
Mauro
b86bf5b7ea
Merge branch 'main' into fix/max-payload-size-in-web-fetch 2026-03-01 22:38:16 +01:00
Luca Martinetti
fc9f1ec921
fix: return fetched content to LLM in web_fetch tool (#833)
* fix: return fetched content to LLM in web_fetch tool

WebFetchTool.Execute was setting ForLLM to a summary string
("Fetched N bytes from URL ...") instead of the actual extracted
text. This meant the LLM never saw the page content and could not
answer questions based on fetched web pages.

Return the extracted text in ForLLM so the model can use it.

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

* fix: put full JSON result in ForLLM, summary in ForUser

Accept suggestion from afjcjsbx: the LLM should receive the full JSON
result (including extracted text) while the user sees a short summary.
Update tests to match the new field assignment.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 07:48:11 +11:00
Tong Niu
d6e88da8ba
fix(pkg):do regex precompile insteadd on the fly (#911)
* fix(pkg/providers):do regex precompile insteadd on the fly

* fix(providers): replace HTTP-specific regex with standalone status code matcher

The precompiled HTTP regex used uppercase "HTTP" which never matched
because ClassifyError lowercases the input. Replace it with a
case-insensitive word-boundary pattern that matches any standalone
3-digit status code (300-599), which also subsumes the HTTP/x.x case.

Add test case for standalone status code extraction.

* fix(providers): restore http regex and add standalone status code matcher

Restore the http-prefixed regex (without unnecessary (?i) flag since
input is already lowercased by ClassifyError) as a mid-priority pattern
to reduce false positives. Add a standalone word-boundary matcher as a
fallback for bare status codes like "429". Fix test to use lowercased
input matching the actual calling convention.

* perf(tools): move path regex compilation from per-call to package init

The path regex in guardCommand was compiled on every call. Hoist it
to a package-level var (absolutePathPattern) alongside defaultDenyPatterns
in a single var block, so it is compiled once at init time.

* style(tools): move inline comment to fix golines formatting error
2026-03-01 23:06:31 +11:00
Meng Zhuo
f7136b6a5d
Merge pull request #861 from p3ddd/refactor/modernize
refactor(modernize): apply safe modernize fixes
2026-03-01 15:38:59 +08:00
Tong Niu
44a52c0cf6
fix(tools): close resp.Body on retry cancel and cache http.Client instances (#940)
* fix(tools): close resp.Body on retry cancel and cache http.Client instances

Fix resp.Body leak in DoRequestWithRetry where req.Body (request) was
incorrectly closed instead of resp.Body (response) on context cancel.
Cache http.Client on web search/fetch provider structs and channel
adapters (WeCom, LINE) to avoid per-call allocation overhead.

* fix(channels): preserve original http client timeouts for LINE and WeCom

Split LINE single 60s client into infoClient (10s) for bot info lookups
and apiClient (30s) for messaging API calls. Lower WeCom cached client
base timeout from 60s to 30s (matching uploadMedia), and ensure it is
always >= the configured ReplyTimeout so the per-request context
deadline remains the effective limit.

* refactor(tools): extract timeout consts and deduplicate WebFetchTool constructors

Address PR review feedback from xiaket:
- Define searchTimeout, perplexityTimeout, fetchTimeout, defaultMaxChars,
  and maxRedirects as package-level consts instead of magic numbers.
- Remove misleading "No proxy" comment in NewWebFetchTool.
- Deduplicate NewWebFetchTool by delegating to NewWebFetchToolWithProxy.

* test(utils): add context cancellation test for DoRequestWithRetry

Verify that resp.Body is properly closed when the context is canceled
during retry sleep, covering the C8 resp.Body leak fix.

* fix(utils): close resp in test to satisfy bodyclose linter

* fix(utils): eliminate flakiness in context cancellation retry test

Synchronize cancellation using an onRoundTrip callback from the
transport wrapper instead of a timing-based context timeout. This
ensures the first client.Do completes before cancel fires, so
cancellation always hits during sleepWithCtx.
2026-03-01 16:55:46 +11:00
yuchou87
a2591e03a9 fix: improve MCP tool name collision safety and registry overwrite warning
- MCPTool.Name(): append FNV-32a hash of original (unsanitized) server+tool
  names whenever sanitization is lossy or total length exceeds 64 chars,
  ensuring names that differ only in disallowed characters remain distinct
- ToolRegistry.Register(): emit warn log when a tool registration overwrites
  an existing tool with the same name, making collisions observable
- scripts/test-docker-mcp.sh: switch shebang from #/bin/bash /Users/yuchou/Work/klook-calendar/klook-google-cal-sync/src/googlecalconversrv/bin/start.sh to #  for portability on minimal distros and Nix environments
2026-03-01 12:00:26 +08:00
yuchou87
ef738f4787 fix: address PR review feedback for MCP tools support
- Avoid logging sensitive cfg.Args in ConnectServer; log args_count instead
- Sanitize server/tool name components in MCPTool.Name() to ensure valid
  identifiers for downstream providers (lowercase, [a-z0-9_-] only)
- Add slack as 5th MCP server example in config.example.json
- Move Dockerfile.full and docker-compose.full.yml into docker/ directory
  for consistency with existing docker/Dockerfile and docker/docker-compose.yml
- Fix all Makefile docker-* targets to reference correct compose file paths
- Fix docker/docker-compose.full.yml build context (.. ) and volume paths
- Fix scripts/test-docker-mcp.sh compose file path and replace cowsay test
  with actual @modelcontextprotocol/server-filesystem MCP server test
2026-03-01 10:56:02 +08:00
yuchou87
077d7c8d9b chore: fix lint issues in mcp and agent packages
- Fix gci import ordering in manager.go, manager_test.go
- Fix gofmt formatting in loop.go, manager.go, mcp_tool.go, mcp_tool_test.go
- Fix gofumpt formatting in manager_test.go
- Fix golines line length issues in manager.go, mcp_tool_test.go
- Fix wastedassign: replace redundant zero-value init with var declaration in loop.go
2026-03-01 08:53:13 +08:00
afjcjsbx
b88e590c6c moved fetch limit bytes in config file 2026-02-28 13:34:33 +01:00
Mauro
172e6ebe5f
fix(exec) fail close on invalid deny pattern (#781)
* fix(exec) fail close on invalid deny pattern

* fix: error check

* resolve conflicts
2026-02-28 16:24:26 +08:00
yuchou87
257b0d82b5 Merge branch 'main' into mcp-tools-support
# Conflicts:
#	go.mod
#	go.sum
#	pkg/agent/loop.go
#	pkg/config/config.go
2026-02-28 15:55:25 +08:00
Petrichor
62bdece7f5
chore: resolve conflicts with upstream/main 2026-02-28 12:21:54 +08:00
afjcjsbx
a9a307584b fix: max payload size in web fetch 2026-02-27 18:56:02 +01:00
Avisek Ray
b1a6b3898d
Merge branch 'sipeed:main' into reasoning-chnl 2026-02-27 14:50:14 +05:30
Petrichor
222d1a3086
refactor(modernize): apply safe modernize fixes 2026-02-27 16:35:07 +08:00
mosir
d88700971f merge: resolve conflicts with main 2026-02-26 20:29:24 +08:00
mattn
8a1fb03974
Perf/precompile regex (#687)
* perf: pre-compile regexes at package level

Move regexp.MustCompile calls from inside methods to package-level
variables in web.go (7 regexes) and loader.go (2 regexes).
This avoids repeated compilation on every invocation.

Amp-Thread-ID: https://ampcode.com/threads/T-019c79c3-ea1c-7471-b09d-be90ba0e1ca0
Co-authored-by: Amp <amp@ampcode.com>

* perf: pre-compile regexes at package level

* retain the helpful comment

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-02-26 20:44:03 +11:00
Vinh Tran
2580ef31ca Merge remote-tracking branch 'origin/main' into feat/searxng 2026-02-26 08:21:09 +01:00
mosir
87e674ba15
Merge branch 'sipeed:main' into fix/atomic-file-writes 2026-02-25 23:44:27 +08:00
George Wang
ef1989f12e
Update pkg/tools/web.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-25 23:04:41 +08:00
George Wang
c8a553f109 add proxy support for TavilySearchProvider 2026-02-25 22:37:05 +08:00
mosir
6e754a86f3 merge: resolve conflicts with main 2026-02-25 21:53:04 +08:00
daming大铭
53578da51b
Merge pull request #617 from Zhaoyikaiii/fix/repeated-context-reprocessing
fix: implement caching for system prompt to avoid repeated context reprocessing (fixes #607)
2026-02-25 19:51:23 +08:00
Kai Xia
d8b164b3d4 enable wastedassign
Finds wasted assignment statements.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:31:07 +11:00
Kai Xia
c5e8e19f54 enable misspell
Finds commonly misspelled English words.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:14:19 +11:00
Zhaoyikaiii
1f7cbd9164
fix: cache system prompt with mtime-based auto-invalidation (#607)
Avoid rebuilding the entire system prompt on every BuildMessages() call
by caching the static portion (identity, bootstrap, skills summary,
memory) and only recomputing it when workspace source files change.

Key changes:

- ContextBuilder caches the static prompt behind an RWMutex with
  double-checked locking. Source file changes are detected via cheap
  os.Stat mtime checks so no explicit invalidation is needed.

- Track file existence at cache time (existedAtCache map) so that
  newly created or deleted bootstrap/memory files also trigger a
  rebuild — the old modifiedSince() silently returned false on
  os.IsNotExist.

- Walk the skills directory recursively with filepath.WalkDir to
  catch content-only edits at any nesting depth; directory mtime
  alone misses in-place file modifications on most filesystems.

- ToolRegistry.sortedToolNames() sorts tool names before iteration,
  ensuring deterministic tool definition order across calls — a
  prerequisite for LLM-side prefix/KV cache reuse.

- Merge all context (static + dynamic + summary) into a single
  system message for provider compatibility: the Anthropic adapter
  extracts messages[0] as the top-level system parameter, and Codex
  reads only the first system message as instructions.

- Fix a data race in BuildMessages() where cachedSystemPrompt was
  read without holding the lock in a debug log statement.

- Add tests: single system message invariant, mtime auto-invalidation,
  new-file creation detection, skill file content change, explicit
  InvalidateCache, cache stability, concurrent access (20 goroutines
  x 50 iterations, passes go test -race), and a benchmark.
2026-02-25 15:27:45 +08:00
Achton Smidt Winther
ec6da7a530
fix: reject empty task in spawn tool (#740)
The spawn tool accepts empty strings as valid task arguments, which
causes a subagent to run with no meaningful work. The subagent's
completion message is then routed back to the originating channel
(e.g. Signal, Discord), where the main agent processes it and may
hallucinate an unrelated response that gets sent to users.

Validate that the task parameter is non-empty after trimming whitespace.

Related: #545

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 07:39:49 +11:00
mosir
f86de3cbb9 Merge remote-tracking branch 'sipeed/main' into fix/atomic-file-writes 2026-02-25 00:03:55 +08:00
mosir
7a2d353d0f Merge branch 'main' of github.com:mosir/picoclaw into fix/atomic-file-writes 2026-02-24 23:59:05 +08:00
mosir
11996f1a0b refactor(pkg): move atomic file write to dedicated fileutil package 2026-02-24 23:57:13 +08:00
daming大铭
fd26fa7459
Merge pull request #587 from nayihz/feat_webtool_proxy
feat: add HTTP proxy support for web tools
2026-02-24 23:51:01 +08:00
mosir
4aed3591e7 refactor(pkg/utils): improve WriteFileAtomic with stronger durability guarantees 2026-02-24 23:49:40 +08:00
Kai Xia(夏恺)
100356e8ec
refactor: cleanup dead code and turn on dead code detection in CI (#515)
* cleanup dead code.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* add these two back with flag.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* fix ci

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* remove this confusing line

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* make fmt

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* remove unused method.

picked up by golangci-lint run

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

---------

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-24 21:52:25 +08:00
nayihz
76f2b42d5b feat: improve web proxy handling and coverage 2026-02-24 17:17:14 +08:00
mosir
c56fcedcb1 refactor(pkg/utils): add unified atomic file write utility 2026-02-24 13:22:52 +08:00
Goksu Ceylan
09b1992dd7
fix(security): ensure custom deny patterns extend defaults instead of replacing them (#479)
* fix (security): custom deny patterns denying default patterns

* fix formatting whitespace
2026-02-24 09:02:44 +11:00
Hoshina
6852f24025 fix: address PR #662 review comments (bus drain, context timeouts, onebot leak)
- Drain buffered messages in MessageBus.Close() so they aren't silently lost
- Replace all context.TODO() with context.WithTimeout(5s) across 7 call sites
- Fix OneBot pending channel leak: send nil sentinel in Stop() and handle
  nil response in sendAPIRequest() to unblock waiting goroutines
2026-02-23 21:34:37 +08:00
0x5487
19c698356c
fix(security): workspace sandbox avoid time-of-check/time-of-use (TOCTOU) races (#464)
* chore: Update default host bindings from 0.0.0.0 to 127.0.0.1 for various services and examples.

* config: Update default host bindings to 0.0.0.0 for improved Docker accessibility and add related documentation.

* refactor: reimplement filesystem tools with `os.OpenRoot` for enhanced security and simplified path validation.

* chore: revert other PR content from this branch

* docs: Update Chinese README.

* docs: Update Chinese README.

* docs: Update Chinese README.

* refactor: Reorder filesystem helper functions, extract directory entry formatting logic, and enhance `WriteFileTool`'s result message.

* feat: Enhance `mkdirAllInRoot` to prevent creating directories over existing files and add tests for directory creation functionality.

* Refactor filesystem tools to use a `fileReadWriter` interface for both host and sandboxed I/O, improving atomic writes and error handling.

* refactor: unify filesystem read/write operations with atomic write guarantees and clearer naming.

* refactor: rename `appendFileWithRW` function to `appendFile`

* refactor: unify filesystem access by introducing a `fileSystem` interface and updating tools to use it directly, removing `os.Root` dependency from `sandboxFs`.

* chore: run make fmt

* fix: `validatePath` now returns an error when the workspace is empty.
2026-02-23 20:09:53 +11:00
Vidish
4cc8b90da9
Fix: missing Tavily config in loop.go, and the invalid config param in web_search (#660) 2026-02-23 12:12:34 +08:00
Hoshina
e10b1e1fd4 feat(channels): add MediaSender optional interface for outbound media
Add outbound media sending capability so the agent can publish media
attachments (images, files, audio, video) through channels via the bus.

- Add MediaPart and OutboundMediaMessage types to bus
- Add PublishOutboundMedia/SubscribeOutboundMedia bus methods
- Add MediaSender interface discovered via type assertion by Manager
- Add media dispatch/worker in Manager with shared retry logic
- Extend ToolResult with Media field and MediaResult constructor
- Publish outbound media from agent loop on tool results
- Implement SendMedia for Telegram, Discord, Slack, LINE, OneBot, WeCom
2026-02-23 03:10:57 +08:00
Hoshina
afc7a1988f refactor(bus): fix deadlock and concurrency issues in MessageBus
PublishInbound/PublishOutbound held RLock during blocking channel sends,
deadlocking against Close() which needs a write lock when the buffer is
full. ConsumeInbound/SubscribeOutbound used bare receives instead of
comma-ok, causing zero-value processing or busy loops after close.

Replace sync.RWMutex+bool with atomic.Bool+done channel so Publish
methods use a lock-free 3-way select (send / done / ctx.Done). Add
context.Context parameter to both Publish methods so callers can cancel
or timeout blocked sends. Close() now only sets the atomic flag and
closes the done channel—never closes the data channels—eliminating
send-on-closed-channel panics.

- Remove dead code: RegisterHandler, GetHandler, handlers map,
  MessageHandler type (zero callers across the whole repo)
- Add ErrBusClosed sentinel error
- Update all 10 caller sites to pass context
- Add msgBus.Close() to gateway and agent shutdown flows
- Add pkg/bus/bus_test.go with 11 test cases covering basic round-trip,
  context cancellation, closed-bus behavior, concurrent publish+close,
  full-buffer timeout, and idempotent Close
2026-02-23 00:44:45 +08:00
Vidish
c6865fe852
feat: integrate Tavily search (#340)
* feat: integrate Tavily search

* fix: set include_raw_content to false in Tavily search as wealready get relevant data inside content

* refactor: update Go type declarations to `any`, apply formatting fixes.
2026-02-23 00:30:14 +08:00
King Tai
cb0c8703fb
test(tools,utils): add ToolRegistry unit tests and fix Truncate panic on negative maxLen (#517)
Add comprehensive unit tests for the ToolRegistry covering registration,
lookup, execution, context injection, async callbacks, schema generation,
provider definition conversion, and concurrent access.

Fix a defensive edge case in Truncate where a negative maxLen would cause
a slice bounds panic, and add table-driven tests covering boundary
conditions, zero/negative lengths, and Unicode handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-22 21:40:59 +11:00
yuchou87
672da984e5 Merge branch 'main' into mcp-tools-support 2026-02-22 14:48:07 +08:00
Hoshina
0066602294 fix: golangci-lint run --fix 2026-02-21 16:20:15 +08:00
Hoshina
3df7f70540 fix: golangci-lint fmt 2026-02-21 16:05:39 +08:00
yuchou87
246fdf3f33 fix(mcp): guard against nil result from CallTool
CallTool can return (nil, nil) if the underlying MCP library misbehaves.
Without a nil check, result.IsError would panic. Return an explicit error
ToolResult instead.
2026-02-21 13:40:55 +08:00
yuchou87
d867e86dbe Merge branch 'main' into mcp-tools-support
# Conflicts:
#	config/config.example.json
#	pkg/config/config.go
2026-02-21 13:28:15 +08:00
Meng Zhuo
273a8a2318
Merge pull request #550 from mymmrac/govet-linter
feat(linter): Fix govet linter
2026-02-21 08:20:35 +08:00
Goksu Ceylan
244eb0b47d
fix (security): ExecTool working_dir sandbox escape (#478)
* fix (security) Shell working_dir bypass

* Feedback from @mengzhuo & Discord
- reuse internal security package to validate path
- add tests for workspace escape
2026-02-21 08:15:46 +08:00
Artem Yadelskyi
02b4d9fbe2
feat(linter): Fix govet linter 2026-02-20 22:35:16 +02:00
Artem Yadelskyi
0675ce7c38
feat(fmt): Fix formatting 2026-02-20 20:03:11 +02:00
Artem Yadelskyi
ad8c2d48c8
Merge branch 'main' into fix-formatting
# Conflicts:
#	cmd/picoclaw/main.go
#	pkg/agent/context.go
#	pkg/agent/loop.go
#	pkg/channels/dingtalk.go
#	pkg/channels/feishu_64.go
#	pkg/channels/line.go
#	pkg/channels/manager.go
#	pkg/config/config.go
#	pkg/migrate/migrate_test.go
#	pkg/providers/anthropic/provider_test.go
#	pkg/providers/claude_provider_test.go
#	pkg/providers/http_provider.go
#	pkg/providers/openai_compat/provider.go
#	pkg/providers/protocoltypes/types.go
#	pkg/providers/types.go
2026-02-20 20:02:53 +02:00
Meng Zhuo
5b525f6139
Merge pull request #378 from lunareed720/fix/exec-timeout-process-tree
fix(exec): kill child process tree on timeout to prevent orphaned tasks
2026-02-20 23:32:05 +08:00
Truong Vinh Tran
e7d8975f1c feat: Add SearXNG search provider support
Implements SearXNG as a third web search provider to address Oracle Cloud
datacenter IP blocking issues and provide a cost-free, self-hosted alternative
to commercial search APIs.

Changes:
- Add SearXNGConfig struct with Enabled, BaseURL, and MaxResults fields
- Implement SearXNGSearchProvider with JSON API integration
- Update provider priority: Perplexity > Brave > SearXNG > DuckDuckGo
- Wire SearXNG configuration through agent tool registration
- Add default config values (disabled by default, empty BaseURL)

Benefits:
- Solves DuckDuckGo datacenter IP blocking (138 bytes redirect responses)
- Zero-cost alternative to Brave Search API ($5/1000 queries)
- Self-hosted solution with 70+ aggregated search engines
- Privacy-focused with no rate limits or API keys required
- Ideal for Oracle Cloud, GCP, AWS, and Azure VM deployments

The implementation follows the existing provider interface pattern and
maintains backward compatibility with all existing search providers.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-20 12:02:00 +01:00
Harsh Bansal
d692cc0cc6
Feature: Implement Skill Discovery - With Clawhub Integration and Caching (#332)
* Add Find Skills and Install Skills

* Improvements

* fix file name

* Update pkg/skills/clawhub_registry.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix

* Comments addressed

* Resolve comments

* fix tests

* fixes

* Comments resolved

* Update pkg/skills/search_cache_repro_test.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* minor fix

* fix test

* fixes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-20 18:55:04 +08:00
yinwm
23c39f41df Merge upstream main into feat/refactor-provider-by-protocol
Resolved conflicts:
- pkg/config/config.go: Removed duplicate DefaultConfig() (already in defaults.go)
- pkg/config/defaults.go: Updated Temperature to *float64 (nil default)

Upstream changes included:
- Temperature changed from float64 to *float64 (nil means use provider default)
- New HeartbeatConfig and DevicesConfig
- Various agent and tool improvements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:25:26 +08:00
Artem Yadelskyi
a896831903
feat(fmt): Fix formatting 2026-02-19 22:05:15 +02:00