* feat(mattermost): add thread.requireExplicitMention to opt out of thread auto-follow
Mattermost treats any reply in a thread the bot has participated in as an
implicit mention, so requireMention only gates the first message and the bot
then answers follow-ups addressed to other people for the participation TTL.
Slack exposes channels.slack.thread.requireExplicitMention for exactly this;
Mattermost had no equivalent and its strict schema rejected the key.
Add channels.mattermost.thread.requireExplicitMention (channel + per-account),
mirroring Slack. When set, thread participation no longer counts as a mention.
Default (unset/false) keeps today's auto-follow behavior unchanged.
Related: #108269
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(channels): add implicit mention policy foundation
* feat(channels): unify implicit mention policy
Co-authored-by: leon <dodoma0919@gmail.com>
* refactor(channels): keep implicit policy inside evaluator
* fix(channels): use exported implicit mention type
* chore(channels): satisfy extension lint
* fix(config): break implicit mention type cycle
* fix(plugin-sdk): account for implicit mention config export
* refactor(config): isolate implicit mention schema
* chore(plugin-sdk): align implicit mention surface budget
* fix(config): remove unused schema re-export
---------
Co-authored-by: leon <dodoma0919@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* refactor(channels): move reef, msteams, matrix, zalouser file state to SQLite with doctor imports
* fix(channels): harden SQLite state migrations
* test(reef): use SQLite flow stores in receipt suites
* fix(reef): validate restored request policy
* fix(reef): retain replay state through relay window
* docs(reef): describe durable state import
* fix(reef): honor configured legacy state path
* chore: leave changelog to release flow
* fix(reef): use managed temp root in flow tests
* fix(matrix): omit undefined device id from state
* fix(discord): open latest activity widget on fallback
* chore: remove release-owned changelog entry
* fix(discord): order activity fallback by delivery
* fix(discord): require atomic widget delivery updates
* test(discord): type activity delivery fixtures
* test(discord): model missing atomic state support
* fix(discord): order activity fallback by message snowflake
* docs(discord): clarify activity fallback order
Adds a Discord Activities integration so an agent can show a self-contained
HTML widget to Discord users, opened as a sandboxed Activity inside the client.
Off by default: routes, the discord_widget tool, and the launch handler register
only when channels.discord.activities is configured. OAuth identifies the user
and gates on the account allowlist; widget lookup is capability- or
instance-validated; token exchange is rate-limited; widget HTML runs in a
no-network sandboxed iframe.
Adds a non-interactive command surface (openclaw reef register|status|friend code|request|list|remove) so an agent can claim a handle and manage guarded friendships when its owner asks, without the interactive wizard. --json emits machine-readable output for automation. Registration is crash-safe and idempotent: guard defaults are provider-coupled, the full config is validated before the single-use magic-link token is consumed, a duplicate-handle claim recovers by proving key ownership and reconciling the relay's request policy, the exchanged session is cached scoped to relay+email (never printed) so reruns recover, one state dir is pinned to one identity, and friend removal revokes both the pin and the allowlist entry. Manifest gains commandAliases/onCommands so the CLI resolves; docs cover the agent-driven path.
* feat(ui): move Devices page into settings and redesign device inventory
- Devices now lives at /settings/devices (System group); /nodes stays as alias
- per-device form-factor icons (phone/browser/terminal/machine) with status dot
- equal-height header actions; stale cleanup and pairing only
- drop manual Refresh button; page already auto-refreshes via presence events + 30s poll
- dynamic connected/pending summary replaces static card subtitle
* style(ui): oxfmt pass + loading empty state for devices inventory
* chore(ui): sync locale bundles for devices settings copy; docs point at Settings → Devices
* refactor(ui): split device tile + pending rows out of view-inventory; drop unused icons
Keeps the TypeScript LOC ratchet green: view-inventory.ts returns below its
baseline and icons.ts sheds unused folderOpen/micOff/volumeOff glyphs.
* fix(ui): ratchet LOC baseline, drop unused DeviceIconSource export, settle devices settings copy
- baseline: icons.ts 693, view-inventory.ts back under the 500 ceiling
- subtitles.nodes now describes the settings page; nav tests updated
- locale bundles resynced (fallbacks=0)
* refactor(ui): rename token row param for reviewer-tool clarity
* fix(ui): collapse device rows in narrow containers and classify the TUI as a terminal client
Review findings: the nodes-entry grid override beat the shared 560px
list-item collapse, overflowing phone-width rows; openclaw-tui connects
with mode ui so only its client id marks it as a terminal.
* chore(ui): translate pending locale keys after rebase (fallbacks=0)
Prevent LINE group allowlist policy from inheriting DM allowFrom entries, so open DMs do not broaden group access. Keep group-specific allowlists and per-group overrides as the only group admission sources, and document the scoped behavior.
Co-authored-by: pgondhi987 <pgondhi987@users.noreply.github.com>
* refactor(config): retire flat streaming keys from the last six channel schemas
signal, irc, nextcloud-talk, whatsapp, googlechat, and mattermost now accept
only the nested streaming.{chunkMode,block.enabled,block.coalesce} shape
(mattermost also drops scalar/boolean streaming); flat spellings migrate via
each channel's defineChannelAliasMigration doctor contract with root seeding
for their wholesale-replace account merges.
* feat(channels): warn once per key when the deprecated flat streaming fallback is used
Bundled schemas now reject the flat delivery keys, so the streaming.ts
fallback only serves external SDK plugin configs; emit a once-per-process
per-key subsystem warning and pin the removal plan to the next release train.
* chore(config): regenerate bundled channel config metadata for nested-only streaming
* docs: describe nested-only channel streaming config and the SDK flat-key deprecation window
* fix(whatsapp): seed migrated named-account streaming from the accounts.default layer
WhatsApp resolution layers accounts.default shared config between root and
named accounts, so doctor-materialized account streaming objects now inherit
default-account settings over root ones; mattermost schema test moves to the
nested-only shape with explicit rejection coverage; scope flat-key deprecation
notes to the pending Matrix/Feishu migrations.
* fix(whatsapp): resolve the default account case-insensitively when seeding migrated streaming
* chore(plugin-sdk): repin API baseline for nested-only channel streaming types