* fix(reply): deliver final reply when queued follow-up claims session; scope dedupe to routed thread
Two core bugs caused composed replies to be silently dropped (no delivery,
no error) when a second message arrived in the same thread mid-run:
1. dispatch-from-config: ensureDispatchReplyOperation only kept the
dispatch-owned operation authoritative while it had no result. Once
runReplyAgent completed the operation to drain queued follow-ups, a
second same-thread inbound could claim the session and the first final
reply would try to re-acquire the lane instead of finishing delivery,
deadlocking behind the queued work. Keep the dispatch-owned operation
authoritative through final delivery.
2. reply-payloads-dedupe: messaging-tool reply dedupe compared only the
channel target, not the routed thread, so a send in one thread could
suppress a later reply in a different thread. Thread the routed thread
id through buildReplyPayloads + follow-up delivery and only fall back to
channel-only matching for providers without a thread-aware suppression
matcher when neither side carries thread evidence.
Adds regression tests; existing Telegram topic-suppression behavior is
preserved by gating the thread guard to providers lacking a plugin matcher.
* fix(reply): preserve threaded message delivery evidence
* fix(reply): dedupe final payloads by delivery route
* fix(slack): preserve native send thread evidence
* fix(reply): preserve explicit reply thread evidence
* fix(reply): align explicit reply route dedupe
* fix(reply): preserve delivery lane through final dispatch
* fix(mattermost): preserve threaded tool send routes
* chore(plugin-sdk): refresh API baseline
* fix(reply): align final delivery route dedupe
* fix(reply): gate followups on final delivery
* fix(reply): keep send receipts private
* fix(reply): infer implicit message provider
* fix(reply): align routed threading policy
* fix(reply): preserve queued delivery context
* fix(reply): hydrate queued system event routes
* fix(reply): hydrate queued execution routes
* fix(reply): scope final delivery barriers
* fix(slack): preserve DM target aliases
* fix(reply): mirror resolved source thread routes
* fix(mattermost): retain delayed delivery barrier
* fix(codex): separate message routing from tool policy
* fix(reply): consume normalized Slack DM targets once
* fix(slack): remove stale target alias
* style(reply): satisfy changed lint gates
* fix(mattermost): preserve explicit reply targets
* test: align Slack reply branch checks
* fix(reply): persist overflow summaries to admitted session
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
diagnostics.otel.captureContent.{toolInputs,toolOutputs} were documented
and config-wired but never produced any span content. Emit tool args and
results over the trusted private-data diagnostic channel (mirroring the
model-content path), and have the OTel exporter bound/redact/truncate them
before span export. Raw tool content never rides the public event bus.
Scope: core embedded-runner tool path (canonical producer). Codex
(async-batched) and Claude CLI remain follow-ups tracked by the issue.
Refs #77391
Move Zalo hosted outbound media metadata and expiry into plugin state, add SDK chunked hosted media storage, and keep CI/type/lint gates green after rebase.
Fixes#85124.
Anthropic standard API keys no longer resolve as provider usage auth for `openclaw status --usage`, so valid inference keys are not sent to Anthropic's OAuth usage endpoint and surfaced as misleading invalid bearer-token errors.
The provider usage-auth SDK result now has an explicit handled/no-token shape so provider hooks can suppress generic fallback without widening the OAuth helper contract. Docs, Plugin SDK API baseline, and extension package-boundary cache inputs were updated with the new contract.
Thanks @zhangguiping-xydt.
Proof:
- node scripts/run-vitest.mjs src/infra/provider-usage.auth.normalizes-keys.test.ts src/infra/provider-usage.auth.plugin.test.ts extensions/anthropic/index.test.ts
- pnpm plugin-sdk:api:check
- pnpm plugin-sdk:check-exports
- git diff --check origin/main...HEAD
- pnpm docs:list
- pnpm run test:extensions:package-boundary:compile
- autoreview clean: no accepted/actionable findings
- PR CI rollup green: 131 success, 22 skipped, 1 neutral, 0 failures
Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Show DeepSeek API-key account balance in status/auth-status usage surfaces by adding a summary-only provider usage snapshot path, a DeepSeek balance fetcher, SDK/docs coverage, and focused regression tests.
Maintainer verification accepted the additive provider-usage/status contract and the DeepSeek balance visibility boundary for authenticated status surfaces.
Proof:
- Live DeepSeek balance proof via 1Password-backed DEEPSEEK_API_KEY against https://api.deepseek.com/user/balance; key and balance amount redacted.
- GitHub CI run 26717953383 passed on the current head.
- Real behavior proof run 26718215605 passed after the PR body was refreshed.
- Local clean PR clone: git diff --check; node --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check; node scripts/run-vitest.mjs run src/agents/bash-tools.exec.path.test.ts.
Co-authored-by: Alex Tang <tangli1987118@hotmail.com>
Co-authored-by: litang9 <141409885+litang9@users.noreply.github.com>
## Summary
- Document scoped configured mention-pattern policy on the Groups page, including allow/deny mode semantics, supported conversation IDs, account-level precedence, and native-mention behavior.
- Add config UI help for `mentionPatterns.mode`, `allowIn`, and `denyIn` on Discord, Matrix, Slack, Telegram, and WhatsApp.
- Regenerate channel config/docs/plugin SDK metadata baselines for the new hint copy.
Refs #70864.
## Verification
- git diff --check
- pnpm format:docs:check
- pnpm docs:check-mdx
- pnpm docs:check-links
- pnpm config:channels:check
- pnpm config:docs:check
- pnpm plugin-sdk:api:check
- node scripts/run-vitest.mjs src/config/schema.hints.test.ts
- .agents/skills/autoreview/scripts/autoreview --mode local
## Real behavior proof
Behavior addressed: Documentation and config UI metadata for scoped configured mention-pattern policy.
Real environment tested: Local OpenClaw checkout on macOS.
Exact steps or command run after this patch: The verification commands listed above.
Evidence after fix: Docs formatting, MDX, link audit, generated config/channel/API baselines, and config hint tests passed; autoreview reported no accepted/actionable findings.
Observed result after fix: The Groups page now explains how to scope `messages.groupChat.mentionPatterns` with `channels.<channel>.mentionPatterns`, and config metadata exposes field help for the supported channels.
What was not tested: Live Discord, Matrix, Slack, Telegram, or WhatsApp inbound messages; this PR is documentation/config metadata only and follows the already-landed runtime behavior from #70864.
Provider-scoped configured regex mention patterns for Discord, Matrix, Slack, Telegram, and WhatsApp.
Native platform mentions keep their existing behavior, and unsupported channels do not opt into the new regex policy path. The new policy supports per-channel allow/deny routing through mentionPatterns.mode with allowIn and denyIn so group auto-reply regexes can be limited without broad global blast radius.
Refs #70864.
Supersedes #87200.
Thanks @patrick-slimelab.