Commit Graph

640 Commits

Author SHA1 Message Date
afjcjsbx 0c117a073f feat(channel): echo voice audio transcription 2026-03-07 15:49:33 +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
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
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
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
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
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
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
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
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
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
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
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
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
Mauro 3e5b849984 Merge pull request #947 from dim/fix/transcription
Fix voice transcription
2026-03-04 18:37:24 +01:00
amagi a305c0a479 fix(openai_compat): avoid predeclared identifier in preview 2026-03-04 23:57:26 +08: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