Commit Graph

672 Commits

Author SHA1 Message Date
daming大铭 faec0261d0 Merge pull request #535 from xiaket/ci-enable-dupl-linter
ci: enable duplication linter in CI
2026-03-02 18:55:35 +08:00
daming大铭 26d1b8e374 Merge pull request #946 from winterfx/fix/preserve-reasoning-content-in-history
fix: preserve reasoning_content in multi-turn conversation history
2026-03-02 16:31:03 +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
Mauro b26337501c fix: error check on state (#864) 2026-03-02 11:59:26 +11:00
Meng Zhuo 83dbff7785 Merge pull request #883 from afjcjsbx/fix/max-payload-size-in-web-fetch
fix: max payload size in web fetch
2026-03-02 08:40:11 +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
Keith d4bc28c113 feat(config): Add support for env var configuration (#896)
* feat(config): Add support for env var configuration

This commit introduces support for two environment variables,
allowing users to override the default paths for picoclaw's home
directory and configuration file.

- `PICOCLAW_CONFIG`: Directly specifies the path to the `config.json` file.
This is initialised first, takes precedence over the hardcoded path, and is ideal
for containerized deployments or custom config management.

- `PICOCLAW_HOME`: Overrides the root directory for all picoclaw data, (except the config)
(e.g., `~/.picoclaw`). This is useful for portable installations or placing
data in non-standard locations.

This change provides greater flexibility for running picoclaw in various environments without
being tied to the default home directory structure.

* `README.md` updated explain PICOCLAW_CONFIG and PICOCLAW_HOME

* docs: translate environment variables section to multiple languages

---------

Co-authored-by: picoclaw <picoclaw@sipeed.com>
2026-03-02 07:41:12 +11:00
美電球 3926585786 Merge pull request #916 from alexhoshina/fix/channel-config-cleanup
docs: sync READMEs, examples, and channel docs to match current config
2026-03-01 22:28:55 +08:00
Hoshina cd3a4e1d1e docs: fix review feedback from PR #916
- Remove Feishu from webhook channel list in README.md and README.zh.md;
  add clarifying note that Feishu uses WebSocket/SDK mode instead
- Replace Chinese text in README.vi.md header with Vietnamese equivalent
- Translate mixed-language WeCom note in README.vi.md to full Vietnamese
- Mark webhook_path as optional (否) in docs/channels/line/README.zh.md
- Remove incorrect yaml struct tags from new-channel example in
  pkg/channels/README.md and README.zh.md (config uses json tags only)
- Fix multi-mode initChannel example to use whatsapp/whatsapp_native
  (matching the "WhatsApp Bridge vs Native" comment) instead of matrix
- Correct ReasoningChannelID description: list the 12 channels that
  have the field and note that PicoConfig does not expose it
2026-03-01 22:21:49 +08: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
GhostC 71bdeb41c9 fix: improve error handling in GitHub Copilot provider (#919)
- Fix ignored error from SendAndWait call
- Improve error message for unimplemented stdio mode with helpful guidance
- Add TODO comment with reference link for future stdio implementation
2026-03-01 22:58:41 +11:00
美電球 1ebfbc1c6b Update docs/channels/line/README.zh.md
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-01 18:59:23 +08:00
Guoguo 25f26f305b docs: update wechat qrcode (#955)
Signed-off-by: Guoguo <i@qwq.trade>
2026-03-01 18:27:37 +08:00
winterfx 9efdde25ad fix: preserve reasoning_content in multi-turn conversation history
The openaiMessage struct and stripSystemParts() were not carrying over
the ReasoningContent field when serializing conversation history for
API requests. This caused thinking models (e.g. kimi-k2.5) to receive
incomplete assistant messages on subsequent turns, resulting in 400
errors from the Moonshot API.

Add the ReasoningContent field to openaiMessage and copy it in
stripSystemParts(). Also add a test to verify reasoning_content is
preserved when sending conversation history.

Fixes #588
Related: #876

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:23:05 +08: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
Kai Xia 434b03ed67 remove wrapper methods
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-03-01 18:24:11 +11:00
Kai Xia 32c864c309 enable dupl check
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-03-01 18:17:32 +11: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
Owen Wu b3c3b02666 fix(onboard): use AGENTS.md template instead of AGENT.md (#931)
* fix(onboard): use AGENTS.md workspace template

* test(onboard): move AGENTS template regression test to new package
2026-03-01 16:25:31 +11:00
DM cadcdc0b41 fix(skills): use registry-backed search for skills discovery (#929)
* fix(skills): use registry-backed search for skills discovery

Signed-off-by: dwizzle204 <25712917+dwizzle204@users.noreply.github.com>

* fix(skills): address review comments for registry search

Signed-off-by: dwizzle204 <25712917+dwizzle204@users.noreply.github.com>

---------

Signed-off-by: dwizzle204 <25712917+dwizzle204@users.noreply.github.com>
Co-authored-by: dwizzle204 <25712917+dwizzle204@users.noreply.github.com>
2026-03-01 15:20:20 +11:00
daming大铭 33f67e8275 Merge pull request #918 from alexhoshina/fix/wecom-resource-leaks
fix(wecom): fix context leak in Start() and data race in processedMsgs
2026-03-01 10:57:07 +08:00
Hoshina c57a9c14e7 docs: sync READMEs, examples, and channel docs to match current config
- Update config.example.json to remove dead webhook_host/webhook_port
  and unused typing/placeholder fields
- Sync all READMEs (en/zh/ja/pt-br/fr/vi) with current channel config
- Update Discord docs: mention_only → group_trigger
- Update LINE, WeCom, WeComApp channel docs
2026-02-28 22:25:37 +08:00
Hoshina e9b4886573 fix(wecom): fix context leak in Start() and data race in processedMsgs
Cancel the constructor-created context before overwriting in Start()
to prevent the original cancel function from becoming unreachable.

Move len(processedMsgs) check inside the write lock to eliminate a
data race, and re-insert the current msgID after map reset to prevent
duplicate processing of the in-flight message.

Applies to both WeComBotChannel and WeComAppChannel.
2026-02-28 22:08:14 +08:00
daming大铭 9c9524f934 Merge pull request #914 from alexhoshina/fix/wecom-context-canceled
fix(wecom): use channel context instead of HTTP request context for async message processing
2026-02-28 21:56:17 +08:00
Hoshina 8e06e2adbd fix(wecom): initialize context in constructors to prevent nil panic in tests
The ctx field was only set in Start(), so tests calling handleMessageCallback
without Start() caused a nil pointer dereference in MessageBus.PublishInbound.
2026-02-28 21:45:08 +08:00
Hoshina 62f59f76e3 fix(wecom): use channel context instead of HTTP request context for async message processing
The HTTP request context is canceled as soon as the handler returns the
response, causing PublishInbound to fail with "context canceled" when
processMessage runs asynchronously in a goroutine. Use the channel's
long-lived context (c.ctx) instead.
2026-02-28 21:31:08 +08:00
afjcjsbx b88e590c6c moved fetch limit bytes in config file 2026-02-28 13:34:33 +01:00
lxowalle 8207c1c7e6 Feat/update migrate (#910)
* * update migrate

* * rename handlers to sources

* * delete dead code

* * fix go test error
v0.2.0
2026-02-28 19:59:17 +08:00
taorye 27e988c484 feat(tui): Add configurable Launcher and Gateway process management (#909)
- Implement POSIX-specific gateway process management in gateway_posix.go
- Implement Windows-specific gateway process management in gateway_windows.go
- Create a menu system in menu.go for user interaction
- Develop model management functionality in model.go, including adding, deleting, and testing models
- Introduce a style configuration in style.go for consistent UI appearance
- Set up the main application entry point in main.go
- Update go.mod and go.sum to include necessary dependencies for tcell and tview
2026-02-28 19:37:18 +08:00
Guoguo 08599f8736 build: add armv6 support to goreleaser (#905)
Add GOARM=6 targets for both picoclaw and picoclaw-launcher builds
to support older ARM devices like Raspberry Pi Zero/1.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:54:23 +08:00
Guoguo 5e028a847c feat: add picoclaw-launcher with web UI for configuration and gateway management (#904)
A standalone web-based tool for managing picoclaw configuration, OAuth
authentication providers, and gateway process lifecycle. Features include
a sidebar layout with i18n (en/zh) and theme support, real-time gateway
log streaming, startup prerequisites checks, and Windows icon embedding.

Co-authored-by: wj-xiao <meetwenjie@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:38:38 +08: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
wenjie 6c8866de6f fix: propagate error when no channels are enabled during startup (#897) 2026-02-28 16:04:44 +08:00
daming大铭 feee0da945 Merge pull request #884 from alexhoshina/fix/memory-leak-whatsapp-reasoning
Fix/memory leak whatsapp reasoning
2026-02-28 14:28:44 +08:00
Hoshina 871b2d7342 fix(whatsapp_native,agent): fixes for resource leak and log noise
- WhatsApp Start(): use deferred cleanup to nil out c.client/c.container
  and disconnect/close resources on any error after struct fields are
  assigned, preventing stale references and double-close in Stop()
- handleReasoning: treat bus.ErrBusClosed as an expected condition
  (DEBUG level) alongside context timeout/cancel, avoiding WARN noise
  during normal shutdown
2026-02-28 14:13:27 +08:00
daming大铭 8529abbc91 Merge pull request #681 from dimensi/bugfix/falsy-context-deadline
fix: distinguish network timeouts from context window errors
2026-02-28 14:12:09 +08:00
Hoshina 7f425f1d11 fix(agent): correct misspelling of 'canceled' 2026-02-28 13:00:40 +08:00
Hoshina d1b10a0004 fix(whatsapp_native,agent): address second round of review feedback
- WhatsApp Send(): detect unpaired state (Store.ID == nil) and return
  ErrTemporary instead of attempting to send while QR login is pending
- handleReasoning: check the returned error type (DeadlineExceeded /
  Canceled) instead of ctx.Err() to decide log level, so pubCtx
  timeouts on a full bus are correctly classified as expected
- Test: fill bus with a short-timeout loop instead of hardcoding the
  buffer size (64), making the test resilient to buffer size changes
2026-02-28 12:54:09 +08:00
Hoshina fc28c2660a fix(whatsapp_native): close TOCTOU race between eventHandler and Stop
Move the stopping check and wg.Add(1) inside reconnectMu in
eventHandler, and set the stopping flag under the same lock in Stop().
This makes the two operations atomic with respect to each other,
preventing the race where:
1. eventHandler checks stopping (false)
2. Stop() sets stopping=true and enters wg.Wait() (wg is 0)
3. eventHandler calls wg.Add(1) → panic or goroutine leak
2026-02-28 12:38:07 +08:00
Petrichor 62bdece7f5 chore: resolve conflicts with upstream/main 2026-02-28 12:21:54 +08:00
Hoshina 9b80fdf885 fix(whatsapp_native,agent): address PR #884 review feedback
- Use c.runCtx for GetQRChannel so the QR producer is canceled on Stop()
- Add atomic stopping guard to prevent wg.Add/wg.Wait race in eventHandler
- Make Stop() context-aware: disconnect client before waiting, respect ctx deadline
- Reduce reasoning publish log noise: use debug level for expected ctx errors
- Add test for handleReasoning when outbound bus is full (timeout path)
2026-02-28 03:05:23 +08:00
afjcjsbx a9a307584b fix: max payload size in web fetch 2026-02-27 18:56:02 +01:00
Hoshina 1d0220f9fd fix(agent): prevent reasoning goroutine accumulation on full bus
Add a 5-second timeout to handleReasoning's PublishOutbound call so
fire-and-forget goroutines do not block indefinitely when the outbound
bus channel is full. Reasoning output is best-effort; on timeout the
publish is abandoned with a warning log instead of holding the
goroutine alive.

Fixes goroutine leak introduced in #802.
2026-02-28 01:39:17 +08:00
Hoshina c7d75a18f8 fix(whatsapp_native): fix goroutine and resource leak in Start/Stop lifecycle
- Move runCtx/runCancel creation before event handler registration and
  QR loop so Stop() can cancel at any point during startup
- Replace blocking QR event loop in Start() with a background goroutine
  that selects on runCtx.Done(), preventing Start() from hanging
  indefinitely when waiting for QR scan
- Track all background goroutines (QR handler, reconnect) with
  sync.WaitGroup; Stop() waits for them to finish before releasing
  client/container resources
- Cancel runCtx on error paths in Start() to avoid leaked contexts

Fixes resource leak introduced in #655.
2026-02-28 01:39:06 +08:00
美電球 cdbc9c4bd6 Merge branch 'sipeed:main' into main 2026-02-28 01:28:39 +08:00
daming大铭 2f4f45080b Merge pull request #882 from sipeed/fix/issue#565
Update config file reference from config.yaml to config.json
2026-02-28 00:41:23 +08:00
美電球 ebfa72a286 Update config file reference from config.yaml to config.json
Closes: #565
2026-02-28 00:36:39 +08:00
daming大铭 1211218b60 Merge pull request #881 from mosir/fix/onboard-include-empty-model
fix(config): keep empty agents.defaults.model in saved config
2026-02-28 00:28:02 +08:00