feat(channels): add human-like chat behavior

Squash merge PR #99 after resolving conflicts with current dev. PR CI run 26703381807 passed release-versioning, go, and web.
This commit is contained in:
Duy /zuey/ authored and GitHub committed 2026-05-31 11:44:56 +07:00
1 parent 3569f8d681
commit f0f39ce31f
51 files changed
+1786 -205

No files matched your search

+11
View File
@@ -71,6 +71,16 @@ The consumer routes system messages based on sender ID prefixes:
Normal channel messages pass through the shared inbound debouncer before agent execution. `gateway.inbound_debounce_ms` merges rapid text messages from the same `channel:chatID:senderID:agentID`; `0` means no debounce and positive values set the wait window. Agents can override the global value with `other_config.inbound_debounce_ms`; unset inherits the global config. Command/control messages such as `/stop`, `/reset`, and system escalations bypass the debouncer.
### Human-like Delivery
`gateway.chat_behavior` controls optional channel-only delivery polish:
- `quick_ack` sends one short acknowledgement after a configurable delay, only for non-streaming channel runs.
- `final_split` splits long final text replies into a bounded number of paragraph messages.
- Per-channel `chat_behavior` overrides inherit the gateway config unless a field is explicitly set.
Splitting is intentionally conservative. Replies containing fenced code, tables, lists, quotes, JSON/XML-ish blocks, or URL-only paragraphs remain a single message. Media replies and streaming deliveries are not split.
**Multi-attachment coalescing (#63).** Messages carrying attachments do NOT bypass the debouncer — that pre-fix shortcut was the source of N-replies for one user action. Instead, when media is present the effective window is `max(configured, mediaFloor)` so multi-file uploads land in the same buffer and flush together. Three surfaces apply the same invariant:
| Surface | Buffer key | Trigger |
@@ -105,6 +115,7 @@ Every channel must implement the base interface:
| `WebhookChannel` | Webhook HTTP handler mounting | Facebook, Feishu/Lark, Pancake |
| `ReactionChannel` | Status reactions on messages | Telegram, Slack, Feishu |
| `BlockReplyChannel` | Override gateway block_reply setting | Discord, Feishu/Lark, Pancake, Slack, Zalo OA, Zalo Personal |
| `ChatBehaviorChannel` | Override gateway chat_behavior setting | Bitrix24, Discord, Feishu/Lark, Pancake, Slack, Telegram, WhatsApp, Zalo OA, Zalo Personal |
`BaseChannel` provides a shared implementation that all channels embed: allowlist matching, `HandleMessage()`, `CheckPolicy()`, and user ID extraction.
+21
View File
@@ -6,6 +6,27 @@ Significant changes, features, and fixes in reverse chronological order.
## 2026-05-29
### Human-like channel delivery MVP (issue #67)
**New**
- Added `gateway.chat_behavior` runtime config for global quick acknowledgement and safe final multi-message splitting.
- Added per-channel `chat_behavior` override support for channel instances that already participate in channel delivery settings.
- Quick acknowledgements are emitted only for non-streaming channel runs and are cancelled when a block reply or terminal event arrives.
- Final splitting applies only to non-streaming text-only final replies; unsafe Markdown, code, tables, lists, quotes, JSON, and URL-only paragraphs stay as one message.
- Added `chat_behavior.preview` RPC plus dashboard controls and per-channel override fields.
**Validation**
- Added Go coverage for config resolution, preview, conservative splitting, and non-streaming quick acknowledgement delivery.
- Verified focused Go packages, both Go builds, `go vet`, web Vitest, web production build, and `git diff --check`.
**Out of scope**
- No archive/timeline storage, renderer, share/export, or interleaved run history changes. Those remain issue #76 scope.
---
### GitHub Releases update scratch dir fallback (issue #94)
- Changed GitHub Releases package updates to prefer `{runtimeDir}/tmp` for