Commit graph

1294 commits

Author SHA1 Message Date
Administrator
c18d8a2ecc Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 22:12:51 +08:00
Adi Susilayasa
9a3ca8e54d
feat(provider): add Alibaba Coding Plan and regional Qwen endpoints (#1748)
* feat(provider): add Alibaba Coding Plan and regional Qwen endpoints

- Add Alibaba Coding Plan provider with OpenAI-compatible endpoint
  (https://coding-intl.dashscope.aliyuncs.com/v1)
- Add Coding Plan Anthropic-compatible endpoint
  (https://coding-intl.dashscope.aliyuncs.com/apps/anthropic)
- Add regional Qwen endpoints (qwen-intl, qwen-us)
- Add provider aliases: coding-plan, alibaba-coding, qwen-coding
- Normalize provider names for coding-plan variants

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix(provider): add reviewer-requested fixes for Alibaba Coding Plan

- Add qwen-international, dashscope-intl, dashscope-us aliases to switch case
- Add coding-plan-anthropic case with anthropicmessages.NewProviderWithTimeout
- Add alibaba-coding-anthropic -> coding-plan-anthropic normalization
- Add qwen-international -> qwen-intl and dashscope-us -> qwen-us normalization

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* test(provider): add tests for Alibaba Coding Plan protocol aliases

- Add tests for qwen-international, dashscope-intl, dashscope-us aliases
- Add tests for coding-plan-anthropic and alibaba-coding-anthropic
- Add getDefaultAPIBase tests for all new aliases
- Add normalization tests for new provider aliases

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-19 22:07:30 +08:00
Alix-007
276a0cb92c
fix(agent): rebind provider after /switch model to (#1769)
* fix(agent): rebind provider after model switch

* test(agent): deduplicate switch model mock servers

---------

Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
2026-03-19 21:44:01 +08:00
Alix-007
05c65d2fe7
fix(provider): skip empty anthropic tool names (#1772)
Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
2026-03-19 21:35:17 +08:00
Bijin
38e1fe435a
fix(config): model_list inherits api_key/api_base from providers (#1786)
When both providers and model_list are configured, model_list entries
with empty api_key or api_base now automatically inherit from the
matching provider (matched by protocol prefix in the Model field).

Example: a model_list entry with model='deepseek/deepseek-chat' and
no api_key will inherit from providers.deepseek.api_key.

Explicit model_list values always take precedence.

Changes:
- Add InheritProviderCredentials() in migration.go
- Call it in LoadConfig() after provider-to-model-list conversion
- Add protocolProviderMapping for all 25 supported protocols
- 6 new tests covering inheritance, precedence, and edge cases

Closes #1635
2026-03-19 21:24:46 +08:00
SakoroYou
844a4eefc7
fix(agent): avoid process exit on exec init failure and add regression test (#1784)
* fix(agent): make exec tool init failure non-fatal

* test(agent): add regression test for invalid exec config fallback
2026-03-19 21:11:36 +08:00
Administrator
583c586db6 Merge branch 'main' into feat/subturn-poc 2026-03-19 20:20:31 +08:00
ZHANG RUI
9a25fad20a
Implement the latest long-connection mode for the WeCom AI Bot. (#1295)
* feat(wecom): add WebSocket long-connection support for WeCom AI Bot

- Introduced WeComAIBotWSChannel to handle WebSocket connections.
- Updated NewWeComAIBotChannel to prioritize WebSocket mode when BotID and Secret are provided.
- Enhanced WeComAIBotConfig to include BotID and Secret for WebSocket mode.
- Implemented message handling for text, image, voice, and mixed messages in WebSocket mode.
- Added tests for WebSocket mode functionality and ensured backward compatibility with webhook mode.
- Refactored existing code to improve clarity and maintainability.

* feat(wecom): implement periodic processing hints and enforce WeCom stream deadline

* feat(wecom): update WeCom AI Bot setup instructions and configuration parameters

* feat(wecom): enhance WeCom AI Bot with image handling and media support

* feat(wecom): refactor WeCom AI Bot task management to use req_id for concurrent message handling

* feat(wecom): refactor WeCom AI Bot to manage request states and late replies

* feat(wecom): add response timeout handling and improve WebSocket command acknowledgment

* fix(wecom): improve error handling for late reply proactive push delivery

* refactor(wecom): reorganize WeCom AI Bot configuration fields for improved readability

* fix(wecom): update error message for websocket delivery failure in late reply proactive push

* feat(wecom): implement shared HTTP clients for WeCom image handling and response URL posting

* refactor(wecom): simplify image download and storage process in storeWSImage

* fix(wecom): improve error logging for WebSocket message handling and proactive push delivery

* fix(wecom): enhance WebSocket connection stability and task cancellation handling

* fix(wecom): improve WS image message handling by ensuring proper error response and initializing mediaRefs

* feat(wecom): enhance WeCom AIBot WebSocket handling with message deduplication and support for file and video messages

* refactor(wecom): rename image handling functions to media handling and enhance media type support

* feat(wecom): implement byte-aware content splitting for WeCom AI Bot stream messages

* refactor(wecom): remove max message length constraint from WeCom AIBot WS channel
2026-03-19 20:06:51 +08:00
Cytown
94fcb25039 Merge branch 'main' into version 2026-03-19 18:16:15 +08:00
Mauro
7673b626b3
feat(tool): debug tool usage via channels (#1332)
* feat(tool): debug usage via channel

* set defaults

* fix conflicts
2026-03-19 18:08:50 +08:00
Cytown
cfd3a1b441 Merge branch 'main' into version 2026-03-19 18:04:58 +08:00
Administrator
54889f21a7 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 17:05:09 +08:00
Mauro
a4b5a9eec1
feat(mcp): per server deferred mode (#1654)
* feat(mcp): per server deferred mode

* fix deferred behavior
2026-03-19 17:03:17 +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
kiannidev
310358d3da Merge upstream/main into fix/1323-telegram-endless-typing
Made-with: Cursor
2026-03-19 10:53:50 +02:00
Administrator
532ea4b56c Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 16:47:35 +08:00
美電球
828971d549
Feat/qq local file upload (#1722)
* feat(qq): support media uploads and inbound attachments

* docs(qq): document media size limit settings

* chore(web): add QQ media size limit hints

* fix(qq): demote botgo heartbeat logs

* style(qq): fix lint issues
2026-03-19 16:27:34 +08:00
Cytown
a8ce992429
refactor[gateway]: just reload the changed channels on reload occurred (#1773) 2026-03-19 15:28:52 +08:00
Administrator
24a382bc0a merge main 2026-03-19 13:53:31 +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
Cytown
2a6ade0fe4
feat: add /reload to gateway api and command (#1725)
* feat: add /reload to gateway api and command

* prevent duplicate reload request in same time
2026-03-19 13:42:36 +08:00
Administrator
e801ccb674 Merge branch 'upstream-main' into feat/subturn-poc 2026-03-19 13:09:05 +08:00
Administrator
ce311be70b feat(subturn): add configurable runtime parameters under agents.defaults
Replace hardcoded constants with config-driven parameters in agents.defaults:
- MaxDepth, MaxConcurrent, DefaultTimeout, DefaultTokenBudget, ConcurrencyTimeout
- Support JSON config and env vars (PICOCLAW_AGENTS_DEFAULTS_SUBTURN_*)
- Add getSubTurnConfig() for runtime config resolution with defaults
- Apply defaultTokenBudget when no explicit budget is provided

Rationale: SubTurn is agent execution infrastructure, not a tool, so it belongs
in agents.defaults rather than tools config.

Example:
{
  "agents": {
    "defaults": {
      "subturn": {
        "max_depth": 5,
        "max_concurrent": 10,
        "default_timeout_minutes": 10
      }
    }
  }
}
2026-03-19 13:08:46 +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
01c2f8d608 refactor(subturn): remove redundant system prompt handling in runTurn function 2026-03-19 11:10:44 +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
Liu Yuan
e73d9d959e
feat(config): support multiple API keys for failover (#1707)
* feat(config): support multiple API keys for failover

Add api_keys field to ModelConfig to support multiple API keys with
automatic failover. When multiple keys are configured, they are expanded
into separate model entries with fallbacks set up for key-level failover.

Example config:
  {
    "model_name": "glm-4.7",
    "model": "zhipu/glm-4.7",
    "api_keys": ["key1", "key2", "key3"]
  }

Expands internally to:
  - glm-4.7 (key1) -> fallbacks: [glm-4.7__key_1, glm-4.7__key_2]
  - glm-4.7__key_1 (key2)
  - glm-4.7__key_2 (key3)

Backward compatible: single api_key still works as before.

* fix(providers): change cooldown tracking from provider to ModelKey

This enables proper key-switching when multiple API keys share the same
provider. Previously, when one key failed, all keys were blocked because
cooldown was tracked per-provider.

Now each (provider, model) combination has independent cooldown, allowing
fallback to alternate keys when one is rate limited.

Includes TestMultiKeyWithModelFallback and related failover tests.
2026-03-19 00:57:20 +08:00
Liqiang Lau
08f305d712
feat: add IsLark field to FeishuConfig to switch between Feishu and Lark domains (#1753)
* feat(feishu): add Lark (international) support via IsLark config field

Add IsLark field to FeishuConfig to switch between Feishu and Lark
domains. Also fix domain inconsistency where WS client defaulted to
LarkBaseUrl while HTTP client used FeishuBaseUrl.

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

* docs: update documentation and web UI for Lark support

Add is_lark field to config example, feishu docs, i18n translations,
and web frontend form.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 00:29:55 +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
美電球
899558bbfa
Feat/issue 1218 agent md context structure (#1705)
* feat(agent): add structured agent definition loader

Parse AGENT.md frontmatter into a runtime definition and pair it with SOUL.md while keeping a legacy AGENTS.md fallback for transition.

Refs #1218

* refactor(agent): build context from structured agent files

Use AGENT.md and SOUL.md as the structured bootstrap source, ignore IDENTITY.md for structured agents, remove USER.md from the new context flow, and update pkg/agent tests accordingly.

Refs #1218

* refactor(onboard): switch workspace templates to AGENT.md

Replace the legacy AGENTS.md, IDENTITY.md, and USER.md templates with a structured AGENT.md plus SOUL.md, and update the onboard template test to assert the new generated files.

Refs #1218

* docs(readme): update workspace layout for AGENT.md

Refresh the documented workspace tree across the README translations so onboarding now points to AGENT.md and SOUL.md instead of the retired AGENTS.md, IDENTITY.md, and USER.md files.

Refs #1218

* feat(agent): restore workspace USER.md context

* docs(readme): document workspace USER.md layout

* fix: sort agent definition imports for gci
2026-03-18 22:42:57 +08:00
Darren.Zeng
54654d2794
fix(anthropic): skip tool calls with empty names to prevent API errors (#1739)
When building parameters for Anthropic API calls, tool calls with empty
names would cause 400 Bad Request errors with the message:
'tool_use.name: String should have at least 1 character'

This fix adds a check to skip tool calls that have empty names, preventing
the API error and allowing the conversation to continue normally.

Fixes #1658
2026-03-18 21:55:01 +08:00
Alexander
12f4029610
feat: telegram use parse mode ModeMarkdownV2 instead of ModeHTML (#1018)
* feat: telegram use parse mode ModeMarkdownV2 instead of ModeHTML

* handle expandable block quotation starts, add test for all md2 formats

* fix: linter issue

* feat: added flag use_markdown_v2, corrected config, updated
documentation

* move parseChatID to parser_markdown_to_html

* fix: tests and linter issues

* fix: case with ~

* test: fixed Test_markdownToTelegramMarkdownV2

* fix: regex block-quote line  >

* fix: linter issues

* fix: send chunk param mismatched, in edit msg use HTML parse mode too

* fix: remove from .gitignore redundant comment
2026-03-18 21:29:21 +08:00
Vast-stars
3e9b7ce9c1
fix(feishu): invalidate cached token on auth error to enable retry recovery (#1318)
The Lark SDK v3's built-in token retry loop does not clear stale tokens
from cache when the server returns error 99991663 (tenant_access_token
invalid), causing all API calls to fail until the token naturally
expires (~2 hours).

- Add tokenCache struct (implementing larkcore.Cache) with
  Get/Set/InvalidateAll methods and proper expired-entry cleanup
- Wire custom cache into lark.NewClient via WithTokenCache()
- Add invalidateTokenOnAuthError helper called in all API methods
2026-03-18 19:07:49 +08:00
Alex
578f90855e
feat: Add Novita provider support (#1677)
* Add Novita provider support

- Add 'novita' prefix to normalizeModel switch in openai_compat provider
- Add Novita provider to all_supported_vendors table in README.md
- Add test cases for Novita model prefix stripping

Novita endpoint: https://api.novita.ai/openai
Default models: deepseek/deepseek-v3.2, zai-org/glm-5, minimax/minimax-m2.5

* feat: complete Novita provider integration

* chore: drop README changes from Novita PR

* fix: remove duplicate function declarations in openai_compat provider

The functions buildToolsList, SupportsNativeSearch, and isNativeSearchHost
were declared twice, causing compilation failures in all CI checks.

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

* fix: break long line in novita test to satisfy golines linter

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 18:29:27 +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
dev-miro26
c07f5c948f
refactor: centralize environment variable key constants (#1730)
* refactor: centralize environment variable key constants

* refactor: update environment variable constants and usage in gateway
2026-03-18 18:03:24 +08:00
badgerbees
a1e8ee56f0
fix(telegram): improve HTML chunking and preserve word boundaries (#1651)
* fix(telegram): improve HTML chunking and preserve word boundaries

* fix(telegram): address copilot feedback, filter empty chunks and add word-boundary regression test

* style(telegram): fix gofmt and gci lint errors in tests

* fix to feedback
2026-03-18 16:44:30 +08:00
Administrator
777230dcd1 feat(agent): implement /subagents command and fix sub-turn observability
- Added `/subagents` platform command to visualize the active task tree.
- Implemented GetAllActiveTurns and FormatTree in AgentLoop to support cross-session observability.
- Fixed a bug where sub-turns spawned via tools were not registered in the global `activeTurnStates` map, making them invisible to system queries.
- Enhanced tree rendering logic to identify and display "orphaned" subagents (children that outlive their parent turns).
- Registered the new command in `builtin.go` and injected the turn state provider into the commands runtime.

Modified Files:
- pkg/agent/turn_state.go: Added TurnInfo snapshotting and recursive tree formatting.
- pkg/agent/loop.go: Injected GetActiveTurn hook and implemented multi-root forest rendering.
- pkg/agent/subturn.go: Added child turn registration into activeTurnStates.
- pkg/commands/cmd_subagents.go: New command implementation.
- pkg/commands/builtin.go: Command registration.
2026-03-18 14:46:20 +08:00
Cytown
e6ebeaed13
feat(web): implement macOS app feature and file logger (#1723) 2026-03-18 14:43:58 +08:00
Administrator
e20ff43f8b fix(agent): resolve subturn deadlocks, panics and context retry state
This commit addresses several critical concurrency and state management bugs within the SubTurn execution and delivery logic.

1. Fix Goroutine Leak & Deadlock in deliverSubTurnResult:
   - Replaced non-blocking select with a safe blocking select that listens to `resultChan` and a new `<-parentTS.Finished()` channel.
   - This ensures results are not arbitrarily dropped when the channel is full (preventing orphaned valid results), while also guaranteeing the child goroutine safely unblocks and exits if the parent finishes execution early.

2. Prevent "Send on Closed Channel" Fatal Panics:
   - Removed `close(pendingResults)` and `drainPendingResults` from `turnState.Finish()`.
   - The pendingResults channel is now naturally garbage collected, completely eliminating the race condition panic when a child attempts delivery at the exact moment the parent finishes.
   - Added a `defer recover()` failsafe inside deliverSubTurnResult to gracefully emit Orphan events in extreme edge cases.

3. Fix Truncation Recovery Prompt Drop:
   - Fixed the runTurn truncation retry logic by introducing an explicit `promptAlreadyAdded` boolean.
   - Ensures that the dynamically generated `recoveryPrompt` is correctly injected into the LLM history sequence on subsequent iterations, adhering to API roles without duplicating arrays.

4. Test Suite Stabilization:
   - Fixed TestDeliverSubTurnResultNoDeadlock to accurately wait for deterministic deliveries instead of racing timeouts.
   - Replaced defunct closed-channel tests with TestFinishedChannelClosedState matching the new Finished() mechanism.
   - Fixed the Finish(true) parameter in TestGrandchildAbort_CascadingCancellation to correctly validate Context cascade behavior.
   - All tests now pass cleanly without hanging or emitting false positives.
2026-03-18 13:10:36 +08:00
Administrator
c7ea018a73 fix(agent): prevent duplicate history during subturn context recoveries
Problem:
During subturn context limit or truncation recoveries, the recovery loops repeatedly
called `runAgentLoop` with the same or modified `UserMessage`. Because `runAgentLoop`
unconditionally adds the `UserMessage` to the session history, this resulted in:
1. Duplicate User Messages polluting the history upon `context_length_exceeded` retries.
2. The possibility of injecting empty User Messages if `opts.UserMessage` was artificially blanked out to work around the duplication.
3. Messy or duplicate entries during `finish_reason="truncated"` recovery injections.

Solution:
- Introduce `SkipAddUserMessage` boolean to `processOptions` to explicitly control whether the agent loop should write the user prompt to history.
- Add an explicit `opts.UserMessage != ""` check in `runAgentLoop` to prevent polluting history with empty message content.
- In `subturn.go`'s recovery loop, set `SkipAddUserMessage: contextRetryCount > 0` to skip writing the user message on context
2026-03-18 12:18:32 +08:00
dataCenter430
f79469c19d
Add model-native search (prefer_native) for OpenAI/Codex (#1618)
* config: add prefer_native and NativeSearchCapable for model-native search

* providers: implement native web search for OpenAI and Codex

* agent: use provider-native search when prefer_native and supported

* tests: add coverage for model-native search

* fix: Golang lint errors

* fix: update the code based on the review

* fix: update codex_provider_test
2026-03-18 11:55:30 +08:00
Zenix
f12c09b767
fix: retry on dimension failure for tg media upload (#1409) 2026-03-18 10:46:35 +08:00
Meng Zhuo
cefa140bd2
Merge pull request #1622 from afjcjsbx/feat/markdown-output-format-web-fetch
feat(tool): markdown format in web_fetch tool output
2026-03-18 09:15:13 +08:00
Mauro
513537d230
Merge pull request #1702 from Alix-007/fix/issue-1153-model-round-robin-cleanbase
fix(config): start model round robin from the first match
2026-03-17 22:28:48 +01:00
Mauro
74f2a1513e
Merge pull request #1479 from securityguy/fix/claude-cli-error-surfacing
fix(claude_cli): surface stdout in error when CLI exits non-zero
2026-03-17 22:16:42 +01:00
Mauro
f901218b43
Merge pull request #1640 from argobell/main
fix(logger): append fields to fileEvent instead of event in file logger block
2026-03-17 22:12:00 +01: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
13d4801601 Merge branch 'main' into feat/markdown-output-format-web-fetch 2026-03-17 17:21:14 +01:00
afjcjsbx
8f460726cc fix lint + error check 2026-03-17 17:14:23 +01:00
juju
9c31b0ca95
fix: Fixed the bug where the bus was closed and consumers had unfinished messages. (#1179)
* fix: Fixed the bug where the bus was closed and consumers had unfinished messages.

* fix: remove unnecessary blank line in Close method

* fix: refactor message bus and channel handling for improved performance and reliability

* fix: improve message handling and bus closure logic for better reliability

* fix: reduce sleep duration in agent loop for improved responsiveness

* fix the test case
2026-03-18 00:12:12 +08:00
juju
f776611e29
feat(cron): refactor scheduler to event-driven model and add unit tests (#1313)
* feat(cron): enhance CronService with wake channel and improve job scheduling logic

* fix(cron): update file permission mode to use octal notation in test and fix some lint errors

* fix(cron): improve wake channel handling and enhance concurrency in tests
2026-03-18 00:02:51 +08:00
Mauro
3791f06faf
Merge branch 'main' into feat/markdown-output-format-web-fetch 2026-03-17 16:37:22 +01:00
Alix-007
c639e2c216
feat(agent): include current sender in dynamic context (#1696)
* feat(agent): include current sender in dynamic context

* test(agent): keep current-sender regression ASCII-only

---------

Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
2026-03-17 23:31:56 +08: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
f8defe3ae1 feat(agent): implement graceful finish vs hard abort for SubTurn lifecycle
Problem:
When parent turn finishes early, all child SubTurns receive "context canceled"
error,because child context was derived from parent context.

Solution:
Implement a lifecycle management system that distinguishes between:
- Graceful finish (Finish(false)): signals parentEnded, children continue
- Hard abort (Finish(true)): immediately cancels all children

Changes:
- turn_state.go:
  - Add parentEnded atomic.Bool to signal parent completion
  - Add parentTurnState reference for IsParentEnded() checks
  - Modify Finish(isHardAbort bool) to distinguish abort types

- subturn.go:
  - Add Critical bool to SubTurnConfig (Critical SubTurns continue after parent ends)
  - Add Timeout time.Duration for SubTurn self-protection
  - Use independent context (context.Background()) instead of derived context
  - SubTurns check IsParentEnded() to decide whether to continue or exit

- loop.go:
  - Call Finish(false) for normal completion (graceful)
  - Add IsParentEnded() check in LLM iteration loop

- steering.go:
  - HardAbort calls Finish(true) to immediately cancel children

Behavior:
- Normal finish: parentEnded=true, children continue, orphan results delivered
- Hard abort: all children cancelled immediately via context
- Critical SubTurns: continue running after parent finishes gracefully
- Non-Critical SubTurns: can exit gracefully when IsParentEnded() returns true
2026-03-17 23:06:16 +08:00
Administrator
e05d2620e1 Added tests to verify SubTurn context cancellation behavior when parent
finishes early - identified need for Critical+heartbeat+timeout mechanism.
2026-03-17 22:31:56 +08:00
Alix-007
fcf406bf2e fix(config): start model round robin from the first match 2026-03-17 21:59:04 +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
Administrator
2fec249be1 refactor(agent): improve SubTurn error handling and logging
- Fix context cancellation check order in concurrency timeout
  - Add structured logging for panic recovery
  - Replace println with proper logger for channel full warning
  - Simplify tool registry initialization logic
  - Remove unused ErrConcurrencyLimitExceeded error
2026-03-17 20:02:56 +08:00
Cytown
afe22c5adf
bug fix: gateway should not start when gateway server is not running (#1562) 2026-03-17 19:07:36 +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
wenjie
8a44410e37
feat: add web gateway hot reload and polling state sync (#1684)
* feat(gateway): support hot reload and empty startup

- extract gateway runtime into pkg/gateway
- add gateway.hot_reload config with default and example values
- allow starting the gateway without a default model via --allow-empty
- stop treating missing enabled channels as a startup error
- update related tests

* feat: replace gateway SSE updates with polling-based state sync

- remove gateway SSE broadcasting and event endpoint
- add polling-based gateway status refresh with stopping state handling
- detect when gateway restart is required after default model changes
- resolve gateway health and websocket proxy targets from configured host
- update gateway UI labels and add backend/frontend test coverage
2026-03-17 18:46:00 +08:00
Mauro
8a8cc35645
Merge pull request #1663 from hyperwd/fix/glm-nil-input
fix(providers): handle nil input in GLM series tool_use blocks
2026-03-17 08:42:17 +01: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
Cytown
e41423483e
add systray ui for all platform (#1649)
* add systray ui for all platform

* update from getlantern/systray to fyne.io/systray for fix test
2026-03-17 14:12:32 +08:00
Administrator
a26a7db7d2 moved turnState and related code from subturn.go to a new turn_state.go file
Created /pkg/agent/turn_state.go (246 lines) containing:
  - turnStateKeyType and context key management
  - turnState struct definition
  - TurnInfo struct and GetActiveTurn() method
  - newTurnState(), Finish(), and drainPendingResults() methods
  - ephemeralSessionStore implementation
  - All context helper functions (withTurnState, TurnStateFromContext, etc.)

  Updated /pkg/agent/subturn.go (428 lines) by:
  - Removing the moved turnState struct and methods
  - Removing unused imports (sync, session)
  - Keeping SubTurn spawning logic, config, events, and result delivery

  All tests pass and the code compiles successfully.
2026-03-17 14:11:38 +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
Zane Tung
8d97896a0d fix(providers): handle nil input in GLM series tool_use blocks
- add defensive nil check for tool call Arguments field
- replace nil input with empty object to comply with Anthropic spec
- prevent API errors when GLM models return null input in tool_use blocks

Zhipu AI's GLM series models may return tool_use blocks with null input field,
which causes their API to reject subsequent requests with error:
"ClaudeContentBlockToolResult object has no attribute id"

This fix ensures compatibility by converting nil inputs to empty objects {},
matching the Anthropic Messages API specification while maintaining backward
compatibility with other providers.
2026-03-17 12:16:24 +08:00
xiaoen
c63c6449b4 fix(agent): forceCompression recovers from single oversized Turn
When the entire session history is a single Turn (e.g. one user message
followed by a massive tool response), findSafeBoundary returns 0 and
forceCompression previously did nothing — leaving the agent stuck in
a context-exceeded retry loop.

Now falls back to keeping only the most recent user message when no
safe Turn boundary exists. This breaks Turn atomicity as a last resort
but guarantees the agent can recover.

Also updates docs/agent-refactor/context.md to document this behavior.

Ref #1490
2026-03-17 10:23:16 +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
Cytown
be4a33cc15
refactor gateway/helpers and add server.pid to health (#1646) 2026-03-17 09:35:52 +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
Mauro
dfafdf7c53
Merge pull request #1570 from alexhoshina/fix/cron-deliver-default-false
fix(cron): default scheduled jobs to agent execution
2026-03-16 21:05:06 +01:00
Administrator
672d11c7d4 fix(agent): prevent double result delivery and panic bypass in SubTurn
- Fix synchronous SubTurn calls placing results in pendingResults channel,
  causing double delivery. Now only async calls (Async=true) use the channel.
- Move deliverSubTurnResult into defer to ensure result delivery even when
  runTurn panics. Add TestSpawnSubTurn_PanicRecovery to verify.
- Fix ContextWindow incorrectly set to MaxTokens; now inherits from
  parentAgent.ContextWindow.
- Add TestSpawnSubTurn_ResultDeliverySync to verify sync behavior.
2026-03-16 23:48:51 +08:00
Administrator
3c2d373a5c fix(agent): resolve race conditions and resource leaks in SubTurn
Critical fixes (5):
- Fix turnState hierarchy corruption in nested SubTurns by checking context
  before creating new root turnState in runAgentLoop
- Fix deadlock risk in deliverSubTurnResult by separating lock and channel ops
- Fix session rollback race in HardAbort by calling Finish() before rollback
- Fix resource leak by closing pendingResults channel in Finish() with recovery
- Add thread-safety docs for childTurnIDs and isFinished fields

Medium priority fixes (5):
- Move globalTurnCounter to AgentLoop.subTurnCounter to prevent ID conflicts
- Improve semaphore acquisition to ensure release even on early validation failures
- Document design choice: ephemeral sessions start empty for complete isolation
- Add final poll before Finish() to capture late-arriving SubTurn results
- Remove duplicate channel registration in spawnSubTurn to fix timing issues

Testing:
- Add 6 new tests covering hierarchy, deadlock, ordering, channel lifecycle,
  final poll, and semaphore behavior
- All 12 SubTurn tests passing with race detector

This resolves 10 critical and medium issues (5 race conditions, 2 resource leaks,
3 timing issues) identified in code review, bringing SubTurn to production-ready state.
2026-03-16 22:54:01 +08:00
Administrator
6b5d7e3fd7 fix(agent): resolve critical race conditions and resource leaks in SubTurn
- Fix turnState hierarchy corruption when SubTurns recursively call runAgentLoop
  by checking context for existing turnState before creating new root
- Fix deadlock risk in deliverSubTurnResult by separating lock and channel operations
- Fix session rollback race in HardAbort by calling Finish() before rollback
- Fix resource leak by closing pendingResults channel in Finish() with panic recovery
- Add thread-safety documentation for childTurnIDs and isFinished fields
- Move globalTurnCounter to AgentLoop.subTurnCounter to prevent ID conflicts
- Improve semaphore acquisition to ensure release even on early validation failures
- Document design choice: ephemeral sessions start empty for complete isolation
- Add 5 new tests: hierarchy, deadlock, order, channel close, and semaphore
2026-03-16 22:37:21 +08:00
Administrator
acd436acfe feat(agent): add session state rollback on hard abort
- Add initialHistoryLength field to turnState to snapshot session state at turn start
- Save initial history length in runAgentLoop when creating root turnState
- Implement session rollback in HardAbort via SetHistory, truncating to initial length
- Add TestHardAbortSessionRollback to verify history rollback after abort
- Import providers package in subturn_test.go for Message type

This ensures that when a user triggers hard abort, all messages added during
the aborted turn are discarded, restoring the session to its pre-turn state.
2026-03-16 21:49:58 +08:00
Administrator
1236dd9e6d feat(agent): add concurrency semaphore and hard abort for SubTurn
- Add maxConcurrentSubTurns constant (5) and concurrencySem channel to turnState
- Acquire/release semaphore in spawnSubTurn to limit concurrent child turns per parent
- Add activeTurnStates sync.Map to AgentLoop for tracking root turn states by session
- Implement HardAbort(sessionKey) method to trigger cascading cancellation via turnState.Finish()
- Register/unregister root turnState in runAgentLoop for hard abort lookup
- Add TestSubTurnConcurrencySemaphore to verify semaphore capacity enforcement
- Add TestHardAbortCascading to verify context cancellation propagates to child turns
2026-03-16 21:03:58 +08: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
Dmitrii Balabanov
64ceb5ab76 fix(logger): show first/last 4 chars of bot token for identification 2026-03-16 12:48:28 +02:00
Dmitrii Balabanov
8fc36a4f9b fix(logger): mask bot tokens in 3rd-party logger output 2026-03-16 12:48:28 +02:00
Dimitrij Denissenko
26fa98c359 Align rendering with Matrix' CommonMark guidelines 2026-03-16 09:07:04 +00:00
Argobell
1ace296b91 fix: use fileEvent instead of event when appending fields for file logger
Co-authored-by: argobell <183611258+argobell@users.noreply.github.com>
2026-03-16 16:46:13 +08:00
xiaoen
b768dab822 test(agent): use realistic session data in context retry test
Session history only stores user/assistant/tool messages — the system
prompt is built dynamically by BuildMessages. Remove the incorrect
system message from TestAgentLoop_ContextExhaustionRetry test data
to match the real data model that forceCompression operates on.
2026-03-16 14:48:35 +08:00
xiaoen
7c1a1c2c1a style(agent): fix gci comment alignment in test 2026-03-16 14:48:35 +08:00
xiaoen
edbdc3bcf1 fix(agent): findSafeBoundary returns 0 for single-Turn history
When the entire history is a single Turn (one user message followed by
tool calls and responses, no subsequent user message), the only Turn
boundary is at index 0. Previously the fallback returned targetIndex,
which could land on a tool or assistant message — splitting the Turn.

Return 0 instead, so callers (forceCompression, summarizeSession) see
mid <= 0 and skip compression rather than cutting inside the Turn.
2026-03-16 14:48:35 +08:00
xiaoen
8034ee7be1 fix(agent): correct media token arithmetic and tool call double-counting
Two estimation bugs fixed:

1. Media tokens were added to the chars accumulator before the chars*2/5
   conversion, resulting in 256*2/5=102 tokens per item instead of 256.
   Fix: add media tokens directly to the final token count, bypassing
   the character-based heuristic.

2. estimateMessageTokens counted both tc.Name and tc.Function.Name for
   tool calls, but providers only send one (OpenAI-compat uses
   function.name, Anthropic uses tc.Name). Fix: count tc.Function.Name
   when Function is present, fall back to tc.Name only otherwise.

Also fix i18n hint text: "auto-detect" was misleading — the backend
uses a 4x max_tokens heuristic, not actual model detection.
2026-03-16 14:48:34 +08:00
xiaoen
639739cb85 refactor(agent): use Turn as the atomic unit for compression cut-off
Introduce parseTurnBoundaries() which identifies each Turn start index
in the session history. A Turn is a complete "user input → LLM iterations
→ final response" cycle (as defined in the agent refactor design #1316).

findSafeBoundary now uses Turn boundaries instead of raw role-scanning,
making the intent explicit: "find the nearest Turn boundary."

forceCompression drops the oldest half of Turns (not arbitrary messages),
which is simpler and more intuitive. The Turn-based approach naturally
prevents splitting tool-call sequences since each Turn is atomic.
2026-03-16 14:48:34 +08:00
xiaoen
efd403242e fix(agent): preallocate messages slice in budget test
Fixes prealloc lint warning by using make() with capacity hint.
2026-03-16 14:48:34 +08:00
xiaoen
b7f1c2b5fc test(agent): add realistic session-shaped tests for context budget
Add tests that reflect actual session data shape: history starts with
user messages (no system prompt), includes chained tool-call sequences,
reasoning content, and media items. Exercises the proactive budget check
path with BuildMessages-style assembled messages.
2026-03-16 14:48:34 +08:00
xiaoen
d5fdd5ebd2 fix(agent): include ReasoningContent and Media in token estimation
estimateMessageTokens now counts ReasoningContent (extended thinking /
chain-of-thought) which can be substantial and is persisted in session
history. Media items get a fixed per-item overhead (256 tokens) since
actual cost depends on provider-specific image tokenization.
2026-03-16 14:48:33 +08:00
xiaoen
9c65d78b07 fix(agent): forceCompression must not assume history[0] is system prompt
Session history (GetHistory) contains only user/assistant/tool messages.
The system prompt is built dynamically by BuildMessages and is never
stored in session. The previous code incorrectly treated history[0] as
a system prompt, skipping the first user message and appending a
compression note to it.

Fix: operate on the full history slice, and record the compression
note in the session summary (which BuildMessages already injects into
the system prompt) rather than modifying any history message.
2026-03-16 14:48:33 +08:00
xiaoen
9c82b0baa2 refactor(agent): context boundary detection, proactive budget check, and safe compression
Separate context_window from max_tokens — they serve different purposes
(input capacity vs output generation limit). The previous conflation caused
premature summarization or missed compression triggers.

Changes:
- Add context_window field to AgentDefaults config (default: 4x max_tokens)
- Extract boundary-safe truncation helpers (isSafeBoundary, findSafeBoundary)
  into context_budget.go — pure functions with no AgentLoop dependency
- forceCompression: align split to safe boundary so tool-call sequences
  (assistant+ToolCalls → tool results) are never torn apart
- summarizeSession: use findSafeBoundary instead of hardcoded keep-last-4
- estimateTokens: count ToolCalls arguments and ToolCallID metadata,
  not just Content — fixes systematic undercounting in tool-heavy sessions
- Add proactive context budget check before LLM call in runAgentLoop,
  preventing 400 context-length errors instead of reacting to them
- Add estimateToolDefsTokens for tool definition token cost

Closes #556, closes #665
Ref #1439
2026-03-16 14:48:32 +08:00
Administrator
ae23193295 feat(agent): port subturn PoC to refactor/agent branch
- Replace duplicate types (ToolResult/Session/Message) with real project types
- Implement ephemeralSessionStore satisfying session.SessionStore interface
- Connect runTurn to real AgentLoop via runAgentLoop + AgentInstance
- Fix subturn_test.go to match updated signatures and types

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
2026-03-16 14:31:32 +08:00
sky5454
2f10b47f59
feat(credential): part1 add AES-GCM encryption, SecureStore, and onboard ke… (#1521)
* feat(credential): add AES-GCM encryption, SecureStore, and onboard keygen

- pkg/credential: new package with AES-256-GCM enc:// credential format,
  HKDF-SHA256 key derivation (passphrase + optional SSH key binding),
  ErrPassphraseRequired / ErrDecryptionFailed sentinel errors,
  and PassphraseProvider hook for runtime passphrase injection

- pkg/credential/store: lock-free SecureStore via atomic.Pointer[string];
  passphrase never written to disk or os.Environ

- pkg/credential/keygen: ed25519 SSH key generation helper used by onboard

- pkg/config: replace os.Getenv(PassphraseEnvVar) with
  credential.PassphraseProvider() at all three call sites so that
  LoadConfig and SaveConfig use whatever passphrase source is active

- cmd/picoclaw/onboard: prompt for passphrase with echo-off, generate
  picoclaw-specific SSH key, re-encrypt existing config on re-onboard

- docs/credential_encryption.md: design doc for the enc:// format

* fix(credential): address Copilot review comments on PR #1521

- credential.go: decouple ErrPassphraseRequired from env var name;
  message is now 'enc:// passphrase required' since PassphraseProvider
  may come from any source, not just os.Environ

- credential.go: Resolver resolves symlinks via EvalSymlinks before the
  isWithinDir containment check, preventing symlink-based path traversal
  for file:// credential references

- store.go: tighten comment to describe only what SecureStore guarantees
  (in-memory only); remove claims about how callers transport the value

- store_test.go: replace the meaningless GetReturnsCopy test (Go strings
  are immutable, equality across two calls proves nothing) with
  TestSecureStore_ConcurrentSetGet that exercises atomic.Pointer under
  10-goroutine concurrent Set/Get load

- config_test.go: update error-message assertion to match new sentinel text

- docs/credential_encryption.md: remove reference to non-existent
  'picoclaw encrypt' subcommand; describe the onboard flow instead

* fix(config): encryptPlaintextAPIKeys: struct-based encryption, fail-fast, remove raw []byte

* fix(credential): require SSH private key for encryption/decryption, remove passphrase-only mode

* lint: fix credential keygen lint, fix test keygen

* onboard: make encryption opt-in via --enc flag

Encryption (passphrase prompt + SSH key generation) is now only
triggered when the user passes --enc to 'picoclaw onboard'.
Without the flag, onboard skips the credential-encryption setup and
writes a plain config + workspace templates directly.

- Add --enc BoolFlag in NewOnboardCommand()
- Pass encrypt bool into onboard()
- Guard passphrase prompt, SSH key generation, and related env-var
  setup behind the encrypt branch
- Adjust 'Next steps' output so the passphrase reminder only appears
  when --enc was used
2026-03-16 14:06:32 +08:00
BitToby
71e2b636d6
fix: Use secure defaults for Pico channel setup and stop leaking the token in the URL (#1563)
* fix: Use secure defaults for Pico channel setup and stop leaking the token in the URL

* fix: Derive default allow_origins from the setup request's Origin header instead of hardcoding localhost ports
2026-03-16 09:58:37 +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
Mauro
021aa7d6d5
feat(agent): steering (#1517)
* feat(agent): steering

* fix loop

* fix lint

* fix lint
2026-03-16 00:08:16 +08:00
duomi
5660b8f24b fix(heartbeat): ignore untouched default template 2026-03-15 21:58:21 +08:00
Hoshina
f7dd040ae4 fix(provider/azure): lint err 2026-03-15 12:45:11 +08:00
Mauro
5a251b46af
Merge pull request #1442 from afjcjsbx/feat/logger-stdout-formatting
feat(logger): Custom console formatter for JSON and multiline strings
2026-03-14 22:04:51 +01:00
Kunal Karmakar
5fb4b3bedf
feat(provider): add support for azure openai provider (#1422)
* Add support for azure openai provider

* Add checks for deployment model name

* Apply suggestion from @Copilot

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

* Addressing @Copilot suggestion to remove the init() function which seemed redundant

* Fix readme

* Fix linting checks

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-14 22:52:34 +08: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
dataCenter430
0c5d7500e8
feat: expose local file paths for non-image media to enable agent file tools (#1516)
* feat: expose local file paths for non-image media to enable agent file tools

* fix: Golang Lint error
2026-03-14 12:09:11 +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
Hoshina
b9aaad95cd refactor(media): centralize temp media dir path 2026-03-14 12:01:47 +08:00
Alix-007
c68b4f3903
fix(qq): populate account bindings metadata (#1456)
Co-authored-by: XYSK-lilong007 <267018309+XYSK-lilong007@users.noreply.github.com>
2026-03-13 23:08:55 +08:00
afjcjsbx
78c9b86d7e added tests 2026-03-13 14:02:28 +01: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
lxowalle
9530883d2c
Fix/Add warning tips for MCP initialization when no valid servers configured (#1497)
* add tips for mcp

* fix test issue
2026-03-13 16:43:00 +08:00
美電球
4ccea5eb93
fix(identity): prevent allowlist ID entries from matching usernames (#1406) 2026-03-13 15:41:18 +08:00
Cytown
9676e51e89
make gateway aware of config.json change (#1187)
* make gateway aware of config.json change

* fix according to code review

* fix lint

* fix review comment

* fix for review

* refactor to fix review

* fix for review

* fix for review
2026-03-13 14:27:46 +08:00
Cytown
dfa36f39cb
add model command to set default model (#1250)
* add model command to set default model

* fix for ci

* fix test for model

* fix active agent not recognized

* implement test for model command

* fix local-model can not set as default issue

* fix review comment

* fix for comment
2026-03-13 14:10:11 +08:00
Zane Tung
9fed4ec136
feat: add anthropic-messages protocol for native Anthropic Messages API support Fixes #269 (#1284)
* feat: add anthropic-messages protocol support

Add native Anthropic Messages API format support to enable
compatibility with custom endpoints that only support Anthropic's
native message format (not OpenAI-compatible format).

Changes:
- Add new pkg/providers/anthropic_messages package with HTTP-based provider
- Implement Anthropic Messages API request/response format conversion
- Add anthropic-messages protocol support in factory_provider.go
- Include comprehensive unit tests (64.2% coverage)

Features:
- Support for system, user, assistant, and tool messages
- Support for tool calls (tool_use blocks)
- Proper header handling (x-api-key, anthropic-version)
- Configurable max_tokens and temperature
- Automatic base URL normalization

Configuration example:
  model: "anthropic-messages/claude-opus-4-6"
  api_base: "https://api.anthropic.com"
  api_key: "sk-..."

Tested with actual API endpoint, verified compatibility
with Anthropic Messages API specification.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* docs: add anthropic-messages protocol examples to README and config

Add configuration examples and documentation for the new
anthropic-messages protocol:

- config.example.json: Add claude-opus-4.6 example with anthropic-messages
- README.md: Add "Anthropic Messages API (native format)" section
- README.zh.md: Add Chinese version of the documentation

This helps users understand when to use anthropic-messages vs
anthropic protocol and fixes issue #269.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: format code with gofmt -s

- Align constant definitions in provider.go
- Align struct fields in test cases
- Fix gofmt formatting issues reported in review

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: address linter errors

- Fix HTTP header canonical form: "x-api-key" → "X-API-Key"
- Fix HTTP header canonical form: "anthropic-version" → "Anthropic-Version"
- Format imports with gci (standard, default, localmodule order)
- Format code with golines (max line length 120)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

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

* fix: resolve golangci-lint errors in anthropic-messages provider

- add nolint comment for canonicalheader rule on X-API-Key header (Anthropic API requires exact casing)
- fix golines formatting issues in provider_test.go (split long lines under 120 chars)
- fix long comment line in factory_provider.go (split into two lines)

Resolves CI linter failures for the anthropic-messages protocol implementation.

* fix(providers): address review comments in anthropic-messages provider

- fix normalizeBaseURL edge case that incorrectly appends /v1 to URLs already containing /v1 path (e.g., https://api.example.com/v1/proxy)
- remove dead code for apiBase empty check as normalizeBaseURL() always provides a default value
- update test to use proper constructor instead of direct struct initialization
- add detailed comments explaining the URL normalization logic

Resolves review comments on PR #1284

* fix(providers): remove hardcoded max_tokens in anthropic-messages provider

- remove hardcoded max_tokens value (4096) from buildRequestBody
- read max_tokens directly from options parameter
- add error handling when max_tokens is missing from options
- update test cases to include max_tokens in options

This fix ensures the provider respects the config default value (32768)
or system fallback (8192) instead of always using the hardcoded 4096.

* fix(providers): improve error handling and add edge case tests

- fix ToolCalls nil vs empty slice issue to ensure consistent JSON serialization
- add detailed HTTP error handling for common status codes (401, 429, 400, 404, 500, 503)
- add edge case tests for buildRequestBody and parseResponseBody
- clarify anthropic vs anthropic-messages protocol differences in docs

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-13 14:09:40 +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
dataCenter430
b811e9186c
feat(provider): add ModelScope as OpenAI-compatible provider (#1486)
* feat(provider): add ModelScope as OpenAI-compatible provider

* test(provider): add ModelScope provider and migration tests

* docs: add ModelScope to README provider tables and free tier sections

* chore: add ModelScope to example config and env template
2026-03-13 14:02:23 +08:00
Cytown
83e24e8ceb
fix 3rd party logger not correct output (#1482) 2026-03-13 11:20:17 +08:00
Eric Jacksch
56fb0dc4e3 fix(claude_cli): surface stdout in error when CLI exits non-zero
When the claude CLI exits with a non-zero status, the previous error
handler only checked stderr. However, the CLI writes its output
(including error details) to stdout, especially when invoked with
--output-format json. This left the caller with only "exit status 1"
and no actionable information.

Now includes both stderr and stdout in the error message so the actual
failure reason is visible in logs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 22:01:56 -04:00
afjcjsbx
a01af36af4 feat(logger): add custom console formatter for JSON and multiline strings 2026-03-12 18:58:24 +01:00
don
19835b2f60
fix(line): limit webhook request body size to prevent DoS (#1413)
* fix(line): limit webhook request body size to prevent DoS

Add io.LimitReader with 1 MB cap on the LINE webhook handler to prevent
unauthenticated memory exhaustion via oversized POST requests.

Follows the same pattern used in the WeCom channel (io.LimitReader).
Requests exceeding the limit are rejected with 413 Request Entity Too Large.

Fixes #1407

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

* refactor(line): hoist body size const, add boundary tests

- Move maxWebhookBodySize to package-level const
- Add TestWebhookAcceptsMaxBodySize (exact limit → 403, not 413)
- Add TestWebhookRejectsOversizedBodyBeforeSignatureCheck
- Use const in test instead of magic number

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:55:40 +08:00
Horsley Lee
8f49af99f9
fix(matrix): stream inbound media downloads to disk (#1436) 2026-03-12 23:48:26 +08:00
Guoguo
1e024321c0
refactor: update model name and add VolcEngine coding plan (#1412)
* docs: swap header logo to webp, move meme logo to bottom

Replace header logo with assets/logo.webp across all 6 README
language variants and move the original meme logo (logo.jpg)
to the bottom of each file.

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

* docs: update GPT model names to gpt-5.4 and refine provider descriptions

Update all 6 language README variants:
- Correct GPT model references from gpt-5.2/gpt4 to gpt-5.4
- Refine provider descriptions in API Key comparison tables

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

* chore: update default model to gpt-5.4, codex to gpt-5.3-codex

Update OpenAI default model references from gpt-5.2 to gpt-5.4
across source code, config examples, tests, and docs. Set Codex
default model to gpt-5.3-codex.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:10:29 +08:00
Alix-007
3bcbfd99b9
fix(channels): stop stale typing loops on overwrite (#1392)
Co-authored-by: XYSK-lilong007 <267018309+XYSK-lilong007@users.noreply.github.com>
2026-03-12 14:31:00 +08:00
Cytown
7359b2c86c add testcase for migrate from v0 to v1 2026-03-12 14:09:31 +08:00
Cytown
1c123e0162 refactor Config to add Version and migratable 2026-03-12 13:52:55 +08:00
Mahendra Teja
8cac29d9bb
docs: remove stale TOOLS.md references (#1388)
TOOLS.md was intentionally removed in 21d60f6 and #771, as tools are
now provided to the LLM via JSON schema through ToProviderDefs().
These references were missed during that cleanup.

Suggested by @yinwm in #1355.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:47:01 +08:00
kiannidev
dc037f0d79 fix(telegram): stop typing indicator when LLM fails or hangs 2026-03-12 02:22:04 +02:00
Mahendra Teja
6612ca099a
fix(openai_compat): improve prompt_cache_key host matching (#1387)
LGTM! The changes improve the robustness of prompt_cache_key host matching and add Azure OpenAI support. Thanks for the contribution!
2026-03-12 03:24:31 +08:00
amagi
49204df678
fix(openai_compat): accept object tool call arguments (#1292) 2026-03-12 02:47:22 +08:00
Cytown
d920b78b41
refactor logger to zerolog (#1239)
* refactor logger to zerolog

* modify dingtalk and discord logger

* fix for lint

* fix for review

* fix for file leak

* fix for review
2026-03-12 02:35:37 +08:00
LeaderOnePro
9222351871
feat(providers): add LongCat model provider support (#1317)
* feat(providers): add LongCat model provider support

Add LongCat as an OpenAI-compatible provider with base URL
https://api.longcat.chat/openai and default model LongCat-Flash-Thinking.
Includes provider config, migration, factory routing, example config,
tests, and README entries for all 6 locales.

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

* fix(providers): address LongCat review feedback

- Add dedicated factory routing test for LongCat provider
- Add longcat to DefaultAPIBase test coverage
- Set default api_base in example config providers section

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

* test(providers): add ResolveProviderSelection tests for LongCat

Add two test cases to TestResolveProviderSelection:
- Explicit provider selection with api_base default and proxy wiring
- Fallback inference from model name with api_base default

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-12 02:34:42 +08:00
Darren.Zeng
8431fa3e04
fix(config): support Chinese comma separator in allow_from environment variables (#1301)
Add UnmarshalText method to FlexibleStringSlice to support both English
(,) and Chinese (,) comma separators in environment variables.

Includes comprehensive unit tests covering:
- English commas, Chinese commas, mixed commas
- Single values, whitespace trimming
- Empty strings, edge cases

Fixes #1280
2026-03-12 02:33:33 +08:00
Dimitrij Denissenko
39a451d312
Enable rich-text messages in matrix channel (#1370)
* Enable rich-text messages in matrix channel

* Fix lint
2026-03-12 01:25:28 +08:00
Mahendra Teja
4a80c6f58c
fix(openai_compat): only send prompt_cache_key to OpenAI endpoints (#1353)
Non-OpenAI providers (Mistral, DeepSeek, Groq, etc.) reject unknown
request fields with 422 errors. The previous blocklist only excluded
Google/Gemini, but the comment already noted this feature is
OpenAI-only. Flip to an allowlist so only api.openai.com receives
the field.

Fixes #1333
2026-03-12 01:21:54 +08:00
Congregalis
9b0a48ac6d
fix(agent): initialize MCP in direct agent mode (#1361) 2026-03-12 01:06:48 +08:00
wenjie
8949a2575b
Add exec allow_remote config support in web settings (#1363)
- default tools.exec.allow_remote to true when omitted in config loading
- preserve allow_remote in OpenClaw config migration and API updates
- expose allow_remote in the web config form with i18n strings
- add backend and config tests covering the new default behavior
2026-03-11 19:57:59 +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
nayihz
8a398988d7
refactor skills loader markdown metadata parsing (#1354) 2026-03-11 18:08:00 +08:00
Mauro
30584f04cb
Merge pull request #1214 from afjcjsbx/feat/echo-voice-audio-transcription
feat(channel): echo voice audio transcription feedback
2026-03-11 08:45:25 +01:00
wenjie
e74820cf69
fix: skip meta json files during session migration (#1340) 2026-03-11 14:29:42 +08:00
Cage
d5cbf198b2
fix: resolve gateway binary path, pass --config flag, and clarify empty model error (#1337) 2026-03-11 12:54:08 +08:00
美電球
755fa32336
Merge pull request #1330 from statxc/fix/session-key-sanitize-slash
fix(session): sanitize '/' and '\' in session keys so forum topic key…
2026-03-11 12:18:54 +08:00
afjcjsbx
08cc09e091 resolve conflicts 2026-03-11 00:17:10 +01:00
afjcjsbx
87d458f519 Merge remote-tracking branch 'origin/main' into feat/echo-voice-audio-transcription
# Conflicts:
#	pkg/channels/telegram/telegram.go
#	pkg/config/config.go
#	pkg/config/defaults.go
2026-03-11 00:06:37 +01:00
Mauro
9cd2d21800
Merge pull request #1207 from afjcjsbx/feat/debug-mode-no-truncate
feat: no-truncate param for debug
2026-03-10 17:13:44 +01:00
statxc
2e3e6788ab fix(session): sanitize '/' and '\' in session keys so forum topic keys don't create invalid paths 2026-03-10 16:11:34 +00:00
美電球
54f0680add
Merge pull request #1291 from statxc/feat/telegram-forum-topics
feat(telegram): support forum topics with per-topic session isolation
2026-03-10 21:38:40 +08:00
statxc
320fcd1f02 fix: Add IsForum check so only forum topic threads get session isolation, not regular group reply threads 2026-03-10 13:25:14 +00:00
lxowalle
680e845d61
feat:Modify the location where version is obtained, and insert version information into the context (#1300)
* feat:migrate version info from internal package to pkg/config

* * fix lint issue
2026-03-10 17:42:05 +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
is-Xiaoen
26f623ed32
feat(session): integrate JSONL persistence into agent loop (#1170)
* feat(session): add SessionStore interface and JSONL backend adapter

Extract a SessionStore interface from the methods the agent loop uses
(AddMessage, GetHistory, SetSummary, TruncateHistory, Save, etc.).
Both SessionManager and the new JSONLBackend satisfy this interface,
allowing the persistence layer to be swapped transparently.

JSONLBackend wraps memory.Store and maps its error-returning API to
the fire-and-forget contract that the agent loop expects — write
errors are logged, reads return empty defaults on failure. Save()
triggers compaction to reclaim space after logical truncation.

Part of #1169

* test(session): add JSONLBackend integration tests

8 tests covering the full SessionStore contract through the JSONL
backend: message roundtrip, tool calls, summary, truncation with
compaction, history replacement, empty sessions, session isolation,
and the complete summarization flow (SetSummary → TruncateHistory →
Save).

Includes compile-time interface satisfaction checks for both
SessionManager and JSONLBackend.

Part of #1169

* feat(agent): wire JSONL session store into agent loop

Replace the concrete *SessionManager field with the SessionStore
interface and initialize the JSONL backend by default. Legacy .json
session files are auto-migrated on first startup. Falls back to
SessionManager if the JSONL store cannot be initialized.

The agent loop code (loop.go) requires zero changes — all method
calls work identically through the interface.

Closes #1169

* fix(session): propagate compact error from Save

Save() was swallowing the error returned by Compact and always
returning nil. Callers checking Save's return value would never
see a compaction failure. Return the error directly so the agent
loop can log or handle it as needed.

* feat(session): add Close to SessionStore interface

Add Close() error to SessionStore so callers can release resources
through the interface. JSONLBackend already had Close; this adds
a no-op implementation to SessionManager for compatibility.

* fix(session): close session stores on shutdown and harden migration

- Add Close() to AgentInstance, AgentRegistry, and AgentLoop so JSONL
  file handles are released during gateway shutdown and CLI exit.
- Fall back to SessionManager when migration fails, preventing a split
  state where some sessions live in JSONL and others remain in JSON.
- Add defer agentLoop.Close() in the CLI agent command path.
- Document SessionStore interface methods (fire-and-forget contract).
2026-03-10 15:14:09 +08:00
statxc
3f1e89da7f fix: solve Lint errors 2026-03-10 04:22:00 +00:00
美電球
2312553286
feat(channels): enhance QQ channel with group/typing/media support and URL sanitization (#1208)
* feat(channels): enhance QQ channel with group support, typing, media, and URL sanitization

Add group message routing alongside existing C2C (direct) support using
chatType sync.Map to track whether a chatID is group or direct. Implement
passive reply with msg_id/msg_seq tracking for multi-part responses.

Add StartTyping (InputNotify msg_type=6 with periodic resend), SendMedia
(RichMediaMessage for HTTP/HTTPS URLs), and configurable Markdown message
support. Replace unbounded dedup map with TTL-based expiry and janitor
goroutine.

Sanitize URLs in group messages by replacing dots in domains with fullwidth
period to avoid QQ's URL blacklist rejection (error 40054010). Add rate
limit config (5 msg/s) and MaxMessageLength/SendMarkdown config fields.

* fix(channels): address review feedback on QQ channel implementation

- Fix goroutine leak: reinitialize done channel and sync.Once in Start()
  to prevent multiple janitor goroutines on restart
- Fix double-close panic: guard close(done) with sync.Once in Stop()
- Fix StartTyping context: use c.ctx (channel lifecycle) instead of
  caller's ctx (request lifecycle) for typing goroutine
- Refactor: extract getChatKind() helper to deduplicate chatType lookup
  across Send(), StartTyping(), and SendMedia()
- Fix: use new(atomic.Uint64) instead of taking address of local var
- Fix: require explicit http(s):// scheme in URL regex to avoid false
  positives on version strings like "1.2.3"
- Optimize: collect expired keys before deleting in dedupJanitor to
  reduce lock hold time
- Fix: remove MaxMessageLength zero-value override in NewQQChannel
  since defaults.go already sets 2000

* fix(channels): address second round of review feedback on QQ channel

- Fix SendMedia: bypass media store for direct http(s) URLs in part.Ref;
  only fall back to store.Resolve for media:// refs; log clear warning
  for local-only paths instead of silently skipping
- Fix chatType routing: default unknown chatIDs to "group" (safer for QQ
  since outbound-only destinations like reasoning_channel_id are groups);
  pre-register reasoning_channel_id as group at Start() time; add debug
  log for untracked chatIDs
- Add dedup hard cap (10000 entries): evict oldest entry when map
  exceeds capacity to prevent unbounded memory growth under high traffic
2026-03-10 12:07:02 +08:00
statxc
123275fcbe feat(telegram): support forum topics with per-topic session isolation 2026-03-10 02:54:10 +00:00
afjcjsbx
68e40aeb47 fix typo 2026-03-09 23:56:59 +01: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
Meng Zhuo
110fc71349 chore: drop unnessary crypto/rand (#1267) 2026-03-09 22:45:01 +08:00
Meng Zhuo
9a13ed50d0
Merge pull request #1107 from afjcjsbx/fix/deny-reading-binary-files
fix(tool) prevent read huge files in tool
2026-03-09 22:11:27 +08:00
lxowalle
abafa3c2aa
* add minimax provider (#1273) 2026-03-09 18:43:58 +08:00
afjcjsbx
f89c9673cb sync sendmessage function 2026-03-09 11:38:23 +01:00
afjcjsbx
584564af63 fix lint 2026-03-09 11:02:31 +01:00
lxowalle
aaf99d7a30
feat: add /clear command to clear chat history (#1266)
* * add clear command to clear chat history

* check nil

* * update comment
2026-03-09 16:39:33 +08:00
afjcjsbx
ff54128ab4 refined code 2026-03-09 09:32:21 +01:00
lxowalle
ba4b702675
fix: retryLLM return empty (#1264) 2026-03-09 14:39:26 +08:00
lxowalle
2c3952b8c0
Fix: improve history compression with retry logic and multi-byte character support (#1167)
* first commit

* Reduce retry wait time to 100ms

* * Add incremental delay and modify the context truncation logic
2026-03-09 13:41:41 +08: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
afjcjsbx
536e26aff1 Removed the old heavy logic 2026-03-08 18:22:15 +01:00
afjcjsbx
f87ab99833 fix empty strings on failed transcription 2026-03-08 18:00:02 +01:00
afjcjsbx
f219ca1263 telegram reply only on first message 2026-03-08 17:57:43 +01:00
afjcjsbx
3b5d04956e fixed double message on slack thread 2026-03-08 17:41:53 +01:00
美電球
7ea7bb0717
Merge pull request #1171 from mutezebra/feat/feishu-random-emoji-v2
feat(feishu): add random reaction emoji config
2026-03-08 23:47:45 +08:00
美電球
b767ca9c3c
Merge pull request #1220 from horsley/feat/matrix-channel-support
feat: add Matrix channel support
2026-03-08 22:58:16 +08:00
horsley
fb2bfe4b3c fix(matrix): satisfy golines in mention regex test 2026-03-08 10:53:45 +00:00
mutezebra
08d668c165
chore(config): gofmt 格式化 FeishuConfig 字段对齐 2026-03-08 17:32:24 +08:00
mutezebra
6aa1d02fff
fix(feishu): 用 crypto/rand 选择随机表情并修正示例配置 2026-03-08 17:30:50 +08:00
horsley
6e16ac7f68 fix(matrix): bound room cache and align temp media dir 2026-03-08 09:23:02 +00:00
horsley
cd955d730b fix(ci): resolve linter and security check failures 2026-03-08 08:06:28 +00:00
mutezebra
b15cff1266
Merge upstream/main and resolve conflicts in .env.example 2026-03-08 15:32:11 +08:00
Meng Zhuo
81dfdf5f45
Merge pull request #1100 from zihan987/main
feat: add Vivgrid provider support
2026-03-08 11:03:13 +08:00
horsley
64b99b34bb fix(matrix): improve group mention detection 2026-03-07 18:05:09 +00:00
afjcjsbx
5b1f11aaf6 resolve conflicts 2026-03-07 18:56:38 +01:00
afjcjsbx
424c40e98b Merge remote-tracking branch 'origin/main' into feat/echo-voice-audio-transcription
# Conflicts:
#	pkg/channels/telegram/telegram.go
2026-03-07 18:55:32 +01:00
afjcjsbx
2effc2b4bd slack reply message with audio transcription 2026-03-07 18:47:22 +01:00
horsley
a66eac42c4 feat: add Matrix channel support 2026-03-07 17:44:24 +00:00
zihan987
4df4138663 Fix Vivgrid docs and inference logic 2026-03-07 09:20:56 -08:00
美電球
826f92cf53
Merge pull request #935 from putueddy/feat/telegram-chunking
feat: add message chunking in Telegram Send method
2026-03-07 23:47:06 +08:00
afjcjsbx
73243c9014 fix lint 2026-03-07 16:45:21 +01:00
afjcjsbx
a0591f0c08 unit test placeholder logic 2026-03-07 16:40:26 +01:00
afjcjsbx
68bdf66168 fix lint 2026-03-07 16:24:49 +01:00
afjcjsbx
48d8c8738d discord reply message on transcript echo 2026-03-07 16:18:53 +01:00
I Putu Eddy Irawan
f07dbd1db2 fix: remove redundant SplitMessage in Send() per review feedback
WithMaxMessageLength(4000) already ensures msg.Content ≤ 4000 chars
before reaching Send(), making the SplitMessage call redundant.
The HTML expansion safety net (re-split when >4096 after conversion)
is still preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 22:01:04 +07:00
afjcjsbx
0c117a073f feat(channel): echo voice audio transcription 2026-03-07 15:49:33 +01:00
Hua Audio
66e6fb6c79
feat(agent) fallback to reasoning content (#992) 2026-03-07 14:17:33 +01:00
Meng Zhuo
aeabbcf2e8
Merge pull request #1138 from amirmamaghani/feat/irc-channel
feat(channels): add IRC channel integration
2026-03-07 20:25:26 +08: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
Mauro
440d665baa
Merge pull request #1075 from qs3c/fix/1068-html-response-error
fix(openai_compat): clarify HTML response parse errors
2026-03-07 09:56:50 +01:00
afjcjsbx
569d509de5 no-truncate param 2026-03-07 09:48:44 +01:00
amagi
53cba73283 fix: resolve openai compat lint issues 2026-03-07 16:12:23 +08:00
amagi
6eaa49f7ab fix: improve openai compat HTML response handling 2026-03-07 15:50:08 +08:00
afjcjsbx
674f00ec63 set offset and length in read_file tool 2026-03-07 00:33:27 +01:00
Amir Mamaghani
a89ba06cb8 fix: address review feedback from @mengzhuo
- Add separate User and RealName config fields (fall back to Nick)
- Make RequestCaps configurable (defaults to server-time, message-tags)
- Refactor isBotMentioned into nickMentionedAt returning position;
  stripBotMention now uses nickMentionedAt internally
- Replace custom isAlphanumeric with unicode.IsLetter/unicode.IsDigit
- Update tests for new nickMentionedAt function
2026-03-06 20:09:37 +01:00
fishtrees
1945436dd4
feat(cron): add execution lifecycle logging (#1185)
- Log job start with name, id, schedule kind, and channel
- Log job completion with duration and next run time
- Log job errors with duration and error message
- Helps diagnose scheduler stalls and connection issues
2026-03-06 20:46:52 +08:00
zihan987
e6f5467711 Fix golines for vivgrid case 2026-03-06 04:20:22 -08: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
BallerIsLeet
23abbb67ea
feat(auth): add Anthropic OAuth setup-token login (#926)
* feat(auth): add Anthropic OAuth setup-token login flow

Add support for Anthropic's OAuth-based setup tokens (sk-ant-oat01-*)
as an alternative to API keys. This includes:

- New `--setup-token` flag on `auth login` command
- Interactive login menu for Anthropic (setup token vs API key)
- Setup token validation and credential storage with oauth auth method
- Usage endpoint integration to show 5h/7d utilization in `auth status`
- Streaming support for OAuth tokens (required by Anthropic API)
- Model ID normalization (dots to hyphens) for API compatibility
- Remove .env.example (secrets should not be templated)

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

* feat(auth):  update related functionality

* refactor(auth): organize constants and improve header casing in requests fo CI

* fix(auth): fix golint again

* fix(auth): handle nil arguments in tool calls for buildParams function

---------

Co-authored-by: Baller <sharonms3377@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 19:58:23 +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
Ming
b716b8a053
feat(commands): centralized command registry with sub-command routing (#959)
* feat(commands): Session management [Phase 1/2] command centralization and registration

* docs: add design for command registry post-review fixes

Documents the architecture decisions for fixing 5 Important issues
from code review: SubCommand pattern, Deps struct, command-group files,
Executor caching, and Telegram registration dedup.

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

* feat(commands): add SubCommand type and EffectiveUsage method

Introduce SubCommand struct for declaring sub-commands structurally
within a parent command Definition. The EffectiveUsage() method
auto-generates usage strings from sub-command names and args,
preventing drift between help text and actual handler behavior.

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

* feat(commands): add Deps struct and secondToken helper, remove dead contains()

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

* feat(commands): add sub-command routing to Executor

Uses Registry.Lookup for O(1) command dispatch instead of iterating
all definitions. Definitions with SubCommands are routed to matching
sub-command handlers. Missing or unknown sub-commands reply with
auto-generated usage.

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

* refactor(commands): split into command-group files with Deps injection

Extract show/list/start/help into individual cmd_*.go files.
Replace config.Config parameter with Deps struct for runtime data.
Restore /show agents and /list agents sub-commands.
Use EffectiveUsage for auto-generated help text.
Bridge external callers (agent/loop.go, telegram.go) with Deps wrapper
until Task 5 fully wires the Deps fields.

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

* perf(commands): cache Executor in AgentLoop, wire Deps with runtime callbacks

Create Executor once in NewAgentLoop instead of per-message. Deps
closures capture AgentLoop pointer for late-bound access to
channelManager and runtime agent model.

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

* fix(telegram): remove duplicate initBotCommands, keep async startCommandRegistration only

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

* chore(commands): restore Outcome comments and annotate Deps.Config

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

* refactor(commands): consolidate /switch into commands package, fix ! prefix

Move /switch model and /switch channel handling from inline loop.go
logic into cmd_switch.go using the SubCommand + Deps pattern. This
removes the OutcomePassthrough branch in handleCommand entirely.

Also replace the hardcoded "/" prefix check with commands.HasCommandPrefix
so that "!" prefixed commands are correctly routed to the Executor.

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

* chore: add docs/plans to .gitignore and untrack existing files

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

* refactor(commands): address code review findings

- Remove dead ExecuteResult.Reply field and unused branch in loop.go
- Extract shared agentsHandler for /show agents and /list agents
- Remove redundant firstToken/secondToken (use nthToken instead)
- Simplify Telegram startup: pass BuiltinDefinitions directly
- Centralize req.Reply nil guard in executeDefinition
- Extract unavailableMsg constant (was duplicated 5 times)
- Remove unused MessageID from Request
- Remove stale "reserved for Phase 2" comment on Deps.Config

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

* refactor(commands): replace Deps with per-request Runtime

Separate stateless Registry (cached on AgentLoop) from per-request
Runtime (passed to handlers at execution time). This enables future
session management features to inject per-request context without
modifying the command registry.

- Rename Deps → Runtime, move to runtime.go
- Change Handler signature: func(ctx, req) error → func(ctx, req, rt *Runtime) error
- NewExecutor now takes (registry, runtime) — executor is created per-request
- BuiltinDefinitions() no longer takes parameters (stateless)
- AgentLoop caches cmdRegistry, builds Runtime via buildRuntime()
- Update all cmd_*.go handlers and tests

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

* style: fix gci import grouping and godoc formatting

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

* fix(onboard): skip legacy AGENT.md when copying embedded workspace templates

The workspace/ directory contains both AGENT.md (legacy) and AGENTS.md
(current). copyEmbeddedToTarget was copying both, causing the test
TestCopyEmbeddedToTargetUsesAgentsMarkdown to fail. Skip AGENT.md
during the walk to match the expected behavior.

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

* refactor(agent): address self-review comments on loop.go

- Move cmdRegistry init into struct literal (review comment #11)
- Rename buildRuntime → buildCommandsRuntime for clarity (review comment #12)
- Add comment to default switch case explaining passthrough (review comment #13)

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

* refactor(commands): address code review findings on naming and correctness

- Rename dispatcher.go → request.go (no Dispatcher type remains)
- Rename cmd_agents.go → handler_agents.go (shared handler, not a top-level command)
- Add modelMu to protect AgentInstance.Model writes in SwitchModel
- Add ListDefinitions to Runtime so /help uses registry instead of BuiltinDefinitions()
- Fix SwitchChannel message: validation-only callback should not say "Switched"
- Propagate Reply errors in executor instead of discarding with _ =
- Add HasCommandPrefix unit test

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

* refactor(onboard): extract legacy filename to constant

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

* fix(agent): handle commands before route error check

Move handleCommand() before the routeErr gate so global commands
(/help, /show, /switch) remain available even when routing fails.
Context-dependent commands that need a routed agent will report
"unavailable" through their nil-Runtime guards.

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

* revert: remove unnecessary AGENT.md skip in onboard

Reverts 02d0c04 and 74deae1. The test failure was caused by a local
leftover workspace/AGENT.md file (gitignored but embedded by go:embed).
Deleting the local file fixes the root cause; the code-level skip was
never needed.

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

* fix: executeDefinition Unknown option

* fix(agent): use routed agent for model commands, restore Telegram command diff

- Remove modelMu: message processing is serial, no concurrent writes
- Pass routed agent to handleCommand/buildCommandsRuntime instead of
  always using default agent
- GetModelInfo/SwitchModel are nil when agent is nil (route failed),
  handlers reply "unavailable"
- Restore GetMyCommands + slices.Equal check before SetMyCommands to
  avoid unnecessary Telegram API calls on restart

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

* fix(commands): remove unintended config mutation in SwitchModel

SwitchModel should only update the routed agent's runtime Model field.
Writing to cfg.Agents.Defaults.ModelName was a behavioral change that
corrupts the default agent config when switching a non-default agent.

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

* refactor(commands): move /switch channel to /check channel

/switch channel only validates availability, not actually switching.
Rename to /check channel to match actual behavior. /switch channel
now shows a redirect message pointing users to the new command.

Addresses review feedback from yinwm on PR #959.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 17:31:40 +08:00
Yajun Yao
7df7e0495c
fix deepseek-chat bug (#1066)
Co-authored-by: FantasticCode2019 <1443996278@qq.com>
2026-03-06 16:04:31 +08:00
zihan987
a2f63e4207 Fix HasProvidersConfig 2026-03-06 00:03:10 -08:00
zihan987
7308f0621b Merge upstream main 2026-03-05 23:58:59 -08:00
Meng Zhuo
9b1e73de9c
Merge pull request #994 from is-Xiaoen/feat/model-routing
feat(routing): intelligent model routing based on structural complexity scoring
2026-03-06 15:47:53 +08:00
美電球
4d965f2c81
Merge pull request #1047 from AaronJny/feat/discord-reply-context
feat(discord): support referenced messages and resolve channel/link references
2026-03-06 15:03:29 +08:00
xiaoen
b84adacc2f fix(routing): address review feedback on CJK estimation and observability
1. CJK token estimation: replace flat rune_count/3 with script-aware
   counting — CJK runes (U+2E80–U+9FFF, U+F900–U+FAFF, U+AC00–U+D7AF)
   count as 1 token each, non-CJK runes at /4. This fixes a 3x
   underestimate for Chinese/Japanese/Korean text that could incorrectly
   route complex CJK messages to the light model.

2. Routing observability: SelectModel now returns the computed score as
   a third value. selectCandidates logs the score on both paths — Info
   level for light model selection, Debug level for primary model
   selection.

3. Added tests: TestExtractFeatures_TokenEstimate_Mixed (CJK+ASCII mix),
   TestRouter_SelectModel_ReturnsScore.

Addresses review feedback from @mingmxren.
2026-03-06 13:10:20 +08:00
mutezebra
92a0db4993
chore(feishu): document reaction emoji option and promote filetype dep
Add an info log for `RandomReactionEmoji` configuration.
2026-03-06 12:53:48 +08:00
mutezebra
9f017d077e
feat(feishu): add random reaction emoji config
- Add random_reaction_emoji config for Feishu channel
- Update .env.example with new env vars
- Update documentation (README.zh.md)
2026-03-06 12:53:47 +08:00
Meng Zhuo
f600829158
Merge pull request #1157 from wangyanfu2/fix-config-shell-command-exec-timeout
fix(tools): make exec tool timeout configurable via config
2026-03-06 11:42:26 +08:00
xiaoen
e433bb8b7f merge: resolve conflicts with upstream/main
Upstream added ThinkingLevel, SummarizeMessageThreshold,
SummarizeTokenPercent, MaxMediaSize, and maybeSummarize.
Our branch added Router, LightCandidates, and selectCandidates.
Both sets of changes are kept. Dead updateToolContexts removed
(upstream deleted it; no callers exist).
2026-03-06 11:27:48 +08:00
wangyanfu2
65e1434e1b style: fix gofmt formatting in ExecConfig struct
Remove extra trailing whitespace between struct tag and inline comment
on TimeoutSeconds field to comply with gofmt formatting rules.
2026-03-06 11:19:25 +08:00
Meng Zhuo
8581d46eaa
Merge pull request #1142 from mattn/fix/handle-io-readall-errors
fix: handle ignored io.ReadAll errors across codebase
2026-03-06 10:25:19 +08:00
Meng Zhuo
651cb2ebda
Merge pull request #1155 from keithy/feature/picoclaw-home-env
feat: honor PICOCLAW_HOME env var for config, auth, and workspace paths
2026-03-06 10:13:14 +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
Keith Patrick
51e8479f99 feat: honor PICOCLAW_HOME env var for config, auth, and workspace paths 2026-03-05 22:08:37 +00:00
Mauro
23da4503c1
Merge pull request #1145 from Esubaalew/fix/upstream-skills-global-toggle
fix(agent): respect global skills toggle for skill tools
2026-03-05 22:17:32 +01: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
Amir Mamaghani
c10959b645 test(irc): add unit tests for IRC channel
Test NewIRCChannel validation, extractHost, isBotMentioned,
stripBotMention, and isAlphanumeric helper functions.
2026-03-05 19:23:40 +01:00
amagi
c1a3876f7d fix: improve error handling for non-JSON responses by checking content type and using a streaming JSON parser. 2026-03-06 01:51:24 +08:00
Amir Mamaghani
1604582a41 fix: resolve gci lint errors in IRC channel files
Sort irc import alphabetically in helpers.go and fix struct field
alignment in irc.go to satisfy golangci-lint gci formatter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:03:10 +01:00
Yasuhiro Matsumoto
03d6ad420f
fix: resolve merge conflicts in wecom error handling
Combine both shadow variable fix (readErr) and proper error
classification (ClassifySendError) in wecom app and bot channels.
2026-03-05 22:01:32 +09:00
Yasuhiro Matsumoto
b878272962
fix: resolve govet shadow and golines lint errors in wecom channels 2026-03-05 21:54:13 +09:00
esubaalew
f046ba59e8 fix(agent): respect global skills toggle for skill tools 2026-03-05 15:40:06 +03:00
Boris Bliznioukov
00ad6be7ea
Update pkg/agent/loop.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 13:30:24 +01:00
mattn
42a32fbf3b
Update pkg/channels/wecom/app.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 21:20:51 +09:00
mattn
ee2ebc8bf3
Update pkg/channels/wecom/app.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 21:20:40 +09:00
mattn
ca4e44bd0f
Update pkg/channels/wecom/bot.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 21:20:31 +09:00
mattn
8d2f2d67b2
Update pkg/channels/line/line.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 21:20:20 +09: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
Yasuhiro Matsumoto
943385105f
fix: handle ignored io.ReadAll errors across codebase
io.ReadAll errors were silently discarded with `body, _ := io.ReadAll(...)`,
which could cause empty or partial data to be used for JSON unmarshaling
or error messages. This adds proper error checks for all instances.
2026-03-05 20:56:38 +09:00
qs3c
9216cd14b5 fix(openai_compat): handle html error bodies and reduce allocations 2026-03-05 19:42:58 +08:00
qs3c
536e9ac9de refactor(skills): reuse shared HTTP retry helper 2026-03-05 19:10:36 +08:00
Amir Mamaghani
40b7b6ee4b feat(channels): add IRC channel integration
Add IRC as a new channel for picoclaw, supporting server connections,
channel joins, DMs, mention-based group triggers, and IRCv3 typing
indicators. Uses ergochat/irc-go for connection management with SASL,
NickServ, and automatic reconnection support.

Closes #1137
2026-03-05 11:48:17 +01:00
zihan987
91f52c4586 Resolve merge conflicts 2026-03-04 23:50:58 -08:00
qs3c
7a2fdc24dc fix(skills): retry ClawHub requests on 429 2026-03-05 15:00:06 +08:00
lxowalle
6f5930624b
Feat/add tool enable or disable configuration (#1071)
* Add tools enable or diable config
2026-03-05 14:53:26 +08:00
zihan987
d1cf680657 Resolve merge conflicts 2026-03-04 22:53:17 -08:00
mosir
0f568aceb7
Merge branch 'sipeed:main' into fix/reload-config-selfkill-guard 2026-03-05 13:58:44 +08:00
美電球
464ae1846e
Merge pull request #1106 from afjcjsbx/fix/prevent-audio-as-image-url
fix(provider) prevent audio as image url
2026-03-05 12:55:46 +08: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
Larry Koo
204038ec60
feat: add extended thinking support for Anthropic models (#1076)
* feat: add extended thinking support for Anthropic models

Support configurable thinking levels (off/low/medium/high/xhigh/adaptive)
via `agents.defaults.thinking_level` config field.

- "adaptive": uses Anthropic's adaptive thinking API (Claude 4.6+)
- "low/medium/high/xhigh": uses budget_tokens (all thinking-capable models)
- "off": disables thinking (default)

API constraints handled:
- Temperature cleared when thinking is enabled
- budget_tokens clamped to max_tokens-1
- Thinking response blocks parsed into Reasoning field

Relates to #645, #966

* fix: address PR review feedback for thinking support

- Add ThinkingCapable interface for provider capability detection
- Warn when thinking_level is set but provider doesn't support it
- Warn when temperature is cleared due to thinking enabled
- Adjust budget values per Anthropic best practices (medium=16K, xhigh=64K)
- Add budget clamp warning and 80% threshold warning
- Add parseResponse thinking block tests
- Add thinking_level field to config.example.json

* refactor: move ThinkingLevel from AgentDefaults to ModelConfig

Thinking is a model-level capability, not a global agent property.
Per-model config avoids silent ignoring on non-Anthropic providers
and eliminates spurious warning logs in multi-provider setups.

Addresses PR #1076 review feedback from @yinwm.
2026-03-05 09:51:18 +08:00
Meng Zhuo
325af2163b
Merge pull request #844 from avianion/feat/add-avian-provider
feat: add Avian as a named LLM provider
2026-03-05 09:45:06 +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
de0f15d548 style: fix golines struct tag alignment in SearXNGConfig
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:48:36 +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
Kyle D
0c97cb30d8 fix: update provider count in migration test to include Avian
The TestConvertProvidersToModelList_AllProviders test expected 19
providers but adding Avian brings the total to 20.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:14:58 +00:00
afjcjsbx
b9ee9b33f5 prevent audio as image url 2026-03-04 19:34:08 +01:00
zihan987
0c17c075da Merge remote-tracking branch 'origin_picoclaw/main' 2026-03-04 09:58:20 -08:00
Mauro
3e5b849984
Merge pull request #947 from dim/fix/transcription
Fix voice transcription
2026-03-04 18:37:24 +01:00
zihan987
ea0b634b3b add Vivgrid config 2026-03-04 09:19:03 -08:00
amagi
a305c0a479 fix(openai_compat): avoid predeclared identifier in preview 2026-03-04 23:57:26 +08:00
I Putu Eddy Irawan
11017ac7ba merge: resolve conflicts with upstream/main
Accept upstream versions for all non-Telegram files to keep PR
scope focused on Telegram message chunking only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:27:55 +07:00
I Putu Eddy Irawan
bd0018a5d7 fix: use queue-based re-splitting for HTML expansion validation
After re-splitting an oversized chunk, sub-chunks were sent without
verifying their HTML also fits under 4096 chars. Non-uniform HTML
expansion (e.g. a sub-chunk dense with bold/links) could still exceed
the limit. Use a queue that pushes sub-chunks back for re-validation
instead of sending them blindly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:19:04 +07:00
I Putu Eddy Irawan
3de4cb863b fix: pass original markdown to sendHTMLChunk for plain-text fallback
When HTML parsing fails, the fallback was re-sending the same HTML
string with ParseMode cleared, showing raw HTML tags to users.
Now pass the original markdown chunk so the fallback displays
readable plain text instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 22:15:17 +07:00
I Putu Eddy Irawan
8bd1935efb telegram: lower MaxMessageLength to 4000 for HTML expansion margin
The Manager splits at MaxMessageLength before calling Send(), and
Telegram's Send() was re-splitting at 4000 internally. Aligning the
channel-level limit to 4000 avoids that redundant second split while
preserving the safety margin for markdown-to-HTML expansion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:46:43 +07:00
daming大铭
c8178f4ad4
Merge pull request #732 from is-Xiaoen/feat/jsonl-memory-store
feat(memory): JSONL-backed session persistence
2026-03-04 19:34:00 +08:00
xiaoen
f9f726c0c1 fix(memory): fsync appended message for consistent durability
addMsg now calls f.Sync() before f.Close(), matching the durability
guarantee of writeMeta and rewriteJSONL (both use WriteFileAtomic
with fsync). Without this, a power loss could leave the appended
line in the kernel page cache only — lost on reboot.
2026-03-04 19:21:34 +08:00
Dimitrij Denissenko
494953fb78 Fix lint 2026-03-04 10:21:59 +00:00
qs3c
4946a8b449 fix(openai_compat): clarify HTML response errors 2026-03-04 17:54:04 +08: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
王路路
e0616362fe fix(discord): prevent duplicate link expansion and add regex tests
Address Copilot review feedback:
- Move resolveDiscordRefs(content) before the referenced message
  concatenation to prevent message links in quoted replies from being
  expanded twice.
- Add unit tests for channelRefRe and msgLinkRe regex patterns,
  covering valid/invalid inputs and the 3-link cap.
2026-03-04 15:11:30 +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
Rahul Bansal
df1b53fdf9
feat: make summarization message threshold and token percent configurable (#854) (#1029)
Co-authored-by: Rahul Bansal <rahul@hudle.in>
2026-03-04 11:23:01 +08:00
王路路
38263333ed fix(discord): prevent cross-guild message leakage in link expansion
Security fix: resolveDiscordRefs now takes a guildID parameter and
skips message links pointing to a different guild, preventing the bot
from leaking content across guilds.

Also uses s.State.Channel() cache before falling back to API calls
to reduce Discord API usage and rate limit risk.
2026-03-04 10:12:37 +08:00
王路路
c3e029061b refactor(discord): self-review fixes for resolveDiscordRefs
- Guard against nil ReferencedMessage.Author to prevent panic
- Hoist regexp.MustCompile to package-level vars to avoid
  re-compilation on every handleMessage call
- Both are defensive programming improvements
2026-03-04 10:12:37 +08:00
王路路
922604fc7e feat(discord): resolve channel references and expand message links
Add resolveDiscordRefs method that:
1. Resolves <#id> channel mentions to #channel-name by calling
   the Discord API to fetch channel info
2. Expands Discord message links (up to 3) by fetching the linked
   message content and appending it as '[linked message from User]: content'

Applied to both quoted/referenced messages and the main message
content for full context resolution.
2026-03-04 10:12:37 +08:00
王路路
465819e1c6 feat(discord): support referenced/quoted messages in replies
When a user replies to a message in Discord, the bot now reads
m.ReferencedMessage and prepends its content to the incoming
message as '[quoted message from Username]: content'.

This gives the LLM full context of what message the user is
replying to, enabling meaningful follow-up conversations.
2026-03-04 10:11:39 +08:00
Kyle D
a4546ffb8f feat: add Avian as a named LLM provider
Add Avian (https://avian.io) as an OpenAI-compatible provider with
API base https://api.avian.io/v1 and AVIAN_API_KEY env var support.

Models: deepseek/deepseek-v3.2, moonshotai/kimi-k2.5, z-ai/glm-5,
minimax/minimax-m2.5. Supports chat completions, streaming, and
function calling.

Changes:
- Add Avian to ProvidersConfig struct, IsEmpty(), HasProvidersConfig()
- Add avian protocol to factory provider and default API base
- Add avian case to legacy provider selection (factory.go)
- Add avian migration rule for old config format
- Add default model entries to ModelList (deepseek-v3.2, kimi-k2.5)
- Add avian to example config
- Update AllProviders test count from 18 to 19
2026-03-03 19:36:46 +00:00
美電球
bea238c337
Merge pull request #853 from nayihz/feat_discord_proxy
feat(discord): add proxy support and tests
2026-03-04 01:03:57 +08:00
I Putu Eddy Irawan
fe97387f0f Merge remote-tracking branch 'origin/feat/exa-search' into deploy/pi-integration 2026-03-03 22:29:10 +07:00
I Putu Eddy Irawan
b7aaa5b887 Merge remote-tracking branch 'origin/feat/dotenv-loading' into deploy/pi-integration 2026-03-03 22:29:05 +07:00
I Putu Eddy Irawan
8ed351cf28 Merge remote-tracking branch 'origin/feat/telegram-chunking' into deploy/pi-integration 2026-03-03 22:28:59 +07:00
I Putu Eddy Irawan
c5d2298490 Merge remote-tracking branch 'origin/feat/kimi-opencode-providers' into deploy/pi-integration 2026-03-03 22:28:54 +07:00
I Putu Eddy Irawan
d257f1aaef merge: resolve conflict with upstream/main in provider_test.go
Keep both KimiCodeUserAgent test (from this branch) and
serializeMessages tests (from upstream) — no overlap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:18:20 +07:00
I Putu Eddy Irawan
e503c87c18 fix: add LiteLLM to env overrides and fix malformed .env test
- Add missing LITELLM entry to loadProviderEnvOverrides so
  PICOCLAW_PROVIDERS_LITELLM_API_KEY/API_BASE env vars work
- Replace valid .env content in TestLoadConfig_MalformedDotenv_NonFatal
  with genuinely malformed content (bare key without '=') to actually
  exercise the non-fatal error path

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:14:25 +07:00
I Putu Eddy Irawan
5b608ae678 test: use guardCommand directly and improve assertions in DiskWiping test
Address Copilot review feedback:
- Use guardCommand() instead of Execute() to avoid running dangerous
  commands (format, mkfs, diskpart) on the host if regex regresses
- Assert error message contains "blocked" for blocked commands
- Replace "go fmt ./..." with "echo go fmt ./..." to avoid accidental
  file modification

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:05:32 +07:00
I Putu Eddy Irawan
56ad77b735 Merge upstream/main into feat/dotenv-loading
Resolve go.mod conflict: keep h2non/filetype from upstream,
tcell/v2 stays in direct deps only (not duplicated in indirect).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 22:01:04 +07:00
I Putu Eddy Irawan
5dcd42e5d3 Merge upstream/main into fix/bugfixes
Resolve conflicts:
- provider.go: keep upstream's serializeMessages (supersedes stripSystemParts)
- provider_test.go: keep upstream's serializeMessages tests
- loop_test.go: add slices import needed by upstream tests
- shell.go: merge PR's --format deny fix with upstream's block device
  pattern, safePaths, and absolutePathPattern
- shell_test.go: include tests from both branches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:55:26 +07:00
I Putu Eddy Irawan
e54b1d39a5 refactor: parse Kimi API hostname once in constructor instead of per-call
Avoid re-parsing apiBase URL on every Chat() invocation by computing
isKimiAPI once in NewProvider(). Also document why the KimiCLI/0.77
User-Agent string is required.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:34:31 +07:00
Mauro
4a7605ee14
Merge pull request #1024 from wangyanfu2/fix-TavilySearch-response
fix: add HTTP status code check in BraveSearchProvider
2026-03-03 11:42:05 +01:00
nayihz
69b1ae48d5 Merge remote-tracking branch 'origin/main' into feat_discord_proxy 2026-03-03 18:38:57 +08:00
daming大铭
a65ccc0d1d
Merge pull request #1020 from shikihane/feat/agent-vision-pipeline-v2
feat(agent): add vision/image support with streaming base64 and filetype detection
2026-03-03 18:35:23 +08:00
daming大铭
cf68166cf2
Merge pull request #1000 from alexhoshina/main
feat(feishu): enhance channel with markdown cards, media, mentions, and editing
2026-03-03 18:30:14 +08:00
pikaxinge
3902061db1
fix(agent): invalidate system prompt cache for global/builtin skills (#845)
* fix(agent): invalidate system prompt cache for global/builtin skills

* test(agent): avoid os.Chdir in builtin skill cache test

* fix(agent): harden skill cache invalidation checks
2026-03-03 18:25:00 +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
Guoguo
1265655ef0
feat(telegram): add base_url support for custom Telegram Bot API server (#1021)
* feat(telegram): add base_url support for custom Telegram Bot API server

Allow users to specify a custom Telegram Bot API server URL via
config field `base_url` or env var `PICOCLAW_CHANNELS_TELEGRAM_BASE_URL`.
Defaults to the official https://api.telegram.org when left empty.

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

* fix(telegram): trim whitespace and trailing slash from base_url

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:27:57 +08:00
shikihane
6ccb68c63e fix: resolve linter issues (gci import grouping, gofumpt, govet shadow)
- Separate third-party imports from local module imports (gci)
- Fix byte slice literal formatting (gofumpt)
- Rename shadowed err variable to ftErr (govet)
- Remove trailing blank lines in test files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:04:54 +08:00
Hoshina
fa1cb9cc74 fix(feishu): address PR #1000 review comments from @xiaket
- Consolidate extractImageKey/extractFileKey/extractFileName into shared
  extractJSONStringField helper to reduce code duplication
- Move mentionPlaceholderRegex to package-level position after imports
- Rename feishuCfg field to config for clarity within FeishuChannel
- Replace @_user_1 heuristic with GET /open-apis/bot/v3/info API call
  at startup for reliable bot @mention detection
- Fix double close on file handle in downloadResource by removing defer
  and using explicit close in both success and error paths
- Add unit tests for common.go and feishu_64.go helpers (53 test cases)
2026-03-03 16:44:24 +08:00
shikihane
43227411ee feat(agent): wire media refs through agent pipeline to LLM provider
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:28:20 +08:00
shikihane
03f7ae494f feat(openai_compat): implement serializeMessages with multipart media support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:28:20 +08:00
shikihane
6fd65825e7 feat(agent): implement resolveMediaRefs with streaming base64 and filetype detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:28:20 +08:00
shikihane
4c6c05a251 feat(config): add configurable max_media_size with 20MB default
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:27:29 +08:00
shikihane
6689c0b1c0 feat(providers): add Media field to Message struct for vision support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:27:29 +08:00
daming大铭
de2ccb5da4
Merge pull request #999 from yinwm/fix/mcp-race-condition-and-resource-leak
fix(mcp): resolve TOCTOU race condition and resource leak
2026-03-03 15:06:57 +08:00
xiaoen
1a922c96a8 merge: resolve conflict with main in loop.go
Main reformatted the fallback.Execute call to multi-line (golines);
our branch renamed agent.Candidates → activeCandidates for routing.
Kept both: multi-line formatting + routing variable.
2026-03-03 12:22:45 +08:00
Guoguo
407707a7cc
Revert "feat(agent): add vision/image support to agent pipeline" 2026-03-03 11:38:32 +08:00
Orgmar
12d4570a36
Merge pull request #990 from shikihane/feat/agent-vision-pipeline
feat(agent): add vision/image support to agent pipeline
2026-03-03 11:32:07 +08:00
shikihane
8ebeefc59f fix(agent,openai_compat): address review feedback on vision pipeline
- serializeMessages: preserve ToolCallID/ToolCalls when Media is present
- resolveMediaRefs: add 20MB file size limit to prevent OOM
- mimeFromExtension: return empty string for unknown extensions
- Add 11 unit tests for serializeMessages, resolveMediaRefs, mimeFromExtension

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:13:22 +08:00
I Putu Eddy Irawan
0e810a2ec4 fix: tighten HTML-expansion test to stay under chunk size
Reduce markdown input from 700 to 600 repeats (3600 runes) so it stays
under the 4000-rune chunk threshold. This ensures the test actually
exercises the HTML-expansion re-splitting logic rather than being split
at the markdown level first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:20:16 +07:00
I Putu Eddy Irawan
2fc87985d2 fix: add kimi-code migration alias and User-Agent test
- Add "kimi-code" to the moonshot provider's providerNames in
  ConvertProvidersToModelList so configs using
  agents.defaults.provider: "kimi-code" migrate correctly.
- Add TestProviderChat_KimiCodeUserAgent verifying that
  User-Agent: KimiCLI/0.77 is set when apiBase hostname is
  api.kimi.com and not set for other hosts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:18:26 +07:00
I Putu Eddy Irawan
df53f4411a fix: format long lines in telegram_test.go to satisfy golines linter
Break function signatures and assert calls that exceed the 120-char
golines limit onto multiple lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:11:24 +07:00
Alfonso
946af6b53d
feat: add LiteLLM provider alias support (#930) 2026-03-03 08:23:55 +11:00
Hoshina
595de7814d fix(feishu): remove dead fetchBotOpenID stub and fix misleading comment 2026-03-03 01:39:33 +08:00
Hoshina
42eb6ea410 fix(feishu): address review findings
- Remove stale "falls back to plain text" comment on Send
- Add empty ChatID validation in SendMedia to match Send
- Use messageID+fileKey as local filename to avoid write collisions
- Check allowlist before downloading inbound media to avoid wasted I/O
- Return errUnsupported consistently from all 32-bit stub methods
2026-03-03 01:27:46 +08:00
Hoshina
0bee9d7bcf fix(feishu): resolve lint issues 2026-03-03 01:04:11 +08:00
Hoshina
c9fb681f3b feat(feishu): enhance channel with markdown cards, media, mentions, and editing
Upgrade the Feishu channel from basic text-only to full feature parity with
Telegram/Discord: interactive card messages with markdown rendering, message
editing (MessageEditor), placeholder messages (PlaceholderCapable), emoji
reactions (ReactionCapable), and inbound/outbound media support (MediaSender).

Also add @mention detection with lazy bot open_id discovery, group trigger
filtering with mention awareness, and multi-type inbound message parsing
(text, post, image, file, audio, video).
2026-03-03 00:49:32 +08:00
yinwm
78aba700d5 fix(mcp): resolve TOCTOU race condition and resource leak
- Use atomic.Bool for closed flag to prevent TOCTOU race between
  CallTool and Close operations
- Add double-check pattern in CallTool for thread-safe closed state
- Use atomic Swap in Close to ensure no new calls can start after
  closed flag is set
- Move MCP manager cleanup defer before initialization to handle
  partial initialization failures
- Update tests to use atomic.Bool operations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:47:25 +08:00
daming大铭
4e348e39ac
Merge branch 'main' into mcp-tools-support 2026-03-03 00:17:39 +08:00
esubaalew
2e0be92776 fix(wecom): resolve upstream rebase conflicts after channel refactor
Rebase onto latest upstream/main, keep ring-buffer dedupe behavior, move dedupe tests to pkg/channels/wecom, and ensure wecom/channels race tests pass.
2026-03-02 18:54:11 +03:00
I Putu Eddy Irawan
84ded81a8c Address Copilot review feedback for .env loading
- Add migrateChannelConfigs() and ValidateModelList() to the fresh-
  install path (no config.json) so legacy env vars are migrated and
  model list is validated consistently with the normal loading path
- Use os.LookupEnv instead of os.Getenv in loadProviderEnvOverrides
  so explicitly empty env vars (e.g. PICOCLAW_PROVIDERS_X_API_BASE=)
  can clear values from config.json
- Guard .env loading with sync.Once to avoid repeated disk I/O and
  noisy log messages when LoadConfig is called from polling handlers
- Add tests: .env file loading, missing config.json with env vars,
  malformed .env non-fatal behavior, and LookupEnv empty-override

Note: go.mod tcell/v2 and tview are correctly listed as direct deps
(they are imported by the launcher TUI); upstream go.mod was stale.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:50:59 +07:00
esubaalew
29e9b6b4b5 fix(wecom): replace dedupe map rotation with circular queue
The previous dedupe map rotation logic completely cleared the map when it reached max size, causing an 'amnesia cliff' where immediately arriving duplicates of just-forgotten messages would be processed.

This change replaces that with a MessageDeduplicator struct that uses a circular queue (ring buffer) to track insertions. When the limit is reached, it only evicts the absolute oldest message from the map, completely resolving the cliff issue.

This also cleans up the WeCom Bot and App webhook handlers by encapsulating the mutex and map state.
2026-03-02 18:50:51 +03:00
esubaalew
8640c8177c fix(wecom): correctly retain boundary message during dedupe map rotation
When the dedupe map rotates, the previous logic entirely cleared the map, meaning the message that triggered the rotation was immediately forgotten and could be duplicated immediately.

This change seeds the new map with the current message to prevent that. Also adds a defensive nil check.
2026-03-02 18:50:29 +03:00
esubaalew
1e2ab4a5e5 test(wecom): add dedupe helper coverage and align constant usage
Use wecomMaxProcessedMessages in tests and add a concurrent same-message test
to lock in race-safety behavior for markMessageProcessed.
2026-03-02 18:50:29 +03:00
esubaalew
db17cdc86d test(wecom): align dedupe rotation behavior and add helper tests
Match rotation semantics to prior behavior by fully resetting the dedupe map
once the size limit is exceeded, and add focused tests for duplicate detection
and boundary rotation behavior.
2026-03-02 18:50:29 +03:00
esubaalew
18d89937ad fix(wecom): remove message-dedupe data races in bot/app channels
Centralize dedupe map access behind a mutex-safe helper and use it in both
WeCom bot and WeCom app channels to eliminate concurrent map access races while
preserving current dedupe behavior.
2026-03-02 18:50:29 +03:00
I Putu Eddy Irawan
8219b5a26f Address Copilot review feedback for Exa search provider
- Add explicit empty-results handling ("No results for: <query>")
- Add "Results for: <query> (via Exa)" header and align per-result
  format with Brave/Tavily/DuckDuckGo/Perplexity
- Add tests: provider priority (Perplexity > Exa > Brave), proxy
  propagation, successful search with header/attribution, empty
  results, and max-results capping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:43:43 +07:00
daming大铭
25639168ea
Merge pull request #300 from mymmrac/telegram-bot-commands
feat(telegram): Init bot commands on start
2026-03-02 23:43:10 +08:00
I Putu Eddy Irawan
33109a1676 Address Copilot review: handle HTML expansion exceeding Telegram limit
When markdownToTelegramHTML expands a chunk beyond 4096 chars (e.g.
**a** → <b>a</b>), re-split the markdown with a proportionally smaller
maxLen so each resulting HTML chunk fits within Telegram's limit.

Extract sendHTMLChunk helper to avoid duplicating the HTML-send +
plain-text-fallback logic.

Add test case for markdown-short-but-HTML-long scenario to verify
the re-splitting behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:35:41 +07:00
I Putu Eddy Irawan
4b7e8d9cb9 feat: add Exa AI search provider
Add Exa (https://exa.ai) as a new web search provider option, slotting
into the priority chain between Perplexity and Brave. Configurable via
config.json or PICOCLAW_TOOLS_WEB_EXA_* environment variables.

Results are capped to the requested count for consistency with other
search providers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:29:26 +07:00
I Putu Eddy Irawan
d9b4af797d feat: add .env file loading and provider env overrides
Load .env files from the config directory before reading config.json,
enabling secrets and API keys to be stored outside version control.
Supports fresh installs (no config.json) by applying env vars and
provider overrides to the default config.

Adds loadProviderEnvOverrides() for PICOCLAW_PROVIDERS_<NAME>_API_KEY
and _API_BASE environment variables across all standard providers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:26:36 +07:00
xiaoen
09e68cb63b fix(routing): resolve golines, gosmopolitan and misspell lint failures
- classifier.go: s/honour/honor/ (American English per misspell)
- router.go: break SelectModel signature across lines (golines)
- router_test.go: break long Message literal (golines)
- router_test.go: replace CJK string literal with rune slice so
  gosmopolitan does not flag the source file; behaviour is identical
2026-03-02 23:11:45 +08:00
I Putu Eddy Irawan
4a067cd9ed
Merge branch 'main' into feat/kimi-opencode-providers 2026-03-02 22:08:50 +07:00
I Putu Eddy Irawan
3501962977 test: add unit tests for Telegram Send() method
Cover empty content early return, single-message send,
multi-chunk splitting for long messages, HTML-to-plain-text
fallback per chunk, and error propagation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 21:54:35 +07:00
xiaoen
02e8192349 feat(agent): wire model routing into the agent loop
instance.go:
  - Add Router *routing.Router and LightCandidates []FallbackCandidate
    to AgentInstance.
  - At agent creation, when routing.enabled and light_model resolves
    successfully in model_list, pre-build the Router and resolve the
    light model candidates once. If the light model isn't in model_list,
    log a warning and disable routing for that agent gracefully.

loop.go:
  - Add selectCandidates(agent, userMsg, history) helper.
    It calls Router.SelectModel and returns either agent.Candidates /
    agent.Model (primary tier) or agent.LightCandidates / light_model
    (light tier). Returns primary unchanged when routing is disabled.
  - In runLLMIteration, resolve (activeCandidates, activeModel) once
    before entering the tool-iteration loop. The model tier is sticky
    for the entire turn so a multi-step tool chain doesn't switch
    models mid-way.
  - Replace hard-coded agent.Candidates / agent.Model references in
    callLLM and the debug log with the resolved active values.

The fallback chain and retry logic are untouched. When light_model
returns an error the fallback chain handles escalation normally.
2026-03-02 22:42:52 +08:00
xiaoen
1943c3e660 feat(routing): add language-agnostic model complexity scorer
Add three new files to pkg/routing/:

features.go — ExtractFeatures(msg, history) → Features
  Computes five structural dimensions with zero keyword matching:
  - TokenEstimate: rune_count/3 (CJK-safe token proxy)
  - CodeBlockCount: ``` pairs in the message
  - RecentToolCalls: tool call count in the last 6 history entries
  - ConversationDepth: total messages in session
  - HasAttachments: data URIs or media file extensions

classifier.go — Classifier interface + RuleClassifier
  RuleClassifier uses a weighted sum that is capped at 1.0:
    code block      → +0.40  (triggers heavy model alone at 0.35 threshold)
    token > 200     → +0.35  (triggers heavy model alone)
    tool calls > 3  → +0.25
    token 50-200    → +0.15
    conversation depth > 10 → +0.10
    attachment      → 1.00 (hard gate, always heavy)

router.go — Router wraps config + Classifier
  Router.SelectModel(msg, history, primaryModel) returns either the
  configured light_model or the primary model depending on whether
  the complexity score clears the threshold. Threshold defaults to
  0.35 when zero/negative to prevent misconfiguration.

router_test.go — 34 tests covering all branches and edge cases
2026-03-02 22:42:20 +08:00
xiaoen
c5a21b269f feat(config): add RoutingConfig to AgentDefaults
Introduce RoutingConfig with three fields:
  - enabled: activates per-turn model routing
  - light_model: references a model_name in model_list
  - threshold: complexity score cutoff in [0,1]

When routing.enabled is true and the incoming message scores below
threshold, the agent switches to light_model for that turn. Absent or
disabled config leaves existing behaviour completely unchanged.

Example:
  "agents": {
    "defaults": {
      "model": "claude-sonnet-4-6",
      "routing": {
        "enabled": true,
        "light_model": "gemini-flash",
        "threshold": 0.35
      }
    }
  }
2026-03-02 22:40:52 +08:00
美電球
f2ab1a74da
Merge pull request #893 from reevoid/rui-dev
Add WeCom AIBot channel implementation and tests
2026-03-02 21:50:21 +08:00
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
Zhang Rui
23f48d7c4e refactor(aibot): remove downloadAndDecryptImage function to streamline image handling 2026-03-02 18:21:53 +08:00
nayihz
9be6fb1a7d Merge branch 'main' into feat_discord_proxy 2026-03-02 18:15:20 +08:00
shikihane
18b36af934 feat(agent): add resolveMediaRefs to convert media:// refs to base64 data URLs
Without this function, media:// refs stored by MediaStore are passed
directly to the LLM API, which rejects them as invalid URLs.

resolveMediaRefs() runs after BuildMessages() and before the LLM call,
converting each media:// ref to a data:image/...;base64,... URL that
vision-capable models can process.

Also adds mimeFromExtension() helper for MIME type inference from
file extensions when ContentType metadata is not available.
2026-03-02 18:08:32 +08:00
Zhang Rui
edd339e056 fix(wecom): handle empty response by encrypting and returning a default response 2026-03-02 17:42:54 +08:00
Zhang Rui
619948f8ff fix(wecom): improve error message for response_url delivery failure 2026-03-02 17:42:54 +08:00
Zhang Rui
d4824a00b6 refactor(config): remove WebhookHost and WebhookPort from WeComAIBotConfig 2026-03-02 17:42:54 +08:00
Zhang Rui
55c556a4c5 fix(wecom): update CanonicalID generation to use identity.BuildCanonicalID for consistency 2026-03-02 17:42:54 +08:00
Zhang Rui
79b7fb7792 fix(wecom): improve error handling in sendViaResponseURL and remove task on failure 2026-03-02 17:42:54 +08:00
Zhang Rui
79bc06c0ba refactor(wecom): simplify stream message structure by introducing WeComAIBotMsgItem and WeComAIBotMsgItemImage types 2026-03-02 17:42:54 +08:00
Zhang Rui
880c402ab7 refactor(wecom): streamline AES encryption/decryption and improve task management logic 2026-03-02 17:42:54 +08:00
Zhang Rui
8f3d611a4c refactor(wecom): replace generateSignature with computeSignature and update related tests 2026-03-02 17:42:54 +08:00
Zhang Rui
81f6787dd5 fix(docs): update WeCom AI Bot timeout duration in README and improve streamTask comments 2026-03-02 17:42:54 +08:00
ZHANG RUI
e88b39f21e Update pkg/channels/wecom/aibot.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 17:42:54 +08:00
Zhang Rui
a87e6b0551 feat(wecom-aibot): enhance stream task management with StreamClosedAt and improved cleanup logic 2026-03-02 17:42:54 +08:00
Zhang Rui
4e09c91dda feat(wecom-aibot): add context management for stream tasks to improve agent cancellation 2026-03-02 17:42:54 +08:00
ZHANG RUI
0b6d913dfc Update pkg/channels/wecom/aibot.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 17:42:54 +08:00
ZHANG RUI
aa9ce6955b Update pkg/channels/wecom/aibot.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 17:42:54 +08:00
ZHANG RUI
e33712deff Update pkg/channels/wecom/aibot.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 17:42:54 +08:00
Zhang Rui
e894f8d39a feat(wecom-aibot): add reasoning_channel_id to configuration and enhance message handling limits 2026-03-02 17:42:54 +08:00
Zhang Rui
c7d4012fc9 fix(wecom-aibot): correct variable name in JSON parsing in message callback handler 2026-03-02 17:42:42 +08:00
Zhang Rui
6caee427bb Add WeCom AIBot channel implementation and tests
- Introduced WeCom AIBot channel configuration in config.go with relevant fields.
- Implemented WeCom AIBot channel factory registration in init.go.
- Created unit tests for WeCom AIBot channel functionalities including initialization, start/stop behavior, webhook path handling, message encryption/decryption, and signature generation.
- Set default values for WeCom AIBot configuration in defaults.go.
2026-03-02 17:42:42 +08:00
shikihane
a4e5c391bd fix(openai_compat): preserve reasoning_content in serializeMessages
The serializeMessages() function was not preserving the reasoning_content
field when serializing messages for vision API calls. This caused the
TestProviderChat_PreservesReasoningContentInHistory test to fail.

This fix ensures reasoning_content is included in both text-only messages
and vision messages with media attachments.

Co-authored-by: Zachary Guerrero <zack.grrr@gmail.com>
2026-03-02 17:38:08 +08:00
shikihane
6997edc82e feat(agent): wire Media through agent pipeline (cherry-pick PR #555)
Add Media field to processOptions, pass msg.Media from inbound
messages through to BuildMessages and serializeMessages so
vision-capable LLMs receive image_url content parts.

Based on work by @as3k in sipeed/picoclaw#555.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:18:04 +08:00
Zachary Guerrero
3d54a77c40 feat: add Media field to Message struct and implement serializeMessages for vision API support
- Add Media []string field to Message struct for image/media URLs
- Implement serializeMessages() to format messages with image_url content parts
- Enables OpenAI-compatible vision APIs to receive image attachments
2026-03-02 17:18:04 +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
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
Dimitrij Denissenko
b74f92ed28 A more neutral and elegant voice.Transcriber interface 2026-03-01 21:02:16 +00: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
Dimitrij Denissenko
b1386ad71f Fix voice transcription 2026-03-01 08:39:05 +00: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
xiaoen
6d894d6138 refactor(memory): use fileutil.WriteFileAtomic and log corrupt lines
- Replace manual temp+rename in writeMeta and rewriteJSONL with the
  project's standard fileutil.WriteFileAtomic. This adds fsync before
  rename, which is important for flash storage on embedded devices
  where power loss can leave zero-length files after an unsynced rename.
- Log a warning when readMessages skips a corrupt line, so operators
  can see that data was lost after a crash instead of silently dropping it.
- Document the lossy sanitizeKey mapping (telegram:123 → telegram_123)
  as an intentional tradeoff.
2026-03-01 14:46:54 +08:00
xiaoen
cd500d2046 Merge branch 'main' into feat/jsonl-memory-store 2026-03-01 14:35:14 +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
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
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
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
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
I Putu Eddy Irawan
2dccee5044 Address Copilot review feedback for Telegram message chunking
- Add early return for empty content to avoid silent no-op
- Split raw markdown before HTML conversion so SplitMessage's
  code-fence-aware logic works correctly and HTML tags/entities
  are never broken by mid-tag splitting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:40:09 +07:00
I Putu Eddy Irawan
9c91d66427 Address Copilot review feedback for Kimi/Opencode providers
- Allow APIBase-only config for opencode provider selection (like VLLM)
- Keep moonshot provider on moonshot.cn/v1 default, only use kimi.com/coding/v1 for kimi/kimi-code
- Use url.Parse hostname match for Kimi User-Agent check instead of strings.Contains
- Add opencode to DefaultAPIBase test cases in factory_provider_test.go
- Add opencode migration tests (full config + APIBase-only) in migration_test.go
- Update AllProviders test count to include opencode (18 -> 19)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:22:49 +07:00
I Putu Eddy Irawan
81aeaf1ca0 fix: address Copilot review feedback on PR #932
- Deny regex: expand left boundary to match shell separators (;, &&, ||)
  to prevent bypass via chained commands like ";format c:"
- Path regex: add "." to initial char class to catch hidden dirs (/.ssh),
  add "=" to left boundary to catch flag-attached paths (--file=/etc/passwd)
- Add test: ModelName must match user model for GetModelConfig lookup
- Add test: stripSystemParts preserves reasoning_content in wire format
- Add test: forceCompression avoids orphaning tool result messages
- Add test: deny pattern blocks disk-wiping commands with shell separators
  while allowing legitimate --format flags

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:08:11 +07:00
I Putu Eddy Irawan
a6f4274870 feat: add message chunking in Telegram Send method
Split HTML content into 4000-char chunks before sending to handle cases
where markdown-to-HTML conversion causes messages to exceed Telegram's
4096-character limit. Uses the existing SplitMessage utility which
preserves code block integrity across chunk boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 08:56:12 +07:00
I Putu Eddy Irawan
ec540312da feat: add Kimi/Moonshot and Opencode provider support
- Add "kimi", "kimi-code", "moonshot" provider cases in factory.go
  with default API base https://api.kimi.com/coding/v1
- Add Kimi Code API User-Agent header (KimiCLI/0.77) for api.kimi.com
- Add "opencode" provider with default API base https://opencode.ai/zen/v1
- Add "opencode" to recognized HTTP-compatible protocols in factory_provider
- Add Opencode field to ProvidersConfig, IsEmpty, HasProvidersConfig
- Add opencode migration entry in ConvertProvidersToModelList
- Update moonshot fallback API base from api.moonshot.cn to api.kimi.com
2026-03-01 08:48:04 +07:00
I Putu Eddy Irawan
ee5b61884a fix: migration ModelName, reasoning_content, shell regex, loop boundary
1. migration.go: Set ModelName to userModel when provider matches so
   GetModelConfig(userModel) can find the entry. Previously the migration
   created entries with the provider name as ModelName (e.g. "moonshot")
   but lookup used the model name (e.g. "k2p5"), causing "model not found".

2. openai_compat/provider.go: Preserve reasoning_content in conversation
   history. Thinking models (e.g. Kimi K2, DeepSeek-R1) return
   reasoning_content which must be echoed back. Without it, APIs return
   400: "thinking is enabled but reasoning_content is missing".

3. shell.go: Fix deny pattern regex for format/mkfs/diskpart to use
   (?:^|\s) instead of \b to avoid matching --format flags.
   Fix path extraction regex to use submatch to avoid matching flags
   like -rf as paths.

4. loop.go: Adjust forceCompression mid-point to avoid splitting
   tool-call/result message pairs, which causes API errors.
2026-03-01 08:44:15 +07: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
Artem Yadelskyi
b0c8fc4a7e
feat(telegram): Fix conflicts 2026-02-28 23:32:15 +02:00
Artem Yadelskyi
aeed392c3f
Merge branch 'main' into telegram-bot-commands
# Conflicts:
#	pkg/channels/telegram.go
2026-02-28 23:27:26 +02: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
2026-02-28 19:59:17 +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
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
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
美電球
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
daming大铭
70fcbc5700
Merge pull request #824 from 0xYiliu/fix/issue-783-fallback-alias-resolution
fix: resolve fallback model alias parsing for issue #783
2026-02-28 00:25:18 +08:00
mosir
1161aee872 fix(config): keep empty agents.defaults.model in saved config 2026-02-28 00:18:10 +08:00
Petrichor
f2a71ca824
fix(lint): format imports in agent_id_test 2026-02-27 21:20:56 +08:00
美電球
f6c275f70c
Fix formatting of WhatsAppConfig struct fields 2026-02-27 20:25:02 +08:00
美電球
67e1dab408
Update test case for unicode letters preservation 2026-02-27 20:20:58 +08:00
美電球
3ad937f05b
Update function comment for SanitizeMessageContent 2026-02-27 20:20:25 +08:00
美電球
6fcc80bf44
Reformat WhatsAppConfig struct fields alignment 2026-02-27 20:20:00 +08:00
美電球
fa68023ac2
Merge branch 'refactor/channel-system' into main 2026-02-27 20:04:08 +08:00
Hoshina
d429dcdd76 chore: fix go fmt formatting issues after rebase
Apply go fmt to files that had formatting inconsistencies
(alignment, indentation) after rebasing onto refactor/channel-system.
2026-02-27 17:35:50 +08:00
Avisek Ray
b1a6b3898d
Merge branch 'sipeed:main' into reasoning-chnl 2026-02-27 14:50:14 +05:30
lxowalle
29d4019e62
fix: set max tokens to 32k, default model to null (#858)
* * Set default value of max tokens to 32768

* * set max tokens to 32k, default model to null

* * Fix format error
2026-02-27 17:02:25 +08:00
Avisek
f96cf3f8cc feat: Add reasoning_channel_id to communication platform configurations and improve message bus context cancellation handling. 2026-02-27 16:58:42 +08:00
Avisek
9f95aad5f3 feat: Introduce LLM reasoning fields to LLM responses and enable routing reasoning output to dedicated channels. 2026-02-27 16:58:42 +08:00
Petrichor
222d1a3086
refactor(modernize): apply safe modernize fixes 2026-02-27 16:35:07 +08:00
lxowalle
b6927c9a7a
Prompt to modify the max_tool_iterations parameter. (#855)
* Prompt to modify the max_tool_iterations parameter.

* fix typo and set max iterations to 50
2026-02-27 15:42:47 +08:00
nayihz
b5a4bb28b6 feat(discord): add proxy support and tests 2026-02-27 14:42:28 +08:00
Aditya Kalro
42ee9ab1e3 Complete the whatsapp native channel implementation based on the new channel interface 2026-02-26 22:35:52 -08:00
Aditya Kalro
a8644ca1c5 Refactor whatsapp native channel based on the new channel interface 2026-02-26 22:35:20 -08:00
Hoshina
779e4dfc38 docs(channels): add English README for channel system architecture 2026-02-27 03:33:21 +08:00