Commit graph

184 commits

Author SHA1 Message Date
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
Artem Yadelskyi
2038f04d0d
Merge branch 'main' into fix-formatting
# Conflicts:
#	pkg/agent/loop.go
#	pkg/agent/loop_test.go
#	pkg/channels/discord.go
#	pkg/channels/onebot.go
#	pkg/config/config.go
#	pkg/tools/subagent_tool_test.go
2026-02-19 22:04:48 +02:00
cointem
394d1d1197
fix: Templates update (#485)
* fix: add MaxTokens and Temperature fields to AgentInstance and update related logic

* feat: add MaxTokens and Temperature options to SubagentManager and update tool loop logic

* feat: add default temperature handling and update related tests

* feat: allow temperature 0 and distinguish unset

* fix: format MockLLMProvider struct in subagent_tool_test.go
2026-02-19 19:16:37 +01:00
yinwm
68cdafc5f2 refactor(providers): restructure provider creation with protocol-based configuration
- Move provider creation logic to factory_provider.go with protocol-based approach
- Add OpenAIProviderConfig with WebSearch support and embedded ProviderConfig
- Add maxTokensField to OpenAI-compatible provider for configurable token field
- Introduce new providers: Ollama, DeepSeek, GitHubCopilot, Antigravity, Qwen
- Remove redundant CreateProvider function from factory.go
- Add ThoughtSignature field to FunctionCall for tool response handling
- Remove duplicate Name field assignment in tool loop
- Update tests to reflect new provider configuration structure
2026-02-20 00:12:01 +08:00
yinwm
f8f1d539d4 Merge remote-tracking branch 'origin/main' into feat/refactor-provider-by-protocol 2026-02-20 00:11:46 +08:00
yuchou87
a5d2e109bf chore: merge main branch into mcp-tools-support
Resolved conflicts in:
- config/config.example.json: Added empty MCP config block
- pkg/config/config.go: Added MCP config structures to new ToolsConfig
- pkg/agent/loop.go: Integrated MCP tools with new AgentRegistry architecture

MCP tools now register to all agents in the registry during startup.
2026-02-19 19:06:37 +08:00
tpkeeper
12f0c4a6cf
fix: ensure tool name is correctly assigned in LLM iteration(missing tool call name in debug mode logs) (#454)
* fix: ensure tool name is correctly assigned in LLM iteration

* fix: ensure tool name is correctly included in assistant message
2026-02-19 12:06:09 +01:00
yuchou87
47533a00cd style: format code with gofmt 2026-02-19 18:53:24 +08:00
yinwm
ec86b21d3f fix: improve migration logic and reduce code duplication
- Preserve user's configured model during config migration (issue #5)
- Simplify ExtractProtocol using strings.Cut
- Extract NormalizeToolCall to shared utility, removing ~70 lines of duplicate code
- Clean up unused fields in providerMigrationConfig struct

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:22:39 +08:00
mattn
e8afd31b28
Replace \s+ with [^\S\n]+ to preserve newlines (#299) 2026-02-19 02:02:28 +01:00
Artem Yadelskyi
9e120f90ea
feat(fmt): Run formatters 2026-02-18 21:48:23 +02:00
Leandro Barbosa
b1e3b11a5d
Merge pull request #304 from mymmrac/golangci-lint
feat(linters): Added golangci-lint config & CI job
2026-02-18 12:16:58 -03:00
Leandro Barbosa
447c17aeb1 merge: sync upstream/main (PR #213) into feat/multi-agent-routing
Resolve conflicts in pkg/providers/types.go and pkg/agent/loop.go:
- types.go: use protocoltypes aliases from PR #213, keep fallback types
- loop.go: drop old single-agent createToolRegistry (replaced by multi-agent pattern)

Refactor to align with PR #213 patterns:
- instance.go: use NewExecToolWithConfig (accept full config for deny patterns)
- registry.go: pass full config to NewAgentInstance
- loop.go: add Perplexity web search options to registerSharedTools
2026-02-18 11:39:14 -03:00
Artem Yadelskyi
b88f4c9ab5
feat(linters): Fix linter 2026-02-18 16:24:55 +02:00
lxowalle
eda6e37332
feat: Support modifying the command filtering list of the exec tool (#410) 2026-02-18 19:31:15 +08:00
lxowalle
01d694b998
fix: Add comprehensive command injection and system abuse prevention patterns (#401)
* Add comprehensive command injection and system abuse prevention patterns

* fix: Container running as root
2026-02-18 15:33:34 +08:00
Luna Reed
acac1972e6 fix(exec): terminate process tree on timeout 2026-02-18 02:01:29 +08:00
mrbeandev
caf3913347 fix(antigravity): normalize tool calls to avoid empty function names 2026-02-17 20:05:35 +05:30
daming大铭
7b9b8104c8
Merge pull request #225 from yinwm/feat/cron-exec-timeout-config
feat(cron): add configurable execution timeout for cron jobs
2026-02-17 21:12:59 +08:00
yinwm
881999aceb refactor(shell): interpret zero timeout as unlimited execution
Replace unconditional WithTimeout usage with conditional context creation
based on timeout configuration. Zero values now bypass timeout enforcement,
using WithCancel for graceful cancellation while preserving existing timeout
behavior for positive values. Simplifies CronTool initialization by removing
unnecessary conditional timeout assignment.
2026-02-17 21:10:20 +08:00
Hua Audio
f929268ab2
feat: Add Perplexity search provider integration (#138)
* feat: Add Perplexity search provider integration

- Add PerplexityConfig struct to config package
- Add PerplexitySearchProvider implementing SearchProvider interface
- Update WebSearchTool to support Perplexity with priority system (Perplexity > Brave > DuckDuckGo)
- Update agent loop to pass Perplexity config options
- Update config.example.json with Perplexity configuration template
- Uses Perplexity's 'sonar' model for web search capabilities

* Edit config example

* make fmt

---------

Co-authored-by: Hua <zhangmikoto@gmail.com>
2026-02-17 21:02:56 +08:00
yinwm
684e7413e1 Merge remote-tracking branch 'origin/main' into feat/cron-exec-timeout-config 2026-02-17 20:53:31 +08:00
Leandro Barbosa
12007b5670 merge: sync upstream/main into feat/multi-agent-routing
Resolve conflicts:
- pkg/agent/loop.go: integrate context compression, command handling,
  utf8 token estimation, and summarization notification into
  multi-agent routing architecture
- pkg/config/config_test.go: merge imports from both branches
- pkg/agent/loop_test.go: update test to use registry-based sessions
2026-02-16 10:34:55 -03:00
yuchou87
02c1792015 fix(tools): preserve MCP tool InputSchema via JSON marshal/unmarshal
- Handle json.RawMessage and []byte types by direct unmarshal
- Use JSON marshal/unmarshal for struct types to preserve schema
- Add test case for json.RawMessage schema
- Fixes issue where non-map schemas returned empty object

This fixes GitHub Copilot feedback that Parameters() was dropping
tool schema when InputSchema wasn't already map[string]interface{}
2026-02-16 19:50:00 +08:00
yuchou87
20f8bb200b refactor(tools): use MCPManager interface in NewMCPTool constructor
- Change NewMCPTool to accept MCPManager interface instead of concrete *mcp.Manager
- Remove unused mcpPkg import from mcp_tool.go
- Remove newMCPToolForTest helper function as NewMCPTool now accepts interface
- Update all tests to use NewMCPTool directly with MockMCPManager
- Improves testability and follows dependency inversion principle
2026-02-16 19:43:05 +08:00
yuchou87
acb974fcf1 Merge branch 'main' into mcp-tools-support 2026-02-16 16:37:24 +08:00
Goksu Ceylan
e3f65fc3d6
fix(security): block critical symlink workspace escape (#188) 2026-02-16 16:20:35 +08:00
is-Xiaoen
5c321a90de
fix: tighten file perms and enforce Slack ACL checks (#186)
- write config and cron store with 0600 instead of 0644
- check allow list in Slack slash commands and app mentions
- pass workspace restrict flag to cron exec tool

Closes #179
2026-02-16 16:06:39 +08:00
Leandro Barbosa
e77b0a6755
feat: add Codex CLI provider for subprocess integration (#80)
* feat: add Codex CLI provider for OpenAI subprocess integration

Add CodexCliProvider that wraps `codex exec --json` as a subprocess,
analogous to the existing ClaudeCliProvider pattern. This enables using
OpenAI's Codex CLI tool as a local LLM backend.

- CodexCliProvider: subprocess wrapper parsing JSONL event stream
- Credential reader for ~/.codex/auth.json with token expiry detection
- Factory integration: provider "codex-cli" and auth_method "codex-cli"
- Fix tilde expansion in workspace path for CLI providers
- 37 unit tests covering parsing, prompt building, credentials, and mocks

* fix: add tool call extraction to Codex CLI provider

- Extract shared tool call parsing into tool_call_extract.go
  (extractToolCallsFromText, stripToolCallsFromText, findMatchingBrace)
- Both ClaudeCliProvider and CodexCliProvider now share the same
  tool call extraction logic for PicoClaw-specific tools
- Fix cache token accounting: include cached_input_tokens in total
- Add 2 new tests for tool call extraction from JSONL events
- Update existing tests for corrected token calculations

* fix(docker): update Go version to match go.mod requirement

Dockerfile used golang:1.24-alpine but go.mod requires go >= 1.25.7.
This caused Docker builds to fail on all branches with:
  "go: go.mod requires go >= 1.25.7 (running go 1.24.13)"

Update to golang:1.25-alpine to match the project requirement.

* fix: handle codex CLI stderr noise without losing valid stdout

Codex writes diagnostic messages to stderr (e.g. rollout errors) which
cause non-zero exit codes even when valid JSONL output exists on stdout.
Parse stdout first before checking exit code to avoid false errors.

* style: fix gofmt formatting and update web search API in tests

- Remove trailing whitespace in web.go and base_test.go
- Update config_test.go and web_test.go for WebSearchToolOptions API
2026-02-16 11:40:17 +08:00
yinwm
40f90281e5 Merge remote-tracking branch 'upstream/main' into feat/cron-exec-timeout-config 2026-02-15 18:41:54 +08:00
yinwm
82856bc57a feat(cron): add configurable execution timeout for cron jobs
Add a new configuration option `exec_timeout_minutes` under the `tools.cron`
section to control the maximum execution time for cron jobs. The default
timeout is set to 5 minutes, which is appropriate for LLM operations.

The configuration can be set in the config file or via the
`PICOCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES` environment variable. A value of
0 disables the timeout entirely.

This change improves system reliability by preventing cron jobs from running
indefinitely in case of unexpected failures or hanging processes.
2026-02-15 18:41:39 +08:00
yuchou87
91c168db20 feat(mcp): add Model Context Protocol integration
Implement comprehensive MCP support with stdio/HTTP/SSE transports, environment variable configuration (env and envFile), custom headers, tool registration, and automatic resource cleanup. Includes full test coverage and VSCode-compatible configuration.

- Added pkg/mcp/manager.go for server lifecycle management
- Added pkg/tools/mcp_tool.go for tool wrapping
- Integrated into agent loop with cleanup
- Support for envFile loading (.env format)
- Headers injection for HTTP/SSE authentication
- Example configs for filesystem, github, brave-search, postgres
2026-02-15 17:26:36 +08:00
Leandro Barbosa
5e89264536 merge: sync upstream/main into feat/multi-agent-routing
Update registerSharedTools to use new WebSearchToolOptions API and
add hardware tools (I2C, SPI) from upstream. Accept upstream's
new web tools config test.
2026-02-14 10:38:04 -03:00
karan
2720fa71c7
add I2C and SPI tools for hardware interaction (#140)
* add I2C and SPI tools for hardware interaction

- Implemented I2CTool for I2C bus interaction, including device scanning, reading, and writing.
- Implemented SPITool for SPI bus communication, supporting device listing, data transfer, and reading.
- Added platform-specific implementations for Linux and stubs for non-Linux platforms.
- Updated agent loop to register new I2C and SPI tools.
- Created documentation for hardware skills, including usage examples and pinmux setup instructions.

* Remove build constraints for Linux from I2C and SPI tool files.
2026-02-14 16:53:17 +08:00
moveyield
1299b20465 refactor: remove unused min func
Signed-off-by: moveyield <moveyield@outlook.com>
2026-02-14 16:24:20 +08:00
ex-takashima
6463796fa1 fix: update tests to match upstream API changes
Fix web_test.go and config_test.go to use current function signatures
after merging upstream changes (WebSearchToolOptions, BraveConfig).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:32:42 +09:00
ex-takashima
ac79a23e0a style: fix gofmt formatting (CRLF -> LF)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 11:21:47 +09:00
Leandro Barbosa
8a6fb7d9e3 merge: sync upstream/main into feat/multi-agent-routing
Resolve conflicts in loop.go, config.go, config_test.go,
spawn.go, and subagent.go. Integrate upstream ToolResult/AsyncTool
pattern with multi-agent routing features. Rename mockProvider
to mockRegistryProvider in registry_test.go to avoid redeclaration
with upstream's loop_test.go.
2026-02-13 12:24:26 -03:00
Leandro Barbosa
272536a11a feat: add multi-agent routing with declarative bindings
Implement per-agent workspace/model/session isolation with 7-level
priority routing cascade (peer > parent_peer > guild > team > account >
channel > default). Backward compatible - empty agents.list creates
implicit "main" agent from defaults.

Core components:
- routing/agent_id.go: ID normalization with pre-compiled regex
- routing/session_key.go: 4 DM scope modes with identity links
- routing/route.go: RouteResolver with priority-based binding matcher
- agent/instance.go: Per-agent state (workspace, sessions, tools, model)
- agent/registry.go: Agent lifecycle, route resolution, subagent ACL

Integration:
- config.go: AgentModelConfig (flexible JSON), bindings, session config
- loop.go: Complete rewrite for multi-agent dispatch
- Channel adapters: peer_kind/peer_id metadata (telegram, discord, slack)
- spawn.go: Subagent allowlist enforcement per agent

Validated end-to-end with Discord channel-based bindings, default
fallback routing, and per-agent session persistence.
2026-02-13 12:12:33 -03:00
Satyam Tiwari
c86e121688 refactor: update tool registry usage and enhance WebSearchTool execution result handling 2026-02-13 15:41:37 +05:30
Satyam Tiwari
e0a766243e Merge branch 'main' of https://github.com/sipeed/picoclaw 2026-02-13 15:36:43 +05:30
Meng Zhuo
584a3dcc87 misc: fmt code 2026-02-13 17:51:47 +08:00
Satyam Tiwari
2f5849b39d feat: add support for DuckDuckGo and refactor Brave search configuration support the control with config.js 2026-02-13 14:42:55 +05:30
Zhaoyikaiii
cf5a84aac1
merge: resolve conflicts with upstream/main
Merge upstream/main into bugfix/fix-duplicate-telegram-messages.

Conflict resolutions:
- pkg/agent/loop.go: Adopt upstream's processSystemMessage which removes
  runAgentLoop call entirely (subagents now communicate via message tool
  directly). Keep PR's HasSentInRound() check in Run() for normal
  message processing path.
- pkg/tools/message.go: Merge both changes - keep sentInRound tracking
  from PR and adopt upstream's *ToolResult return type with Silent: true.
2026-02-13 16:52:33 +08:00