Commit Graph

145 Commits

Author SHA1 Message Date
daming大铭 faec0261d0 Merge pull request #535 from xiaket/ci-enable-dupl-linter
ci: enable duplication linter in CI
2026-03-02 18:55:35 +08:00
美電球 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
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 32c864c309 enable dupl check
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-03-01 18:17:32 +11:00
Tong Niu 44a52c0cf6 fix(tools): close resp.Body on retry cancel and cache http.Client instances (#940)
* fix(tools): close resp.Body on retry cancel and cache http.Client instances

Fix resp.Body leak in DoRequestWithRetry where req.Body (request) was
incorrectly closed instead of resp.Body (response) on context cancel.
Cache http.Client on web search/fetch provider structs and channel
adapters (WeCom, LINE) to avoid per-call allocation overhead.

* fix(channels): preserve original http client timeouts for LINE and WeCom

Split LINE single 60s client into infoClient (10s) for bot info lookups
and apiClient (30s) for messaging API calls. Lower WeCom cached client
base timeout from 60s to 30s (matching uploadMedia), and ensure it is
always >= the configured ReplyTimeout so the per-request context
deadline remains the effective limit.

* refactor(tools): extract timeout consts and deduplicate WebFetchTool constructors

Address PR review feedback from xiaket:
- Define searchTimeout, perplexityTimeout, fetchTimeout, defaultMaxChars,
  and maxRedirects as package-level consts instead of magic numbers.
- Remove misleading "No proxy" comment in NewWebFetchTool.
- Deduplicate NewWebFetchTool by delegating to NewWebFetchToolWithProxy.

* test(utils): add context cancellation test for DoRequestWithRetry

Verify that resp.Body is properly closed when the context is canceled
during retry sleep, covering the C8 resp.Body leak fix.

* fix(utils): close resp in test to satisfy bodyclose linter

* fix(utils): eliminate flakiness in context cancellation retry test

Synchronize cancellation using an onRoundTrip callback from the
transport wrapper instead of a timing-based context timeout. This
ensures the first client.Do completes before cancel fires, so
cancellation always hits during sleepWithCtx.
2026-03-01 16:55:46 +11:00
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
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
wenjie 6c8866de6f fix: propagate error when no channels are enabled during startup (#897) 2026-02-28 16:04: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
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
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
美電球 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 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
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
Hoshina e5788e7f95 docs(channels): add Chinese README for channel system architecture 2026-02-27 03:33:21 +08:00
Hoshina 29ed650107 feat(channels): auto-orchestrate Placeholder/Typing/Reaction via capability interfaces
Define PlaceholderCapable, TypingCapable, and ReactionCapable interfaces
and have BaseChannel.HandleMessage auto-detect and trigger all three as
independent pipelines on inbound messages. This replaces the scattered
manual orchestration code in each channel's handleMessage with a single
unified dispatch in the framework layer.

Changes:
- Add PlaceholderCapable interface to interfaces.go
- Add ReactionCapable + RecordReactionUndo to interfaces.go
- BaseChannel.HandleMessage auto-triggers Typing → Reaction → Placeholder
- Manager gains reactionUndos sync.Map with TTL janitor cleanup
- Telegram: extract SendPlaceholder from manual code, add StartTyping
- Discord: add SendPlaceholder + StartTyping
- Pico: add SendPlaceholder (uses Pico Protocol message.create)
- Slack: extract ReactToMessage from manual code
- OneBot: extract ReactToMessage, remove leaked pendingEmojiMsg sync.Map
- LINE: move group-chat guard into StartTyping, remove manual orchestration
- Config: add Placeholder to PicoConfig; remove from Slack/LINE/OneBot
  (no MessageEditor, so placeholder config was dead code)
2026-02-27 03:33:21 +08:00
Hoshina ba98069a00 fix: resolve wastedassign lint warnings in channel subpackages
Remove wasted initial assignments before switch statements in
onebot (segType), telegram (filename), and wecom (mediaType).
2026-02-26 23:36:06 +08:00
Hoshina 35a035bdda fix: port main branch changes to channel subpackages after rebase
Port changes that were applied to the old pkg/channels/*.go files on main
to their new locations in channel subpackages:
- telegram: precompile regex, var transcribedText, GetModelName()
- discord: var transcribedText declaration
- onebot: resp.Body.Close(), "canceled" spelling, remove empty line
- slack: named return values in parseSlackChatID
- wecom: remove sendMarkdownMessage dead code
- whatsapp: resp.Body.Close() after Dial
- gateway/helpers: remove unused errors import
2026-02-26 23:24:35 +08:00
ex-takashima 61eae92b38 fix(line): log loading refresh errors, skip typing without recorder
Address review feedback from @alexhoshina and Codex:
- Log sendLoading errors in ticker goroutine instead of discarding
- Only start typing indicator when PlaceholderRecorder is available
  to avoid wasted API calls and unnecessary goroutine creation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:29:09 +09:00
ex-takashima e268ea82b9 Revert "feat(line): add StartTyping and PlaceholderRecorder integration"
This reverts commit ad736d71cb.
2026-02-26 20:17:45 +09:00
mattn 8a1fb03974 Perf/precompile regex (#687)
* perf: pre-compile regexes at package level

Move regexp.MustCompile calls from inside methods to package-level
variables in web.go (7 regexes) and loader.go (2 regexes).
This avoids repeated compilation on every invocation.

Amp-Thread-ID: https://ampcode.com/threads/T-019c79c3-ea1c-7471-b09d-be90ba0e1ca0
Co-authored-by: Amp <amp@ampcode.com>

* perf: pre-compile regexes at package level

* retain the helpful comment

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-02-26 20:44:03 +11:00
ex-takashima e450e9e053 feat(line): add StartTyping and PlaceholderRecorder integration
Implement TypingCapable interface for LINE channel using the
loading animation API (1:1 chats only, no group support).

- Add StartTyping() with 50s periodic refresh and context-based stop
- Integrate PlaceholderRecorder.RecordTypingStop in processEvent
- Skip RecordPlaceholder (LINE has no message edit API)
- Change sendLoading to accept context and return error
- Relax callAPI status check from 200 to 2xx range

Design consulted with Codex (GPT-5.2).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 16:43:41 +09:00
Aditya Kalro 49612adf8a Rebuilt after the refactoring of the base channel implementation. 2026-02-25 20:50:40 -08:00
Kai Xia b190e6e910 enable whitespace
Whitespace is a linter that checks for unnecessary newlines at the start and end of functions, if, for, etc.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:31:07 +11:00
Kai Xia d8b164b3d4 enable wastedassign
Finds wasted assignment statements.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:31:07 +11:00
Kai Xia 09cf8efde6 enable nakedret
Checks that functions with naked returns are not longer than a maximum size (can be zero).

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:31:07 +11:00
Kai Xia c5e8e19f54 enable misspell
Finds commonly misspelled English words.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:14:19 +11:00
Kai Xia 95f22bc07b enable bodyclose
Checks whether HTTP response body is closed successfully.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-25 21:14:19 +11:00
Hoshina c241c55a0d fix(channels): address PR #734 review comments
Rename fastID() to uniqueID() with a security caveat comment clarifying
the ID is not cryptographically secure, and add unit tests for the
refactored index-based split helper functions.
2026-02-25 11:51:21 +08:00
Hoshina 72e897f95a fix(channels): fix memory hazards in channel abstraction layer
Address 7 memory/architecture issues affecting long-running gateway
processes on embedded devices (<10MB RAM):

- Fix dispatcher busy-wait: remove select+default pattern that caused
  CPU spin after context cancellation; SubscribeOutbound handles ctx
  internally
- Add TTL janitor for typingStops/placeholders sync.Map entries to
  prevent unbounded accumulation when outbound paths fail
- Reduce queue buffers from 100 to 16 slots (~84% memory reduction)
- Optimize SplitMessage with index-based rune operations to reduce
  intermediate string/rune allocations
- Replace uuid.New() with atomic counter + random prefix for media
  scope IDs (eliminates per-call crypto/rand syscall)
- Lazy channel worker creation: defer goroutine+buffer allocation
  until channel.Start() succeeds
2026-02-24 22:30:22 +08:00
Kai Xia(夏恺) 100356e8ec refactor: cleanup dead code and turn on dead code detection in CI (#515)
* cleanup dead code.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* add these two back with flag.

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* fix ci

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* remove this confusing line

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* make fmt

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

* remove unused method.

picked up by golangci-lint run

Signed-off-by: Kai Xia <kaix+github@fastmail.com>

---------

Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-24 21:52:25 +08:00
daming大铭 d20cb364a2 Merge pull request #677 from yinwm/refactor/model-to-model-name
refactor(config): rename model field to model_name
2026-02-24 19:05:40 +08:00
Hoshina 0ede643e78 chore: apply PR #697 comment translations to refactored channel subpackages
Translate Chinese comments to English in qq, slack, and telegram channel
implementations, following the translation work done in PR #697. The
original PR modified the old parent package files, but these have been
moved to subpackages during the refactor, so translations are applied
to the new locations.
2026-02-24 12:17:11 +08:00
Aditya Kalro 04806bffe3 Moving logging from INFO to DEBUG for messages
Removing extrnaeous comments about mutex in loop.go

Made-with: Cursor
2026-02-23 15:50:55 -08:00
Kai Xia 6fb61539d7 translate Chinese comments
Signed-off-by: Kai Xia <kaix+github@fastmail.com>
2026-02-24 10:27:49 +11:00
Hoshina 6852f24025 fix: address PR #662 review comments (bus drain, context timeouts, onebot leak)
- Drain buffered messages in MessageBus.Close() so they aren't silently lost
- Replace all context.TODO() with context.WithTimeout(5s) across 7 call sites
- Fix OneBot pending channel leak: send nil sentinel in Stop() and handle
  nil response in sendAPIRequest() to unblock waiting goroutines
2026-02-23 21:34:37 +08:00
yinwm 712f5a8300 refactor(config): rename model field to model_name
The configuration field for specifying the model has been renamed from
"model" to "model_name" for better clarity and consistency with the
model_list configuration.

A GetModelName() accessor method has been added to maintain backward
compatibility. Existing configurations using the old "model" field will
continue to work correctly.

This change affects:
- Configuration structure (AgentDefaults struct)
- All references across the codebase
- Documentation in all language variants
- Example configuration files
2026-02-23 16:55:06 +08:00
Aditya Kalro 25362ec763 Add new build tag for WhatsApp native support to keep the binary smaller. 2026-02-22 19:22:32 -08:00
Aditya Kalro 76f8ab827f Handle dis 2026-02-22 19:18:02 -08:00