Commit Graph

1338 Commits

Author SHA1 Message Date
daming大铭 729a878f73 Merge pull request #1636 from lppp04808/feat/subturn-poc
feat(agent): subturn
2026-03-22 21:17:33 +08:00
Administrator 7868c5811a fix(agent): fix subturn panic result, hard abort rollback, and drain bus exit
- spawnSubTurn: set result=nil on panic instead of constructing a non-nil ToolResult
- HardAbort: roll back session history to initialHistoryLength after Finish()
- drainBusToSteering: switch to non-blocking reads after first message so function
  returns promptly when the inbound channel is empty
- remove obsolete documentation files
2026-03-22 20:35:14 +08:00
Administrator 7ba8682ac5 Merge branch 'refactor/agent' into feat/subturn-poc 2026-03-22 19:51:43 +08:00
Administrator f7f27e237a merge: resolve conflicts between refactor/agent and main 2026-03-22 19:21:58 +08:00
daming大铭 0432facffc Merge pull request #1863 from alexhoshina/feat/hook-manager
Feat/hook manager
2026-03-22 14:36:07 +08:00
daming大铭 04def0f10b Merge pull request #1844 from afjcjsbx/fix/scope-steering
fix(agent) scope steering
2026-03-22 14:22:43 +08:00
Administrator 482c88cd15 remove merge conflict markers from .gitignore 2026-03-22 13:48:03 +08:00
Administrator 88d754b172 merge main 2026-03-22 13:47:14 +08:00
daming大铭 931eee92a0 Merge pull request #1853 from kunalk16/feat-configurable-logger
feat(logging): add configurability for log levels preference
2026-03-22 13:27:06 +08:00
Caize Wu 9107740781 Merge pull request #1857 from lc6464/main
docs: clean up README and update QRCode
2026-03-22 11:12:30 +08:00
Mauro c0bb8d6df9 Merge pull request #1617 from yzxlr/codex/fix-1561-heartbeat-template-idle
fix(heartbeat): ignore untouched default template
2026-03-21 20:18:39 +01:00
Mauro e6ea9c4ff3 Merge pull request #1855 from badgerbees/fix/telegram-group-id-validation
fix(identity): support negative integers in isNumeric for Telegram group IDs
2026-03-21 20:16:49 +01:00
Mauro 7a47d7a55c Merge pull request #1782 from biisal/chore/docker-data-in-gitignore
chore: Ignore the `docker/data` directory.
2026-03-21 19:52:25 +01:00
Mauro 5286464bfc Merge pull request #1861 from amirmamaghani/feat/agent-browser-skill-heavy-dockerfile
feat: add agent-browser skill and Dockerfile.heavy
2026-03-21 19:47:07 +01:00
daming大铭 3cd674e3b8 Merge pull request #1865 from sipeed/revert-1752-feat/exec-tool-enhancement
Revert "feat(tools): add exec tool enhancement with background execution and PTY support"
2026-03-22 00:46:56 +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
Hoshina 9978c9550b docs(hooks): inline and translate hook examples 2026-03-21 23:18:29 +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
Amir Mamaghani 520391643b feat: add agent-browser skill and Dockerfile.heavy with full runtime
Add agent-browser skill to the default workspace with complete CLI
reference for browser automation via Chrome/Chromium CDP. The skill
includes a runtime guard that checks for the binary before use.

Add Dockerfile.heavy — a batteries-included container image with:
- Node.js 24 + npm
- Python 3 + pip + uv
- Chromium + Playwright (for agent-browser)
- agent-browser CLI pre-installed
- Non-root picoclaw user (UID/GID 1000)
- Default workspace with all skills
- Persistent workspace volume

