* fix(discord): clear stale heartbeat timers in SafeGatewayPlugin.connect()
The @buape/carbon@0.15.0 heartbeat setup has a race where stopHeartbeat()
runs before heartbeatInterval is assigned, leaving a stale setInterval with
a closed reconnectCallback. When the stale interval fires ~41s later it
throws an uncaught exception that bypasses the EventEmitter error path and
crashes the gateway process via process.on('uncaughtException').
Add a connect() override in SafeGatewayPlugin that unconditionally clears
both heartbeatInterval and firstHeartbeatTimeout before calling super. The
parent's connect() only calls stopHeartbeat() when isConnecting=false; when
isConnecting=true it returns early without clearing — this override fills
that gap.
Fixes#65009. Related: #64011, #63387, #62038.
* test(discord): assert super.connect() delegation in SafeGatewayPlugin tests
* fix(ci): update raw-fetch allowlist line numbers for gateway-plugin.ts
The connect() override added in the heartbeat fix shifted the two
pre-existing fetch() callsites from lines 370/436 to 387/453.
* docs(changelog): add discord heartbeat crash note
* test(cli): align plugin registry load-context mock
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(config): resolve CLI command aliases against parent plugin in plugins.allow (#64748)
The CLI allow guard checked command names (e.g. 'wiki') directly against
plugins.allow, missing the parent plugin ('memory-wiki'). Additionally,
memory-wiki did not declare 'wiki' as a commandAlias, so doctor --fix
would remove it as stale.
- Add commandAliases entry for 'wiki' in memory-wiki plugin manifest
- Check parent plugin ID in the CLI fallback allow guard
- Add tests for both allow and deny cases
* fix(cli): inject manifest registry for alias diagnostics
* Update CHANGELOG.md
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix: require confirmation before implicit device approval
Keep re-requested pairing entries from jumping the queue and force operators to confirm implicit latest-request approval so a refreshed attacker request cannot be silently approved.
* fix: require exact device pairing approval
* fix: stabilize reply CI checks
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* msteams: add pin/unpin, list-pins, and read message actions
Wire up Graph API endpoints for message read, pin, unpin, and list-pins
in the MS Teams extension, following the same patterns as edit/delete.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: address PR review comments for pin/unpin/read actions
- Handle 204 No Content in postGraphJson (Graph mutations may return empty body)
- Strip conversation:/user: prefixes in resolveConversationPath to avoid Graph 404s
- Remove dead variable in channel pin branch
- Rename unpin param from messageId to pinnedMessageId for semantic clarity
- Accept both pinnedMessageId and messageId in unpin action handler for compat
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: resolve user targets + add User-Agent to Graph helpers
- Resolve user:<aadId> targets to actual conversation IDs via conversation
store before Graph API calls (fixes 404 for DM-context actions)
- Add User-Agent header to postGraphJson/deleteGraphRequest for consistency
with fetchGraphJson after rebase onto main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: resolve DM targets to Graph chat IDs + expose pin IDs
- Prefer cached graphChatId over Bot Framework conversation IDs for user
targets; throw descriptive error when no Graph-compatible ID is available
- Add `id` field to list-pins rows so default formatters surface the pinned
resource ID needed for the unpin flow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* msteams: add react and reactions (list) message actions
* msteams: fix reaction count undercount and remove unpin messageId fallback
* msteams: wire pinnedMessageId through CLI/tool schema, add channel pin beta warnings, add list-pins pagination
* msteams: address PR #53432 remaining review feedback
* fix(msteams): route channel actions via teamId/channelId path (#53432)
* msteams: add unpin pinnedMessageId test coverage (#53432)
* fix(msteams): keep graph routing scoped to graph actions
* fix(msteams): align graph routing context types
* msteams: route fetchGraphAbsoluteUrl through fetchWithSsrFGuard
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm test -- src/cli/send-runtime/channel-outbound-send.test.ts src/gateway/server-methods/send.test.ts
Representative verification note:
- pnpm check reached tsgo in this worktree and then failed locally without actionable diagnostics; treated as an unhealthy local tooling signal rather than a PR-specific regression.
Co-authored-by: ShionEria <267903315+ShionEria@users.noreply.github.com>
Exit gateway configuration failures with EX_CONFIG and teach generated systemd units not to restart on that exit status.\n\nCo-authored-by: neo1027144-creator <neo1027144-creator@users.noreply.github.com>
When users put a runtime command name like "dreaming" into `plugins.allow`,
validation now explains that it is a command provided by a specific plugin
(e.g. "memory-core") and suggests using the plugin id instead, rather than
the generic "plugin not found" warning that previously created a circular
trap with the CLI error message.
Similarly, running `openclaw dreaming` from the CLI now explains that
`/dreaming` is a runtime slash command (not a CLI command) and points users
to `openclaw memory` for CLI operations or `/dreaming` in a chat session.
Fixes two related UX problems:
1. `plugins.allow: ["dreaming"]` → validation warned "plugin not found"
2. `openclaw dreaming status` → CLI said "add dreaming to plugins.allow"
(which then triggered problem 1)
Root cause: "dreaming" is a slash command registered by the memory-core
plugin via `api.registerCommand()`, not a standalone plugin or CLI command.