Commit Graph

465 Commits

Author SHA1 Message Date
美電球 658961b728 Merge pull request #2531 from is-Xiaoen/feat/delegate-tool
feat(tools): add delegate tool for cross-agent task handoff
2026-05-07 11:25:41 +08:00
Mauro 788cda5c7a Merge pull request #2762 from afjcjsbx/feat/stop-command
feat(agent): stop command
2026-05-06 18:19:14 +02:00
afjcjsbx a7e52e8a25 fix(agent): drain scoped follow-up queue when pending stop skips turn startup 2026-05-05 19:24:15 +02:00
xp d601b75268 fix(agent): send SVG attachments as files 2026-05-05 19:36:09 +08:00
Mauro ba4abff4a4 Merge pull request #2670 from david1gp/fix/tool-feedback-pretty-print
feat(agent): add pretty_print and disable_escape_html options for tool feedback
2026-05-04 21:47:32 +02:00
afjcjsbx d63430ab33 fix(agent): don't arm pending stop when /stop targets idle session 2026-05-04 13:10:02 +02:00
afjcjsbx 7a1f5fe8b9 fix test 2026-05-04 09:06:39 +02:00
Hoshina 057683d94c fix(agent): use runtime event kind for LLM retry 2026-05-04 15:06:34 +08:00
afjcjsbx a0245c7b02 feat(agent): stop command 2026-05-04 08:41:29 +02:00
afjcjsbx f3ef7090c5 feat(agent): stop command 2026-05-04 08:41:17 +02:00
Mauro be67aed4dc Merge pull request #2677 from alexhoshina/feat/runtime-events-plan
Feat/runtime events
2026-05-03 23:15:25 +02:00
Mauro 490d90749c Merge pull request #2717 from LiusCraft/feat/deepseek-vision-unsupported-error
feat: add DeepSeek vision unsupported error detection
2026-05-03 20:24:56 +02:00
Mauro 272dee3fca Merge pull request #2669 from david1gp/fix/network-error-retry
feat(agent): add network error retry with configurable max retries and backoff
2026-05-03 20:18:18 +02:00
Guoguo 5db008f384 fix(channels): dismiss tool feedback animation when turn ends via ResponseHandled (#2713)
* fix(channels): dismiss tool feedback animation when turn ends via ResponseHandled

When a tool sets ResponseHandled=true (e.g., send_file), the turn ends
without producing a final assistant response. This meant no outbound
message triggered FinalizeToolFeedbackMessage, leaving the animation
goroutine running indefinitely — editing the Feishu card every 3 seconds
with "." / ".." suffixes long after the tool had finished.

Fix: call DismissToolFeedback at "Tool output satisfied delivery" so the
tracker is cleared and the animation goroutine is stopped immediately.

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

* fix(adapters): add DismissToolFeedback to channelManagerAdapter

The adapter must implement the new interface method added in the
previous commit, otherwise the package fails to compile.

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

* fix(channels): pass InboundContext to DismissToolFeedback for topic-aware keys

Telegram forum topics use scoped tracker keys like "chatID/topicID",
resolved via ToolFeedbackMessageChatID with the InboundContext. The
previous nil context caused the lookup to fall back to the raw chatID,
missing the topic-scoped entry and leaving the animation goroutine
orphaned in forum-topic conversations.

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

* style: wrap long function signatures for golines

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 11:17:55 +08:00
Guoguo cb1e1a3595 fix(feishu): fix image download with API fallback and post image support (#2708)
* fix(feishu): fix image download with API fallback and post image support

- Add Image.Get API fallback when MessageResource.Get fails (different
  permission scope: im:resource vs im:message:readonly)
- Extract and download images from post (rich text) messages
- Extract images from interactive card messages
- Deduplicate post image keys across locales
- Add comprehensive tests for new helpers

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

* feat(media): add image path tags alongside base64 for LLM file access

Images are still base64-encoded into msg.Media for multimodal LLMs,
but now also get [image:path] tags injected into message content so
the LLM knows the local file path for save/forward operations.

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

* refactor(media): only auto-inject images for tool results, not user messages

Channel-received images (role=user) now get path tags only, letting
the LLM decide whether to view via load_image or just operate on
the file. Tool result images (role=tool, e.g. load_image) are
base64-encoded into a synthetic user message appended after the tool
message, since many LLM APIs don't support image_url in tool messages.

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

* fix(media): preserve tool-message ordering for multi-tool-call scenarios

Move synthetic user message (carrying base64 tool images) to after the
entire contiguous tool-message block instead of immediately after each
tool message. This preserves the assistant→tool→tool ordering required
by OpenAI-compatible APIs.

Also fix load_image to use generic [image: photo] placeholder so
injectPathTags can properly replace it with the actual path.

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

* fix(test): update load_image test for [image: photo] placeholder

The test was checking ForLLM for the media:// ref, but load_image now
emits the generic [image: photo] placeholder instead.

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

* fix(media): match all channel image placeholders in injectPathTags

Different channels emit different placeholder formats — Telegram/Feishu
use [image: photo], WeCom/WeChat/Line use bare [image], QQ/Discord use
[image: <filename>]. The previous string-match code only handled
[image: photo], so for the other channels the path tag was appended as
a duplicate, producing content like "[image] [image:/path]".

Switch to per-type regex that matches all generic placeholder shapes
while leaving path tags ([image:/path]) untouched. Also fixes the same
issue for [audio], [video], [file] tags. Added test coverage for the
various placeholder shapes.

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

* fix(media): skip path tag append for JSON content (Feishu cards/posts)

When content is structured JSON (interactive cards, post messages),
injectPathTags now skips the fallback append — only placeholder
replacement is attempted. This prevents corrupting JSON payloads
like {"schema":"2.0",...} with appended [image:/path] tags.

Adds looksLikeJSON() helper and three test cases covering JSON
objects, arrays, and an end-to-end resolveMediaRefs scenario with
Feishu card content.

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

* fix(media): prepend path tags for JSON content, narrow looksLikeJSON

Two fixes from code review:

1. looksLikeJSON now only checks for '{' prefix (not '['), avoiding
   false positives on regular text like "[update] see attached".

2. For JSON content (Feishu cards/posts), path tags are prepended
   before the JSON instead of being silently dropped. This ensures
   the LLM can discover attached images via the path tag while the
   JSON payload stays valid for downstream parsing.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-30 11:08:00 +08:00
LiusCraft 1722cfc282 feat: add DeepSeek vision unsupported error detection
Add detection for 'unknown variant' + 'image_url' error pattern used by
DeepSeek and other strict providers when vision is not supported.
These providers reject the image_url field at the JSON schema level
rather than returning a semantic 'not supported' message.
2026-04-30 02:24:29 +08:00
SiYue-ZO 2114e1a53f feat(config): wire serial tool into runtime and dashboard 2026-04-28 12:56:27 +08:00
David Siewert 8dca2a1319 fix: improve error handling and nil consistency in FormatArgsJSON
- Use fmt.Sprintf fallback instead of {} on encoding errors
- Normalize nil args to {} in FormatArgsJSON for consistent output
- Update tests to expect {} instead of null for nil args

Based on PR #2670 review feedback from afjcjsbx
2026-04-27 16:05:10 +06:00
David Siewert 97b1c3efec fix duplicate toolFeedbackArgsPreview function declaration 2026-04-27 15:42:18 +06:00
Hoshina 78fd080189 fix(events): keep runtime observers non-blocking
Add a non-blocking runtime publish path and switch hot-path publishers to it.

Enforce subscription timeout boundaries, keep ordered subscriber snapshots up to date on subscribe changes, expose all runtime kinds to process hooks, add safe log attrs for non-agent events, and close the gateway message bus on full shutdown.
2026-04-27 13:09:03 +08:00
Hoshina 4d6337fd26 fix runtime event logger reload and shutdown 2026-04-26 19:28:26 +08:00
Hoshina b3d9f86a01 feat(events): add configurable runtime event logging 2026-04-26 17:41:00 +08:00
Hoshina f4a24614b8 docs(events): remove stale subturn event names
Replace leftover SubTurnOrphanResultEvent and short subturn event references with runtime event kinds in comments, tests, and hook design notes.

Validation: GOCACHE=/tmp/picoclaw-go-cache go test ./pkg/agent -run TestSpawnSubTurn_OrphanResultRouting; make lint
2026-04-26 17:04:38 +08:00
Hoshina 795ee362ea refactor(events): emit agent runtime events directly
Remove the legacy EventKind/Event envelope mapping and let agent event emission build pkg/events.Event values directly.

Keep HookMeta as the shared hook metadata shape and preserve legacy observe string aliases by mapping them to runtime event kinds.

Validation: GOCACHE=/tmp/picoclaw-go-cache go test ./pkg/agent; make lint
2026-04-26 16:55:02 +08:00
Hoshina b954e6b8dc refactor(events): remove legacy agent event bus
Drop the old agent EventBus, SubscribeEvents/EventDrops public surface, legacy hook observer dispatch, and hook.event process notification path. Agent observations now flow through pkg/events runtime events.

Validation: go test ./pkg/agent; make lint
2026-04-26 16:39:35 +08:00
Hoshina b2249df3ea refactor(events): split agent event payload types
Move agent domain event payload structs out of the legacy event envelope file so the remaining EventKind/Event/EventMeta compatibility layer can be removed independently later.

Validation: go test ./pkg/agent; make lint
2026-04-26 16:31:52 +08:00
Hoshina 6e8a81bfbf test(events): prefer runtime hook observation
Use RuntimeEventObserver for the normal in-process hook observer path and make the process-hook helper assert hook.runtime_event notifications.

Validation: go test ./pkg/agent; make lint
2026-04-26 16:28:41 +08:00
Hoshina dc80e8f5f2 test(events): migrate agent tests to runtime events
Move AgentLoop event assertions to the runtime event stream and keep the legacy SubscribeEvents test only for dual-publish compatibility.

Validation: go test ./pkg/agent; make lint
2026-04-26 16:23:58 +08:00
Hoshina d9717b5632 refactor(events): start runtime event consumer migration
Deprecate the legacy agent event APIs and add a runtime event test helper, then migrate the follow-up queued test to the runtime event stream.

Validation: go test ./pkg/agent; make lint
2026-04-26 16:11:09 +08:00
Hoshina 8caf9aeb2b feat(events): publish runtime service events
Migrate hook observation to runtime events and update the process hook notification protocol. Add runtime event publication for message bus failures, channel lifecycle/outbound flow, gateway reloads, MCP server state, and MCP tool calls.

Validation: go test ./pkg/events/... ./pkg/bus ./pkg/agent ./pkg/channels ./pkg/mcp ./pkg/tools/integration ./pkg/gateway; make lint
2026-04-26 16:05:10 +08:00
Hoshina eedebabbea feat(events): add runtime event bus
Introduce pkg/events with filtered channels, subscription policies, backpressure, and stats. Wire AgentLoop to dual-publish legacy agent events into runtime events while preserving old event APIs.

Validation: go test ./pkg/events/... ./pkg/agent; go test -race ./pkg/events/...; make lint
2026-04-26 15:36:03 +08:00
David Siewert 9bc702ebaf fix test: enable pretty_print in tool feedback test 2026-04-25 23:09:40 +06:00
lc6464 6d04d15ce0 fix(tool-feedback): dedupe duplicate content and keep full explanations 2026-04-26 00:40:55 +08:00
lc6464 5cd10b594a feat(pico): add support for tool_calls in chat messages 2026-04-25 23:43:10 +08:00
David Siewert 3c4523e7aa test(agent): add unit tests for network error retry backoff strategy
- Test all network error types trigger retry (connection_reset, broken_pipe, read_tcp, eof, connection_refused)
- Test custom MaxLLMRetries and LLMRetryBackoffSecs config is respected
- Test retry count limit (1 initial + maxRetries retries)
- Add countingErrorProvider mock for deterministic call count verification
2026-04-25 21:19:13 +06:00
David Siewert bcc3d447a1 feat(agent): add pretty_print and disable_escape_html options for tool feedback
- Add PrettyPrint and DisableEscapeHTML config options to ToolFeedbackConfig
- Add FormatArgsJSON helper function with configurable pretty printing and HTML escaping
- Add toolFeedbackArgsPreviewWithOptions to pass formatting options
- Update pipeline_execute.go to use new formatting options for tool feedback

This fixes the issue where '&&' would be displayed as '\u0026' in tool
feedback messages and provides optional pretty-printing for better
readability.
2026-04-25 20:46:16 +06:00
David Siewert 06fad95719 feat(agent): add network error retry with configurable max retries and backoff
- Add isNetworkError detection for connection reset, broken pipe, read/write tcp, EOF
- Add retry logic with configurable exponential backoff for network errors
- Add config options max_llm_retries and llm_retry_backoff_secs in agents.defaults
- Network errors now retry with backoff (was previously not retried)
- Timeout errors now use configurable backoff instead of hardcoded 5s
- Default: 2 retries with 2s backoff (3 total attempts)
2026-04-25 19:08:46 +06:00
maxiaoyang 9f0f914ad7 Merge upstream/main into feat/delegate-tool
Resolves conflicts after the agent loop refactor on main:
- pkg/agent/loop.go was deleted upstream (logic split into agent.go,
  agent_init.go, pipeline.go, etc.); accepted the deletion.
- Moved the delegate tool registration block from the old loop.go
  into registerSharedTools in pkg/agent/agent_init.go, immediately
  after the spawn/spawn_status block. Logic and gating
  (len(registry.ListAgentIDs()) > 1) are unchanged.
- pkg/agent/subturn.go and pkg/agent/subturn_test.go merged cleanly
  on their own; TargetAgentID field, validation, registry lookup,
  and tests all preserved.

Verified locally:
- go build ./pkg/agent/... ./pkg/tools/...  clean
- go vet  clean
- TestDelegateTool* (17 cases) pass
- TestSpawnSubTurn_TargetAgentID_* (3 cases) pass
- TestDelegateToolRegistered_MultiAgent / _SingleAgent pass
- full pkg/agent + pkg/tools test suites green
2026-04-25 17:17:03 +08:00
美電球 41f4d95597 Merge pull request #2657 from lc6464/fix-deepseek-v4-thinking-history
fix(reasoning): persist canonical history for DeepSeek and web chat
2026-04-25 15:08:48 +08:00
美電球 788f76f422 Merge pull request #2666 from afjcjsbx/fix/mcp-nil-arguments
fix(mcp): send empty object instead of null for tool
2026-04-25 11:38:48 +08:00
美電球 2f91cc0a80 Merge pull request #2660 from afjcjsbx/fix/tool-feedback-json-format
fix(tool-feedback): format tool args as JSON code blocks
2026-04-25 11:34:09 +08:00
afjcjsbx 9d8f0dc877 fix(mcp): send empty object instead of null for tool 2026-04-24 21:24:29 +02:00
Hoshina 9ca73b944f fix(agent): preserve prompt hook and cache semantics 2026-04-25 01:25:17 +08:00
afjcjsbx 94a6b0c0f5 fix(tool-feedback): format tool args as JSON code blocks 2026-04-24 18:07:48 +02:00
lc6464 bb0f983708 fix(reasoning): persist canonical history for DeepSeek and web chat 2026-04-24 21:45:41 +08:00
Hoshina 48d8952591 feat(agent): migrate tool prompts to capability slots 2026-04-24 19:36:46 +08:00
Hoshina 2e65b1be83 feat(agent): add structured prompt layering 2026-04-24 18:14:28 +08:00
wenjie cac4f21746 fix(tools): improve web search provider fallback (#2629)
- centralize web search provider readiness and resolution logic
- fall back when the configured provider is unavailable or invalid
- allow native-search-capable models to use built-in search without the client tool
- simplify the tools page and add direct access to web search settings
- add backend, agent, and integration tests for the new selection behavior
2026-04-23 15:39:16 +08:00
lxowalle 451db2f5d8 Feat(channels): unify animated tool feedback across chat channels and Pico (#2622)
* feat(channels): unify tool feedback animation across discord telegram and feishu

* fix(tool-feedback): unify fallback and single-message delivery

* fix(channels): finalize tool feedback in place

* fix ci

* feat: improve tool feedback

* fix review blockers in pico token cache and tool feedback

fix(provider): preserve function thought signatures

fix(feishu): recover tool feedback after edit fallback

* * delete dead code

* fix(pico): clean up tool feedback progress state

* fix ci

* fix(web): preserve tool feedback line breaks in chat

* fix(channels): preserve tool feedback progress state

fix(pico): preserve context usage when finalizing tool feedback

chore: record branch review pass

fix: preserve tool feedback finalization state

fix(web): handle pico history update fallback

* fix ci
2026-04-23 10:35:50 +08:00
Mauro 68ceb54b36 Merge pull request #2535 from afjcjsbx/feat/mcp-channel-commands
feat(commands): add MCP slash commands and tool details
2026-04-22 14:54:28 +02:00