This complements the existing minimal Dockerfile and Dockerfile.full
for deployments that need browser automation and rich tool support.
2026-03-21 15:14:32 +01:00
Hoshina 337e43e5a5 feat(agent): add configurable hook mounting 2026-03-21 19:46:16 +08:00
Hoshina cf68c91eca feat(agent): add hook manager foundation 2026-03-21 19:15:10 +08:00
LC f71a6ff76c docs: update alt text of wechat.png with a more meaningful description
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-21 18:52:39 +08:00
lc6464 e2e3e6d5b0 docs: update WeChat QRCode for README 2026-03-21 18:40:10 +08:00
lc6464 ab93c235ae docs: clean up README by removing duplicate sections 2026-03-21 18:36:29 +08:00
Administrator 670b433f1a refactor: replace interface{} with any for improved type clarity 2026-03-21 18:24:56 +08:00
Badgerbees bc0be17e88 fix(identity): support negative integers in isNumeric for Telegram group IDs 2026-03-21 17:09:02 +07:00
Administrator 1bd144ac13 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-21 17:13:26 +08:00
Administrator 087e8519c5 refactor: improve code readability and consistency across multiple files 2026-03-21 17:12:45 +08:00
Kunal Karmakar 073ae4864f Fix spelling 2026-03-21 07:20:59 +00:00
Kunal Karmakar 4c8526d917 Merge branch 'feat-configurable-logger' of https://github.com/kunalk16/picoclaw into feat-configurable-logger 2026-03-21 06:54:55 +00:00
Kunal Karmakar 647071d342 Add default value for config 2026-03-21 06:54:49 +00:00
Kunal Karmakar 92b7687068 Add configurable logger 2026-03-21 06:54:49 +00:00
Kunal Karmakar 650827103d Merge branch 'main' of https://github.com/sipeed/picoclaw into feat-configurable-logger 2026-03-21 06:53:17 +00:00
Kunal Karmakar f35516c5c9 Add default value for config 2026-03-21 06:53:05 +00:00
BeaconCat 6148ccc529 docs(feishu): note that Feishu channel does not support 32-bit devices (#1851)
Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com>
2026-03-21 14:36:51 +08:00
Kunal Karmakar 8490084640 Merge branch 'main' of https://github.com/sipeed/picoclaw into feat-configurable-logger 2026-03-21 05:18:55 +00:00
Kunal Karmakar 329322075d Add configurable logger 2026-03-21 05:18:25 +00:00
Mauro 100720bb74 Merge pull request #1818 from Alix-007/fix/issue-1815-empty-response-message
fix(agent): separate empty-response and tool-limit fallbacks
2026-03-20 23:23:48 +01:00
afjcjsbx 9e344594a2 fix logic 2026-03-20 21:07:07 +01:00
afjcjsbx 827449aff3 fix lint 2026-03-20 20:12:55 +01:00
afjcjsbx 1c6586681d fix(agent) scope steering 2026-03-20 19:44:00 +01:00
BeaconCat 403ceb39be docs: fix inaccuracies, add translations, and expand channel docs (#1837)
## Config field fixes (cross-verified against Go source)
- MaixCam: server_address → host + port
- IRC: use_tls → tls, channels_to_join → channels (all 6 languages)
- WeCom AI Bot: callback port 18791 → 18790
- credential_encryption: base_url → api_base, add required model field,
  remove incorrect passphrase-only mode docs
- providers.md: agents.defaults.model → model_name (×4), remove
  non-existent session.backlog_limit
- migration guide, troubleshooting: agents.defaults.model → model_name
- ANTIGRAVITY_AUTH: fix file path, Go 1.21 → 1.25, model → model_name
- spawn-tasks: fix truncated file, add Heartbeat introduction
- tools_configuration: add Tavily/SearXNG/GLMSearch, exec allow_remote/
  timeout_seconds/custom_allow_patterns, cron allow_command, skills
  github/search_cache, clawhub timeout/max_zip_size/max_response_size
- configuration: fix builtin skills path (build-time embedded, not cwd),
  HEARTBEAT.md marked auto-generated

## Broken link fixes (15 total)
- chat-apps.md: WeCom/Matrix links with wrong relative paths
- providers.md: migration link with extra docs/ prefix
- hardware-compatibility.md: README links with wrong depth (all 5 langs)
- chat-apps.md: WhatsApp dead links → anchor links (zh/ja)

## Getting-started accuracy
- README (all 6 langs): add picoclaw.io as recommended download,
  add missing picoclaw model CLI command
- docker.md: clarify first-run trigger condition (all 6 langs)
- configuration.md: fix builtin skills path description (all 6 langs)

## QQ channel
- Add quick setup via q.qq.com/qqbot/openclaw (one-click bot creation)
- Add manual setup as fallback (all 6 languages)

## Feishu channel
- Update setup flow: WebSocket/SDK mode, no webhook URL needed
- Preserve Lark international domain note (all 6 languages)

## chat-apps.md
- Add Feishu, Slack, IRC, OneBot detail sections (all 6 languages)
- Add MaixCam section to ja/fr/pt-br/vi
- Fix all channel doc links to point to correct language version

## New translations (25 files, 5 docs × 5 languages)
debug.md, credential_encryption.md, hardware-compatibility.md,
ANTIGRAVITY_AUTH.md, ANTIGRAVITY_USAGE.md → zh/ja/fr/pt-br/vi

## Channel docs (6 languages each, 60 new files)
telegram, discord, qq, feishu, maixcam, dingtalk, line, slack, onebot,
wecom/wecom_aibot, wecom/wecom_app, wecom/wecom_bot

Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com>
2026-03-20 22:37:05 +08:00
liqianjie 0fe058254c fix: add fallback DNS resolver for Android with multi-DNS support (#1835)
On Android, /etc/resolv.conf does not exist, causing Go's default DNS
resolution to fail. This adds an init() hook that:

1. Detects missing /etc/resolv.conf (Android environment)
2. Configures a custom resolver with PreferGo: true
3. Supports multiple DNS servers via PICOCLAW_DNS_SERVER env var
   - Semicolon-separated: "8.8.8.8:53;1.1.1.1:53"
   - Single server also works: "8.8.8.8"
   - Auto-appends :53 if port omitted
4. Round-robin rotation across configured servers
5. Defaults to Google DNS + Cloudflare DNS

Also patches http.DefaultTransport to use the custom resolver.
2026-03-20 22:32:21 +08:00
Amir Mamaghani 71134babb9 feat(telegram): stream LLM responses via sendMessageDraft (#1101)
* feat(telegram): stream LLM responses in real-time via sendMessageDraft

Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.

The streaming pipeline threads through all layers:

- StreamingProvider interface (providers/types.go): opt-in ChatStream()
  method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
  SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
  NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
  the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
  opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
  telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
  with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
  manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
  streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
  support streaming, cancels stream on tool calls, skips PublishOutbound
  when Finalize already delivered the message

Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
  failed=true, subsequent Updates become no-ops, Finalize still delivers
  via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config

Closes #1098

* fix(telegram): delete placeholder message when streaming delivers response

When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.

* refactor(streaming): remove dead code and simplify streaming wiring

- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
  creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
  streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
  (Update/Cancel promoted, only Finalize overridden)

* fix(streaming): skip streamer acquisition when SendResponse is false

Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().

* fix(streaming): guard streamer for non-sendable messages, add streaming config

Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().

Add streaming.enabled to Telegram defaults and example config.

* feat(telegram): stream LLM responses in real-time via sendMessageDraft

Implements real-time token streaming to Telegram using the sendMessageDraft
API (telego v1.6.0). Instead of showing only a "Thinking..." placeholder
until the full response arrives, users now see partial LLM output appear
in the chat as it's generated.

The streaming pipeline threads through all layers:

- StreamingProvider interface (providers/types.go): opt-in ChatStream()
  method that receives an onChunk callback with accumulated text
- OpenAI-compatible SSE streaming (openai_compat/provider.go): parses
  SSE events with stream:true, handles text deltas and tool call assembly
- Anthropic native streaming (anthropic/provider.go): uses SDK's
  NewStreaming() for direct Anthropic API connections
- HTTPProvider delegation (http_provider.go): delegates ChatStream to
  the underlying openai_compat provider
- StreamingCapable + Streamer interfaces (channels/interfaces.go):
  opt-in channel capability like TypingCapable/PlaceholderCapable
- Telegram streamer (telegram/telegram.go): BeginStream returns a
  telegramStreamer that throttles sendMessageDraft calls (3s/200 chars)
  with graceful degradation on API errors
- StreamDelegate bridge (bus/bus.go): decouples agent loop from channel
  manager without tight imports
- Manager integration (manager.go): implements StreamDelegate, tracks
  streamActive state, coordinates with placeholder editing
- Agent loop (loop.go): uses ChatStream when both provider and channel
  support streaming, cancels stream on tool calls, skips PublishOutbound
  when Finalize already delivered the message

Graceful degradation:
- Bots without forum/topics mode: first sendMessageDraft error sets
  failed=true, subsequent Updates become no-ops, Finalize still delivers
  via SendMessage. User sees normal non-streaming behavior.
- Non-streaming providers: type assertion fails, falls back to Chat()
- Config opt-out: streaming.enabled (default true) in telegram config

Closes #1098

* fix(telegram): delete placeholder message when streaming delivers response

When streaming was active, the "Thinking..." placeholder message stayed
in the chat because preSend only deleted the tracking entry without
removing the actual Telegram message. Now preSend deletes the placeholder
via the new MessageDeleter interface when streamActive is set.

* refactor(streaming): remove dead code and simplify streaming wiring

- Delete unused Anthropic ChatStream/parseStream (-131 lines) — factory
  creates HTTPProvider for all OpenAI-compat providers including OpenRouter
- Simplify runLLMIteration from 4 to 3 return values (remove unused
  streamed bool)
- Replace managerStreamer struct with finalizeHookStreamer using embedding
  (Update/Cancel promoted, only Finalize overridden)

* fix(streaming): skip streamer acquisition when SendResponse is false

Heartbeat messages set SendResponse=false but the streaming path
was unconditionally acquiring a streamer, causing HEARTBEAT_OK to
leak to Telegram via streamer.Finalize().

* fix(streaming): guard streamer for non-sendable messages, add streaming config

Skip streamer acquisition for heartbeat (NoHistory=true), preventing
HEARTBEAT_OK from leaking to Telegram via streamer.Finalize().

Add streaming.enabled to Telegram defaults and example config.

* fix(picoclaw): add missing closing brace for StreamingProvider interface

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

* fix: resolve golangci-lint formatting issues

Fix gci import ordering in telegram and anthropic provider, and break
long function signature in openai_compat provider to satisfy golines.

* fix: address code review feedback on streaming PR

- Deduplicate Streamer interface: alias channels.Streamer to bus.Streamer
  to prevent type drift across packages
- Increase SSE scanner buffer to 10MB max to handle large single-line
  responses that exceed bufio.Scanner's 64KB default
- Switch draftID generation from math/rand to crypto/rand for
  collision-resistant random IDs
- Add context cancellation check in SSE parsing loop so cancelled
  streams stop processing immediately
- Log Finalize failures with chat_id and content length for debugging
  silent message delivery failures

* feat: make streaming throttle interval and min growth configurable

Move hardcoded streamThrottleInterval (3s) and streamMinGrowth (200)
into StreamingConfig so they can be tuned per deployment via config
or environment variables.

* fix(telegram): use parseTelegramChatID in DeleteMessage and BeginStream

These two functions called undefined parseChatID. Use
parseTelegramChatID with _ for the unused threadID instead of adding
a wrapper function. Fixes all three CI checks.

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

* fix(streaming): set streamActive only after successful Finalize

Move onFinalize hook to run after Streamer.Finalize succeeds, so that
if Finalize fails the streamActive flag stays false and the regular
placeholder fallback path remains available.

Addresses review feedback from @alexhoshina.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:04:14 +08:00
daming大铭 73a683fd16 Merge pull request #1827 from alexhoshina/refactor/agent-loop
Refactor/agent loop
2026-03-20 20:56:53 +08:00
Amir Mamaghani 544940807f feat(pico): add pico_client outbound WebSocket channel (#1198)
* feat(pico): add pico_client outbound WebSocket channel

Add a client-mode counterpart to the existing pico server channel.
pico_client connects to a remote Pico Protocol WebSocket server,
enabling picoclaw to bridge messages with external Pico-compatible
services.

Includes config, factory registration, manager wiring, 8 unit tests,
and a minimal echo-server example for interactive testing.

* fix(pico): address PR #1198 review — goroutine leak, race, auth

- Add per-connection context cancel to picoConn to prevent pingLoop
  goroutine leak on disconnect
- Re-acquire mutex in StartTyping stop closure to avoid stale conn race
- Remove query-param token auth from echo server (header-only)
- Move ListenAndServe to main goroutine where log.Fatal is safe

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

* fix: replace ConsumeInbound with InboundChan select in client test

MessageBus does not expose a ConsumeInbound method. Use a select on
InboundChan() with context cancellation, matching the pattern used in
the bus package tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:43:40 +08:00
daming大铭 54de9ade7d Merge pull request #1822 from alexhoshina/feat/agent-eventbus
Feat/agent eventbus
2026-03-20 20:14:06 +08:00
taorye 75cfee46de Merge pull request #1832 from taorye/main
refactor(tui): enhance TUI configuration for picoclaw-launcher-tui
2026-03-20 19:46:46 +08:00
taorye 955d6e70f1 refactor: update interface types to use 'any' and improve code formatting 2026-03-20 19:41:59 +08:00