Fix Codex app-server completion-stall recovery so replay-safe stdio completion-idle failures retry once, while progress/terminal turn-watch timeouts only surface timeout payloads.
Also preserve post-tool completion guards for scoped native response deltas and stabilize the oversized CONNECT timeout regression test picked up from latest main.
Co-authored-by: Kelaw - Keshav's Agent <keshavbotagent@gmail.com>
Adds the shared SQLite state database base, moves plugin keyed state into it with doctor migration coverage, and keeps generated Kysely guardrails aligned. Proof: focused SQLite/plugin-state tests, db:kysely:check, lint:kysely, architecture/dependency guards, autoreview, and PR CI all clean.
Move compaction planning work to a bounded worker-thread path so large transcript planning no longer monopolizes the agent event loop. Extract pure planning helpers, sanitize worker inputs before structured clone, package the worker entrypoint, and keep synchronous fallback only for worker-unavailable cases.
Fixes#86358.
Fixes#87438.
Bound unset heartbeat run timeouts so background heartbeat turns no longer inherit the built-in 48-hour interactive agent default. Timeout precedence is explicit heartbeat timeout, explicit global agent timeout, then heartbeat cadence capped at 600 seconds.
Verification:
- git diff --check
- Testbox tbx_01kstna69zvznn4fq7zrqr04a1: corepack pnpm test src/infra/heartbeat-runner.model-override.test.ts -- --reporter=verbose passed 13 tests
- Direct node --import tsx runtime probe verified 300s, 600s, 60s, and 45s timeout precedence cases
- Autoreview clean
Known CI state:
- PR CI run 26661465248 has failures matching latest main CI run 26661386468 at a7820b2f54; failures are outside this six-file heartbeat/docs diff.
Keep session lock cleanup from removing live OpenClaw-owned locks solely because they are old. Cleanup now reports age-only stale locks without deleting them, while still removing dead, orphaned, recycled, malformed-old, and non-OpenClaw-owned locks.
Update doctor docs and regression coverage for the cleanup/repair contract.
Refs #87779
Notte exposes a CDP-compatible WebSocket gateway at
wss://us-prod.notte.cc/sessions/connect?token=<NOTTE_API_KEY> that
auto-creates a session on connect — the same shape OpenClaw's existing
"Direct WebSocket CDP providers" section was generically framed for
(per #31085).
Real behaviour proof (against wss://us-prod.notte.cc/sessions/connect):
$ openclaw browser --browser-profile notte open https://example.com
opened: https://example.com/
tab: t4
id: 7FE04AC44931A6E1C799DE4ABF0DC807
A screenshot captured against the same session is a 1254x1111 PNG of
the rendered example.com page.
Playwright connectOverCDP flow against the same URL (today):
connectOverCDP 695ms
context.newCDPSession(page) 169ms
session.send('Target.getTargetInfo') → targetId 87ms
page.goto('https://example.com') 631ms
total 1.8s
AI-assisted (Claude Opus 4.7). codex review --base origin/main returned
clean. See PR description for the full pre-flight checklist.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Forward initial image/file attachments when spawning ACP subagents through the existing sessions_spawn attachment opt-in. Remove the PR-only acpEnabled config split so ACP uses the same attachment gate as other runtimes.
Also fix the PR branch CI fallout: type the browser element CLI request mock and use Vitest env stubs in the Azure speech test to satisfy the changed-path security scan.
Verification:
- GitHub CI passed on f6ca26b160.
- Autoreview clean.
- Crabbox AWS live OpenAI proof passed: cbx_a576d49493fe / run_081dcc6c6a1b.
Thanks @zhangguiping-xydt.
Fix `sessions.json` persistence after compaction transcript rotation.
When the agent runtime rotates from the pre-compaction session transcript to the post-compaction transcript, post-run consumers now receive the effective OpenClaw session id and session file. Backend CLI session ids remain backend metadata and no longer overwrite the top-level OpenClaw session identity.
Refs #88040.
Thanks @1052326311.
Verification:
- `node scripts/run-vitest.mjs src/agents/agent-command.compaction-rotation.test.ts src/agents/agent-command.live-model-switch.test.ts src/agents/command/session-store.test.ts`
- Autoreview clean
- GitHub CI green on PR head `c3d3c77ddf675bbba0b9ba6681b030a2f69a898c`
Fix claude-cli transcript resume so session-id rotation and transcript flush timing do not drop valid resume state.
- Capture the latest claude-cli session_id from JSONL output.
- Resolve Claude project transcript paths through the shared canonical project-dir resolver.
- Probe transcript content from the actual CLI process cwd.
- Thanks @benjamin1492!
Persist GitHub Copilot SDK session ids in the plugin-state SQLite store so separate OpenClaw process turns can resume the same Copilot-side session when the compatibility fingerprint still matches.
The fingerprint covers provider/model/cwd, resolved agent id, resolved Copilot home, and auth identity. Plugin-state lookup/register/delete failures are non-fatal, stale rows are invalidated, and reset delete failures use an in-process tombstone so reset does not accidentally reuse a durable binding.
Also routes the QQBot token POST through the plugin SDK SSRF guard with capture disabled for the secret-bearing request, preserving the current token lifetime validation from main.
Verification: focused Copilot and QQBot Vitest suites, raw channel fetch guard, autoreview clean, Blacksmith Testbox pnpm check:changed tbx_01kst9fwjmsfzwaxqatszcbf40, live local Copilot two-turn smoke with the same SDK session id persisted in SQLite.
Refs #88064
Summary:
- The PR changes plugin auto-enable materialization so an explicit empty `plugins.allow` stays empty while non-empty restrictive allowlists are still extended, and adds a regression test.
- PR surface: Source +3, Tests +17. Total +20 across 2 files.
- Reproducibility: yes. Source inspection of current main shows an empty array reaches `ensurePluginAllowlisted`, and the linked report gives a concrete `doctor --fix` config path that matches that code.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head c06837f5dd.
- Required merge gates passed before the squash merge.
Prepared head SHA: c06837f5dd
Review: https://github.com/openclaw/openclaw/pull/87883#issuecomment-4570537738
Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Active Memory recall now runs on its own queue lane instead of sharing the parent prompt-build lane.\n\nValidation:\n- git diff --check\n- node scripts/run-vitest.mjs extensions/active-memory/index.test.ts -t "runs recall on a dedicated active-memory lane"\n- fresh local gateway smoke with Active Memory + Memory Core + loopback OpenAI-compatible model: HTTP 200, active-memory start/done, recall elapsedMs=209\n\nFixes #79026.\nRelated: #72015.
Summary:
- The PR updates Codex doctor route repair to preserve explicit non-default `agentRuntime` pins across agent model maps and provider policies, adds regression coverage, and tightens a live-gateway test helper type guard.
- PR surface: Source +240, Tests +574. Total +814 across 3 files.
- Reproducibility: yes. The source path is clear from current main's model-map merge behavior and the PR's bef ... beRepairCodexRoutes` with the reported config, though this read-only review did not execute the test suite.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(doctor): preserve explicit non-default agentRuntime pin during le…
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8414…
Validation:
- ClawSweeper review passed for head c142ec1ef8.
- Required merge gates passed before the squash merge.
Prepared head SHA: c142ec1ef8
Review: https://github.com/openclaw/openclaw/pull/84362#issuecomment-4493152445
Co-authored-by: David Huang <nxmxbbd@gmail.com>
Co-authored-by: Nex <nex@dbitstec.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Add a general typed tool-progress contract so long-running non-exec tools can emit public channel progress without overloading model-facing tool content.
`web_fetch` now uses the generic delayed progress helper: it shows `Fetching page content...` only when the fetch is still pending after five seconds, clears the timer on completion/abort, passes the abort signal into guarded fetch, and avoids provider fallback or cached success after cancellation. The subscriber path accepts only explicit `visibility: "channel"` and `privacy: "public"` progress metadata, while untyped tool partials and exec output keep their existing behavior.
Docs now explain typed progress, delayed producer examples, and the `web_fetch` timing behavior.
Proof: `pnpm test src/agents/tools/web-tools.fetch.test.ts src/agents/embedded-agent-subscribe.handlers.tools.test.ts -- --run`; `pnpm docs:check-mdx`; changed-file `pnpm exec oxlint ...`; `git diff --check`; autoreview clean.
Match text slash command names case-insensitively across the reset/new fallback paths and the shared registry/control detection contract while preserving command argument casing.
Add regression coverage for uppercase and mixed-case reset/new commands plus registered non-reset commands such as `/STATUS`, `/Model`, `/T`, and `/COMPACT`.
Co-authored-by: zhangtong26 <zhangtong26@xiaomi.com>
Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
Remove stale Telegram-only wording from the reasoning stream acknowledgement and docs so channel-neutral behavior is reflected.
Fixes#68305.
Co-authored-by: Lanzhi <lizhan3@xiaomi.com>
Load `docker-compose.override.yml` when ClawDock builds its explicit Docker Compose file list, preserving standard Compose override behavior while keeping `docker-compose.extra.yml` as the final OpenClaw overlay.
Update Docker docs so manual Compose users include the same override order, and keep the regression test for the generated `_clawdock_compose` arguments.
Fixes#49909.
Thanks @spacegeologist.
Co-authored-by: zhengzuo0-ai <zheng.zuo0@gmail.com>
Preserve npm install selectors while recording resolved npm provenance for plugin and hook install/update records. Active `record.spec` stays the requested selector unless explicitly pinned, while resolved npm fields remain available for audit and diagnostics.
Adds focused coverage for hook-pack npm fallback provenance after the maintainer review found that path worth pinning down.
Co-authored-by: Phil <99397913+GitHoubi@users.noreply.github.com>
Forward Zalo quote-reply metadata from zca-js data.quote into the existing ReplyToId, ReplyToBody, and ReplyToIsQuote context keys so agents can correlate quoted replies with prior bot messages.
Adds parser and monitor regression coverage for quote extraction and context projection.
Fixes#86851.
Thanks @tanshanshan.
Remove unreachable optional chaining from four Discord message-handler-family runtime error calls.
This aligns the code with the required RuntimeEnv.error contract while leaving production behavior unchanged for valid runtimes. Maintainer-updated PR proof clarifies that shared queue reporter hooks still treat malformed runtime reporter failures as best-effort.
Clean up completed exec tool-call abort listeners so normal foreground completion and background-yield no longer retain the exec run/session context through AbortSignal listener state.
The listener cleanup now lives beside the exec listener registration and runs when the foreground process settles, rejects, or the tool returns a background running result. Existing abort/timeout/background behavior remains owned by the process supervisor and process registry.
Verification:
- gh pr checks 83022
- gh api repos/openclaw/openclaw/commits/fe86528ecb2043b6febef5c2eec53f9124be5543/check-runs
- git merge-tree --write-tree origin/main refs/remotes/pr/83022
- git diff --check origin/main...refs/remotes/pr/83022
- node AbortSignal add/remove listener probe
Thanks @c19354837.
Co-authored-by: Ninty <c19354837@hotmail.com>
Fixes#66479.
Workspace skills whose SKILL.md starts with a UTF-8 BOM now keep their shared markdown frontmatter metadata, so they remain discoverable through skills list. The fix strips one leading BOM at the parser boundary and adds parser plus workspace discovery regression coverage.
Thanks @jbetala7 for the fix.
Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com>
Route Microsoft Teams attachment downloads through the shared SSRF guarded fetch path so DNS validation is pinned into the dispatcher used for the actual request.
Keep Teams auth fallback and allowlisted HTTPS Authorization redirect behavior while failing closed for custom fetch hooks that cannot accept dispatcher injection.
Verification:
- CI=1 OPENCLAW_VITEST_MAX_WORKERS=1 timeout 300 node scripts/run-vitest.mjs run extensions/msteams/src/attachments/shared.test.ts extensions/msteams/src/attachments/bot-framework.test.ts src/infra/net/fetch-guard.ssrf.test.ts
- gh pr checks 87567 --repo openclaw/openclaw --watch=false
PR: #87567
Fix cron local-model preflight fallback handling so scheduled runs try configured fallback candidates before skipping when the local primary is unavailable.
Verification:
- GitHub CI on PR head fe884dab90: passing required CI checks.
- Local focused cron/model fallback tests passed earlier for the touched surface.
- Local merge-wrapper build and check passed on the prepared candidate.
- Local full pnpm test reported unrelated failures outside this PR's touched files; touched files are limited to cron docs, src/agents/model-fallback.ts, and src/cron/isolated-agent/*.
Co-authored-by: chen-zhang-cs-code <chenzhangcode@163.com>
Co-authored-by: Onur Solmaz <2453968+osolmaz@users.noreply.github.com>
Remove the chatType === 'direct' guard from
shouldAllowQuietChannelOwnedProgressCallbacks so that channel-owned native
progress callbacks (onToolStart, onItemEvent, onPlanUpdate,
onApprovalEvent, onCommandOutput, onPatchSummary, onCompactionStart/End)
are forwarded in group and group-channel sessions when verbose is off.
Previously the guard required chatType === 'direct', which meant that
/verbose off would suppress all progress callbacks in group sessions
while direct sessions continued to relay them. Message-level tool
summary suppression is handled separately; native channel relay hooks
should not be gated on chat type.
Closes#87612
Cache single-row gateway session child indexes without hiding live subagent registry changes.
Summary:
- Reuses store-derived child-session candidates for repeated single-row session loads.
- Keeps runtime subagent registry reads live per row so moved child sessions do not stay attached to stale parents.
- Versions the session-store cache and includes that version in the single-row cache key so same-object store rewrites cannot reuse stale child candidates.
- Adds focused regression coverage for cache reuse, live registry refresh, and same-object session-store writes.
Verification:
- git diff --check
- pnpm tsgo:prod
- pnpm test src/gateway/session-utils.single-row-cache.test.ts src/gateway/session-utils.subagent.test.ts -- --reporter=verbose
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- GitHub CI run 26620265206: passing
- Azure Crabbox cbx_a58389e50f49: single-row-loads 13.622240 ms before vs 1.869456 ms after, 7.29x speedup, 86.3% reduction
* feat: add Claude Opus 4.8 support
* fix: omit Vertex Opus sampling overrides
* fix: preserve Opus adaptive thinking levels
* fix: clamp Anthropic max effort support
* fix: use sha256 for QA mock call ids
* fix: type Anthropic transport test model metadata
* test: update PDF model default for Opus 4.8
Summary:
- This PR adds an internal gateway active-run projection flag, clears it during terminal lifecycle handling be ... ons.list on that flag, adds gateway regression coverage, and tightens memory-wiki confidence normalization.
- PR surface: Source +29, Tests +131. Total +160 across 7 files.
- Reproducibility: yes. Source inspection shows current main can broadcast terminal sessions.changed before ch ... the abort-controller entry, and the before/after recording supports the visible stuck In progress symptom.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(gateway): preserve chat retry guard after terminal state
- PR branch already contained follow-up commit before automerge: fix(gateway): clear completed session active runs
Validation:
- ClawSweeper review passed for head 9b132bdc2b.
- Required merge gates passed before the squash merge.
Prepared head SHA: 9b132bdc2b
Review: https://github.com/openclaw/openclaw/pull/87810#issuecomment-4569094800
Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Adds opt-in Discord progress-draft commentary for assistant preambles while keeping commentary hidden by default and final delivery unchanged.
Keeps commentary config Discord-specific, strips directive tags/NO_REPLY, and clears stale commentary rows without stopping the active draft stream.
Thanks @bryanpearson.
Co-authored-by: bryanpearson <bryanmpearson@gmail.com>
Preserve OpenClaw-owned embedded system prompts after active tool selection in both normal embedded attempts and compaction. Adds an exact base prompt path on AgentSession that keeps active tool prompt metadata current for extension hooks.
Fixes#87807.
Verification:
- mise exec node@24.16.0 -- node scripts/run-vitest.mjs src/agents/sessions/sdk.test.ts src/agents/embedded-agent-runner/system-prompt.test.ts src/agents/embedded-agent-runner/run/attempt.spawn-workspace.context-engine.test.ts src/agents/embedded-agent-runner/compact.hooks.test.ts --reporter=dot
- mise exec node@24.16.0 -- pnpm tsgo:core
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
Thanks @shakkernerd.
Handle exec-backed Gateway SecretRefs in doctor, lint, and health probing without executing providers by default.
- Add `openclaw doctor --allow-exec` for explicit SecretRef execution during lint/doctor checks.
- Skip only the active exec-backed gateway probe path and avoid local service diagnostics for remote-only skipped health.
- Keep env-winning and dormant fallback credentials probeable, stabilize related tests, and remove a stale live-shard fixture left by the moving base.
Verification:
- `node scripts/run-vitest.mjs src/commands/doctor-gateway-auth-token.test.ts src/commands/doctor.warns-state-directory-is-missing.e2e.test.ts src/gateway/credentials.test.ts src/gateway/probe-auth.test.ts src/commands/doctor-gateway-daemon-flow.test.ts test/scripts/test-live-shard.test.ts --reporter=verbose`
- `mise x node@24.13.0 -- pnpm prompt:snapshots:check`
- `pnpm tsgo:prod`
- `pnpm build`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- Crabbox AWS live config proof: `run_f44a4d9dae4e`
- GitHub CI: green on final head `88d24abdbf9529a59d75d1d5e04eac74bbbbc267` after rerunning a stale in-progress Security High workflow.
Co-authored-by: Merlin <258679497+funmerlin@users.noreply.github.com>
Fixes#87132.
Default Usage now requests all configured agents with `agentScope: "all"`, while selecting a specific agent sends `agentId` consistently to both session usage and cost usage calls. The gateway now supports explicit all-agent session usage, aggregates all-agent cost summaries across configured agents, and keeps scoped cache entries separate. Legacy gateway fallbacks remain for older `agentId` / `agentScope` support, with protocol docs/schema and Swift generated models updated.
Verification:
- `node scripts/run-vitest.mjs ui/src/ui/controllers/usage.node.test.ts ui/src/ui/app-render-usage-tab.test.ts ui/src/ui/views/usage.test.ts --reporter=dot`
- `node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway-methods.config.ts src/gateway/server-methods/usage.test.ts src/gateway/server-methods/usage.cost-usage-cache.test.ts src/gateway/server-methods/usage.sessions-usage.test.ts --reporter=dot`
- `pnpm check:test-types`
- `pnpm protocol:check`
- targeted `node scripts/run-oxlint.mjs ...`
- `git diff --check`
- autoreview clean after Swift compatibility fix
- PR CI green at head `d67156a3c552c4f9c8b6edf8516b6242bf5cdd26`
Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
Keep Codex reasoning updates as accumulated snapshots and mark the stream payload so channel consumers can distinguish snapshots from deltas.
This prevents Discord and Teams progress previews from duplicating accumulated reasoning text while preserving delta-style reasoning for legacy producers.
Refs #86708
Thanks @SebTardif.
Co-authored-by: OpenAI Codex <codex@openai.com>
Scope jiti filesystem transform caches for OpenClaw plugin loaders by package version and package.json install metadata so stale transforms cannot survive upgrades or package reinstalls.
Covers the central plugin module loader and the plugin SDK root alias CJS loader, while preserving jiti filesystem-cache env opt-outs and the TMPDIR cwd guard.
Verification: CI run 26601117143 passed; Real behavior proof run 26601445285 passed; CodeQL selected checks passed in run 26601117126; CodeQL Critical Quality plugin-boundary and plugin-sdk-package-contract passed in run 26601117074; OpenGrep PR diff passed in run 26601117137.
Refs: https://github.com/openclaw/openclaw/pull/87745
Thanks @fuller-stack-dev.
Route Codex app-server report-mode PreToolUse plugin approval requirements through the matching app-server approval request instead of failing closed. Shares duplicate in-flight approvals, preserves block/rewrite fail-closed behavior, and keeps generic plugin allow-always scoped to one Codex request. Supersedes #86978; thanks @clawSean for the original docs clarification.
Compact promoted short-term memory snippets before writing them into MEMORY.md, while keeping the full rehydrated snippet in recall state for ranking/provenance. Adds the deep-dreaming config surface and docs, with the default promoted snippet cap set to 160 estimated tokens.
Verification:
- git diff --check
- fnm exec --using v24.13.0 node scripts/run-vitest.mjs run extensions/memory-core/src/short-term-promotion.test.ts extensions/memory-core/src/dreaming.test.ts src/memory-host-sdk/dreaming.test.ts
- GitHub CI run 26605272497
- CodeQL security run 26605272404
Co-authored-by: AMARA <amara@eyeinthesky.pl>
Server-side cron job list filtering now applies schedule-kind and last-run-status filters before pagination, and the UI only sends table filters for the cron table view.
Fixes#9455.
Co-authored-by: Alix-007 <267018309+Alix-007@users.noreply.github.com>
* fix(msteams): rebase SDK migration onto current main
Reapply the msteams SDK migration (originally on feat/msteams-sdk-migration)
on top of upstream/main, resolving conflicts with parallel msteams work that
landed upstream during our session.
What got applied vs decisions made:
CLEANLY APPLIED (3-way patch):
- monitor.ts, monitor-handler.ts, polls.ts, reply-stream-controller.ts/.test.ts,
reply-dispatcher.ts, attachments/download.ts, monitor.lifecycle.test.ts,
monitor-handler/message-handler.ts, monitor-handler.types.ts, etc.
- streaming-message.ts + .test.ts deletions
WHOLESALE TAKE FROM ORIGINAL BRANCH (partial 3-way left broken cross-refs):
- sdk.ts, sdk.test.ts, messenger.ts, feedback-reflection.ts,
send-context.ts, send.test.ts
KEPT UPSTREAM (deferred for separate cleanup):
- extensions/msteams/package.json (still has jsonwebtoken/jwks-rsa per
Peter's b3bc60ae25 incremental approach)
- src/plugins/contracts/package-manifest.contract.test.ts (consistent with
package.json)
- pnpm-lock.yaml (avoids lockfile churn; pnpm install --frozen-lockfile clean)
ADAPTED:
- Dockerfile matrix-sdk-crypto check now wraps upstream's new retry-loop in
the if-matrix-bundled gate
KNOWN TEST FAILURES (need eyes — see PR comment):
- attachments.test.ts: 1 fail (pre-existing — warn meta arg shape changed in
our migration but test wasn't updated)
- reply-dispatcher.test.ts: 6 fails (pre-existing — tests mock old
TeamsHttpStream, not updated for our ctx.stream rewrite)
- send.test.ts: 4 fails (NEW from merge — upstream's send.ts changed media
loading; our mocks need updating or take upstream's send.test.ts wholesale)
UPSTREAM COMMITS POTENTIALLY MISSED (in wholesale-take files):
- 08c4af0ddf fix(msteams): accept conversation id allowlists
- e1840b8581 fix(msteams): bind global audience tokens to app id
- Channels turn-kernel refactor (ffe67e9cdc / 1ead1b2d18 / 9a9cd0c0ab) —
may be partially preserved in cleanly-patched files
Static checks pass: pnpm check:changed is green (typecheck, lint, contract
tests, import cycles, etc.). Manual testing required before merge.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(msteams): preserve thread routing for channel and group-chat replies
- monitor.ts: adaptSdkContext now uses ctx.reply() for channel and groupChat
conversations (so the SDK threads outbound activities to the inbound's
replyToId/serviceUrl) and ctx.send() only for personal DMs (where
reply()'s blockquote-prepend is ugly).
- messenger.ts: sendProactively passes resolvedThreadId on the non-thread
fallback path so channel @mentions that fall through outbound.ts -> send.ts
still land in the original thread instead of top-level.
Live-validated: channel @mention -> bot replies in thread, threaded reply
-> bot replies in same thread, no top-level leakage.
* fix(msteams): tag outbound SDK calls with OpenClaw User-Agent
- user-agent.ts: add buildOpenClawUserAgentFragment() that returns just
'OpenClaw/<version>'. The SDK's Client.clone merges this with its own
'teams.ts[apps]/<sdk-version>' identifier — passing the full buildUserAgent()
here would double-print the SDK token.
- sdk.ts: pass the fragment via AppOptions.client.headers['User-Agent'] so
the Teams backend can identify OpenClaw traffic for usage telemetry.
Final UA looks like 'OpenClaw/<openclaw-version> teams.ts[apps]/<sdk-version>'.
* fix(msteams): handle StreamCancelledError when user presses Stop mid-stream
The new SDK throws StreamCancelledError synchronously from stream.emit/update
when the user pressed Stop in Teams: Teams replies 403 to the next chunk
update, the SDK flips _canceled, and any subsequent emit() throws. The old
custom TeamsHttpStream either swallowed cancel or didn't expose this exception
type, so the migration inherited an SDK behavior the original code didn't have
to handle.
Symptom on 2026-05-05: pressing Stop during a streaming reply caused an
unhandled promise rejection that crashed the Node 24 process. Docker restarted
the gateway about two minutes after each Stop click. Two related bugs surfaced
once the crash was caught: the would-be block fallback re-delivered the full
text as a second message (duplicate after Stop), and the typing-keepalive kept
pulsing in Teams for the rest of the agent run because nothing told it to
stop.
reply-stream-controller.ts:
- Wrap stream.update / stream.emit / stream.close in try/catch that swallows
StreamCancelledError (matched by .name to dodge tsgo's SDK re-export
resolution quirk). Latch a wasCanceled flag so subsequent calls
short-circuit even if stream.canceled is stale.
- preparePayload() returns undefined when the stream was canceled — the
streamed prefix is already visible to the user, so dropping the payload
prevents a duplicate block message from overriding the cancel intent.
reply-dispatcher.ts:
- Typing-keepalive gate now also checks streamController.wasCanceled() so
typing pulses stop firing once Stop is observed. Otherwise the bot keeps
pulsing for the rest of the (uncancellable) agent run.
reply-stream-controller.test.ts:
- 6 new regression tests cover: cancel-during-emit (the crash scenario),
cancel-during-update, cancel-during-finalize, non-cancel error propagation,
post-cancel inactivity, and dropped-payload-on-cancel.
Live-validated: long streaming reply + Stop mid-stream -> stream freezes,
no duplicate message, no zombie typing, container stays healthy.
* fix(msteams): allow Bearer-token retry on Skype CDN attachment downloads
Teams puts inline DM images and clipboard-pasted images on
*.asm.skype.com URLs (e.g. us-api.asm.skype.com/v1/objects/<id>/views/imgo).
The download path in attachments/download.ts already does a plain GET first
and falls back to a Bearer-token retry on 401/403 — but the retry was gated
on the URL being in DEFAULT_MEDIA_AUTH_HOST_ALLOWLIST. asm.skype.com hosts
were in DEFAULT_MEDIA_HOST_ALLOWLIST (download permitted) but not in the
auth-host list, so a 401 plain-GET response skipped the retry and surfaced
as a missing image to the agent.
Add asm.skype.com and ams.skype.com to the auth allowlist so openclaw
attempts the Bearer-token retry consistently, matching how it treats the
other CDN/Bot-Framework hosts already in the list.
Note: this does not unblock all clipboard-pasted DM images — for at least
some tenants asm.skype.com rejects the Bot Framework token (returns 401
even with auth). Routing those URLs through <serviceUrl>/v3/attachments/...
the way #62219 already handles HTML-wrapped attachments is a separate
follow-up. The +button 'Upload from this device' path works today because
Teams generates an attachment with an HTML wrapper that triggers the
existing BF v3 attachments fallback in monitor-handler/inbound-media.ts.
* fix(msteams): align docker-compose msteams port default with plugin default
The plugin defaults webhook.port to 3978 (the Bot Framework standard used in
Microsoft samples) and listens on whatever the operator sets there. The
docker-compose.yml port mapping was exposing ${OPENCLAW_MSTEAMS_PORT:-3000}:3000
which only works for operators who explicitly set webhook.port to 3000.
Default-config users would have the plugin listening on 3978 inside the
container while compose forwarded 3000, causing connection refused.
Realign to ${OPENCLAW_MSTEAMS_PORT:-3978}:3978 so a default-config docker
compose up Just Works with Teams. Operators wanting a custom port override
both webhook.port in openclaw.json and OPENCLAW_MSTEAMS_PORT env var.
* fix(msteams): post-rebase reconciliation with main
Three follow-ups after rebasing the SDK migration onto current main:
- reply-dispatcher.ts: rename createChannelReplyPipeline to its post-rebase
identifier createChannelMessageReplyPipeline (the plugin-sdk barrel renamed
it during the 1454-commit rebase window).
- reply-dispatcher.ts: tighten the typing-keepalive onStartError signature to
(err: unknown) to satisfy upstream's stricter type checks.
- messenger.ts: drop the unconditional thread suffix on the bottom proactive
fallback. The previous behavior threaded all top-level proactive sends when
the stored ref had a threadId, which contradicts replyStyle='top-level'
semantics (and breaks the new upstream test). Threading on the proactive
path is preserved where it matters — the onRevoked branch within
replyStyle==='thread' still passes resolvedThreadId, which is the original
#55198 fix path.
- attachments.test.ts: update the warn-call assertion to match the migration's
inline message format (host=... error=...) — the structured meta object was
being dropped by the logger formatter pre-migration.
* feat(msteams): port streaming preview/progress features to ctx.stream
While the SDK migration was open, upstream landed preview/progress/draft
streaming features built on the OLD custom TeamsHttpStream class (which the
migration deletes). This commit ports the user-visible parts of those
features onto the new ctx.stream substrate so the migration doesn't lose
ground:
- pickInformativeStatusText: reads custom labels from
msteams.streaming.progressDraft config via resolveChannelProgressDraftLabel.
Falls back to the plugin-sdk default rotation. Pre-rebase used a hardcoded
4-string array.
- streamMode resolution: "partial" (default, per-token streaming),
"progress" (no tokens; preview card carries informative label that updates
as tools run), or "block" (no native streaming). Mode is read from
cfg.channels.msteams.streaming.preview.
- progress-draft gate: createChannelProgressDraftGate gates informative
updates so the rotating label only starts firing once meaningful work has
begun (avoids flicker before the first tool call).
- noteProgressWork() / pushProgressLine(): public methods on the controller
for callers (typing keepalive ticks, tool-event callbacks) to signal work.
pushProgressLine appends tool names as bullets above the rotating label
when streaming.previewToolProgress is enabled. Wiring these into actual
tool events is a separate follow-up.
- preparePayload progress-mode path: when stream is active but no tokens
streamed (progress mode) and a final text payload arrives, emit the text
into the stream so the preview card transitions in place to the final
reply on close().
reply-dispatcher: pass log + msteamsConfig + a stable progressSeed
(${accountId}:${conversation.id}) to createTeamsReplyStreamController so the
informative-label rotation is consistent across reconnects.
What's NOT ported and why:
- Live-edit-via-replaceInformativeWithFinal: the SDK's HttpStream natively
accumulates emitted text + entities + channelData and flushes ONE final
activity at close() using the same activity id as the preview. So the
separate "replace informative with final" call from upstream is
unnecessary — we get live-finalization for free via the SDK's design.
- pushProgressLine triggers from tool events: needs reply-pipeline-side
callbacks the new SDK migration didn't surface yet. Follow-up.
Tests: existing 22 reply-stream-controller tests still pass (the new
behaviors are additive).
* feat(msteams): wire pipeline tool events to streaming progress + fix test debt
Two follow-ups from yesterday's stopping point:
1. Wire pipeline events into the stream controller's progress-draft surface.
reply-dispatcher's replyOptions now exposes onReasoningStream, onToolStart,
onItemEvent, onPlanUpdate, onApprovalEvent, onCommandOutput callbacks that
format each event via the channel-streaming helpers and route through
streamController.pushProgressLine(). Mirrors the discord adapter's wiring.
Also:
- resolveChannelStreamingPreviewToolProgress + ...SuppressDefaultTool... so
the dispatcher exposes suppressDefaultToolProgressMessages on its
replyOptions when progress mode is on.
- Switch disableBlockStreaming resolution to the channel-streaming helpers
(resolveChannelPreviewStreamMode + resolveChannelStreamingBlockEnabled)
so streaming.mode='block' and streaming.block.enabled=true are honored
alongside the legacy blockStreaming boolean.
2. Fix the test debt that the rebase exposed:
- reply-dispatcher.test.ts: drop the streamInstances + TeamsHttpStream
mock pattern (file deleted by migration); replace with a streamMock
provided via context.stream that mirrors the SDK's IStreamer shape
(update/emit/close/canceled). Update assertions on sendInformativeUpdate
-> stream.update, stream.update -> stream.emit. Drop the
resumes-typing-between-segments test (no equivalent in the new
ctx.stream model — the SDK's HttpStream doesn't have a 'between
segments' notion; close ends the stream).
- send.test.ts: fix two stale mock targets — loadOutboundMediaFromUrl
comes from openclaw/plugin-sdk/outbound-media (not /msteams), and
resolveMarkdownTableMode comes from openclaw/plugin-sdk/markdown-table-runtime
(not /config-runtime). The previous mock paths were no-ops post-migration.
All 854 msteams tests now pass (was 17 failing in 4 files yesterday).
* fix(msteams): SDK streaming delta + use app.reply for proactive thread sends
Two narrow regressions exposed by the @microsoft/teams.apps migration:
- The SDK's HttpStream.emit appends each chunk to its internal buffer
(`this.text += activity.text`), but the channel reply pipeline emits
cumulative text on each chunk. Forwarding cumulative text into an
appending sink produced "chunk1 + chunk1chunk2 + chunk1chunk2chunk3..."
duplication for streamed (DM) replies. Track the emitted prefix length
in the stream controller and only forward the new tail.
- Replace the manual `${convId};messageid=${msgId}` URL construction in
the proactive thread fallback with `app.reply()`, which builds the
threaded conversation id via the SDK's own toThreadedConversationId
helper. Mechanically equivalent today; removes coupling to Teams' URL
format and tracks any future SDK changes.
Also adds the `reply` method to the structural MSTeamsApp type so the
refactor typechecks without casts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(msteams): bump @microsoft/teams.api and teams.apps to 2.0.10
2.0.10 adds support for the AAD v1 token issuer that the Bot Framework
JWT validator needs. The minor version bump pulls teams.cards / common /
graph along to 2.0.10 too.
Add `@microsoft/teams.*` to `minimumReleaseAgeExclude` in
pnpm-workspace.yaml because 2.0.10 was published <48h ago and the default
`minimumReleaseAge: 2880` (~2 days) would otherwise reject it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* revert(msteams): remove asm.skype.com auth-host allowlist additions
These hosts were added in dfc169d31d for inline DM image auth-retry, but
the commit's own footnote acknowledges it doesn't actually unblock
clipboard-pasted images (asm.skype.com rejects Bot Framework tokens in
at least some tenants). The change is unrelated to the SDK migration and
the user-visible bug it claimed to fix isn't fixed; lifting it out keeps
this PR focused on the migration. Will land as a separate PR if the
auth-allowlist consistency improvement is wanted on its own.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(msteams): typed ExpressAdapter helper, drop unknown-cast pyramid
The monitor's SDK bootstrap had an awkward chain:
httpServerAdapter: new (
(await import("@microsoft/teams.apps")) as unknown as {
ExpressAdapter: new (app: unknown) => unknown;
}
).ExpressAdapter(expressApp) as never,
Three casts (`unknown`, structural shape literal, `never`) were a
defensive workaround from when the SDK's hashed d.ts files tripped up
tsgo. With the SDK's exports now resolving cleanly, the same import can
be done with full types.
- Extend the lazy `loadSdkModules()` cache to include `ExpressAdapter`
alongside `App` so the dynamic import is shared.
- Add `createMSTeamsExpressAdapter(serverOrApp)` helper in `sdk.ts` that
encapsulates the lazy import and returns a properly-typed adapter
instance.
- Replace `httpServerAdapter`'s structural shape on `CreateMSTeamsAppOptions`
with the SDK's own `IHttpServerAdapter` interface (re-exported from
`@microsoft/teams.apps`).
The call site in `monitor.ts` becomes a single typed call with no `any`,
no `unknown`, no `as never`. The lazy-load behavior is preserved: nothing
imports `@microsoft/teams.apps` at module load time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(msteams): unbreak tsgo:extensions on the ExpressAdapter helper
CI's check-prod-types failed because the previous commit's typed helper
used `typeof import("@microsoft/teams.apps").ExpressAdapter`, which
tsc/tsgo's NodeNext resolution can't follow through the SDK's chained
`export *` barrel:
@microsoft/teams.apps/dist/index.d.ts:
export * from "./http"; // folder with index.d.ts
export * from "./app"; // single .d.ts file
The folder re-export drops `ExpressAdapter` and `IHttpServerAdapter` from
the namespace shape under `tsconfig.extensions.json` (passes under the
per-extension `tsconfig.json` because of inherited `paths`). Same root
cause as why we already model `MSTeamsApp` structurally (line 47 comment).
Switch the ExpressAdapter side to the same structural-shape pattern:
- Define `MSTeamsHttpServerAdapter` and `MSTeamsExpressAdapterCtor` locally.
- Cast `m.ExpressAdapter` once inside `loadSdkModules` (the runtime export
is fine; only the type surface is hidden).
- `httpServerAdapter` on `CreateMSTeamsAppOptions` and the return type of
`createMSTeamsExpressAdapter` use the local structural type.
Net result: the call site in `monitor.ts` stays the cast-free single line
the previous commit landed; the one remaining cast is confined to the
SDK-loading helper with an explanatory comment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(msteams): drop unused jsonwebtoken/jwks-rsa deps
The SDK migration removed all `import "jsonwebtoken"` / `import "jwks-rsa"`
from source code (the SDK does JWT validation internally now), but the
package.json entries and the matching `package-manifest.contract.test.ts`
expectation were left orphaned. Drop both:
- `extensions/msteams/package.json`: remove `jsonwebtoken` (^9), `jwks-rsa`
(^4) from `dependencies` and `@types/jsonwebtoken` from `devDependencies`.
- `src/plugins/contracts/package-manifest.contract.test.ts`: remove the
two entries from msteams's `pluginLocalRuntimeDeps` expectation.
- `monitor.lifecycle.test.ts`: extend the `./sdk.js` mock with the
`createMSTeamsExpressAdapter` export added in the typed-helper cleanup,
so the lifecycle suite still mounts after the deps drop.
Lockfile regenerates accordingly. All msteams tests (865) pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(msteams): drop unused @microsoft/teams.api direct dep
CI's deadcode:dependencies (knip) flagged @microsoft/teams.api as
unused in extensions/msteams. The plugin source uses structural type
aliases (MSTeamsActivityParams, MSTeamsActivityLike, etc.) to dodge
tsgo resolution bugs with teams.api's hashed d.ts files, so it never
imports teams.api directly. The package is brought in transitively
via @microsoft/teams.apps; the only other reference is
probe.test.ts's vi.mock("@microsoft/teams.api"), which works on the
import-path string and doesn't require a direct dep declaration.
Lockfile regenerates accordingly. tsgo:extensions, knip, and all
865 msteams tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(msteams): clear three CI gate failures (lint, contract, deprecated config API)
Three CI checks flagged on the latest run; all three are msteams-local
and unrelated to one another:
- **check-lint** / **check-additional-extension-bundled**:
`oxlint` flagged a redundant `as string[]` assertion in
`reply-dispatcher.ts:431`. The preceding `every((s: unknown) => typeof
s === "string")` already narrows the array type, so the cast does
nothing. Drop it.
- **checks-fast-contracts-plugins-c**: the
`package-manifest.contract.test.ts` `pluginLocalRuntimeDeps` for
msteams still expected `@microsoft/teams.api`, but the deadcode
cleanup commit (8f4050f51a) dropped it from
`extensions/msteams/package.json`. Remove it from the contract test
too — `teams.api` is only present transitively via `teams.apps`,
which is the reason knip flagged it.
- **check-additional-runtime-topology-architecture**: the deprecated
internal config API guard caught `messenger.ts:223` calling
`getMSTeamsRuntime().config.loadConfig()`. Switch to
`config.current()` to match the pattern used by phone-control,
synology-chat, and matrix.
Pre-existing failures on this run that are NOT msteams-related and not
caused by this PR: `check-test-types` (errors in
`src/agents/openai-transport-stream.test.ts` and
`pi-embedded-runner/openai-stream-wrappers.test.ts`) and `macos-swift`
(`hoistAwait` in `MacNodeRuntime.swift`). Leaving those for upstream.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(msteams): cast config.current() return to OpenClawConfig
The previous commit switched `messenger.ts:223` from the deprecated
`config.loadConfig()` to `config.current()` to satisfy the architecture
guard, but `config.current()` returns a deeply-readonly type that's not
assignable to the `Partial<OpenClawConfig>` parameter
`resolveMarkdownTableMode` expects (a mutable type from the SDK
contract). Phone-control, synology-chat, and matrix all cast at this
seam — adopt the same pattern.
Verified locally: tsgo:core, tsgo:extensions, check:architecture, and
test:extensions:package-boundary:compile all pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(msteams): address PR review — pre-auth body limit, allowlist log level, /api/messages forwarder, narrow release-age exclude
Four narrow fixes from the PR review (BradGroux + clawsweeper bot +
galiniliev's plan), each its own concern:
- **pre-auth-body-limit** (monitor.ts) — install
`express.json({ limit: DEFAULT_WEBHOOK_MAX_BODY_BYTES })` before the
bearer-presence gate and SDK route. Express memoizes the parsed body
on the request, so the SDK's later `json()` becomes a no-op and our
limit applies before any handler parses bodies. Closes the gap where
a `Bearer garbage`-shaped attacker could force unbounded JSON parsing
before token validation.
- **allowlist-error-logging** (monitor.ts) — restore main's `runtime.error`
level for the `msteams resolve failed` catch (was downgraded to
`runtime.log` mid-merge). Graph allowlist resolution failures are
security-relevant; they need to surface to operators.
- **legacy-messages-route** (monitor.ts) — when `webhook.path` is set
to a custom value, also accept POSTs on the legacy `/api/messages`
path with a one-time deprecation warning, then re-enter the Express
middleware chain on the configured path. Keeps existing Azure Bot
registrations working through the transition. Cast-free
(`expressApp(req, res, next)` works because `Application extends
IRouter extends RequestHandler`).
- **release-age-scope** (pnpm-workspace.yaml) — narrow
`@microsoft/teams.*` glob to the single direct dep
`@microsoft/teams.apps`. Future scoped packages no longer get a
freshness-guard pass.
Tests + checks: msteams suite (867), tsgo:core, tsgo:extensions,
tsgo:test, lint:extensions, check:architecture, knip --dependencies,
package-manifest contract, all green.
Still pending from the review (separate commits):
- auth-coverage-tests (Brad #1 + comment) — tests proving the SDK accepts
`aud=<bot app id>` and rejects `aud=api.botframework.com`.
- invoke-response-handling (Brad #2, codex P2) — file-consent invoke ack
must return through the SDK invoke handler, not `ctx.sendActivity`.
- stream-failure-fallback (codex P2, galin F5) — `streamFailed` latch so
partial streams fall back to block delivery on non-cancel errors.
- serviceurl-routing (Brad #4, codex P2) — proposed rebuttal pending
empirical confirmation that `smba.trafficmanager.net/teams` routes to
non-default-region conversations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(msteams): lock SDK auth contract — aud + v1/v2 issuer coverage
Adds extensions/msteams/src/auth-coverage.test.ts driving ServiceTokenValidator
and createEntraTokenValidator directly with jose-minted RS256 tokens against an
in-memory JWKS (via JwksClient.prototype patch). Locks in the three contract
cases @BradGroux flagged on #76262: aud=<bot app id> accepted, aud=api.botframework.com
rejected even when appid/azp match, and v1/v2 issuers accepted for allowed tenant
(disallowed tenant rejected).
Drops a stale ambient module declaration in src/types/microsoft-teams-sdk.d.ts
that was shadowing the SDK's real jwt-validator types with a long-renamed
createServiceTokenValidator surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): route file-consent invokes through typed app.on, drop broken invokeResponse send
Brad #2 / codex #4 on PR #76262 — `ctx.sendActivity({ type: "invokeResponse", ... })`
no longer reaches Teams as an HTTP InvokeResponse on the new SDK; it becomes
an outbound Bot Framework activity instead. Move file-consent accept/decline
to typed `app.on("file.consent.accept|decline", ...)` handlers. The SDK's
typed-route layer wraps a void return into `{ status: 200 }`
(`app.process.js:130`), so the manual ack disappears.
While in here, type `MSTeamsApp.on` properly. Borrowing the SDK's `App.on`
directly fails because that function carries a `this: App<TPlugin>`
constraint our structural alias can't satisfy, so we model an equivalent
generic over `IRoutes` with route-specific overloads (`card.action`,
`file.consent.*`, `activity`). The overloads work around a tsgo bug — the
`@microsoft/teams.api` `Activity` discriminated union collapses to `any`,
turning `ActivityRoutes` into a `[string]: RouteHandler<X, void>` index
signature that swallows every typed `Out` not already void-compatible
(card.action returns `AdaptiveCardActionResponse`; the others happen to
include `void`). Real tsc resolves cleanly. Linked upstream:
https://github.com/microsoft/typescript-go/issues/1057.
Other cleanups:
- Cast-free call sites for `adaptSdkContext` (now returns
`MSTeamsTurnContext` instead of `unknown`).
- card.action error responses include `innerHttpError` per the SDK's
`HttpError` shape requirement.
- Activity catch-all also skips `fileConsent/invoke` now that it's
typed-routed (parallel to the existing `adaptiveCard/action` skip).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): route SSO sign-in invokes through typed app.on, drop broken invokeResponse send
Brad #2 / codex #4 on PR #76262, SSO half. Continue the typed-route migration:
`signin/tokenExchange` and `signin/verifyState` now register via
`app.on("signin.token-exchange" | "signin.verify-state", ...)`. Per the
SDK's router, registering a user route with the same name as a system
route removes the system default — so the SDK's built-in handlers (which
would call `api.users.token.exchange` themselves and emit a `signin` event
nobody currently subscribes to) are silenced, and only ours runs. The SDK
wraps a void return into the HTTP 200 InvokeResponse, so the legacy
`ctx.sendActivity({ type: "invokeResponse", ... })` ack — broken on the new
SDK because it becomes an outbound BF activity instead of the HTTP
response — is gone.
The handler body is extracted from the activity-catch-all dispatch in
`monitor-handler.ts` to a new `signin-invoke.ts`, parallel to
`file-consent-invoke.ts`. `isSigninInvokeAuthorized` is now exported from
`monitor-handler.ts` so the new handler can reuse it. The activity
catch-all skips the SSO invoke names alongside the existing skips for
`adaptiveCard/action` and `fileConsent/invoke`.
`MSTeamsAppOn` overloads now cover the two SSO routes with their typed
ctx (`ISignInTokenExchangeInvokeActivity` / `ISignInVerifyStateInvokeActivity`).
Tests in `monitor-handler.sso.test.ts` were rewritten to call the
extracted handler directly — the `registered.run(ctx)` shape no longer
covers SSO, and the `expect(ctx.sendActivity).toHaveBeenCalledWith({ type:
"invokeResponse" })` assertions were dropped to match the new contract
(the SDK ack happens via the typed-route return value).
Note on overlap with #77784 (Stefan Stüben, Microsoft): that PR is doing
a much bigger SSO rework (sign-in card / sign-in-link / six-digit-code
fallbacks plus a `ctx.auth` plumbed to plugin tools). This change is
the small migration-correctness fix and is structured so #77784's SSO
body changes drop into the typed-route registrations cleanly on rebase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): route message-submit (feedback) invokes through typed app.on
Last invoke off the activity catch-all dispatch. `message/submitAction`
(thumbs up/down on AI-generated messages) now registers via
`app.on("message.submit", ...)`. Same shape as file-consent and SSO:
handler body extracted to a new `feedback-invoke.ts`, the SDK wraps a
void return into the HTTP 200 InvokeResponse, the broken
`ctx.sendActivity({ type: "invokeResponse", ... })` line is gone, and
the activity catch-all skips this invoke name alongside the others.
`isFeedbackInvokeAuthorized` is exported from `monitor-handler.ts` so
`feedback-invoke.ts` can reuse it. Tests in
`monitor-handler.feedback-authz.test.ts` were rewritten to call the
extracted handler directly — the old `handler.run(ctx)` shape no longer
intercepts feedback, and `originalRun` was removed because the typed
route is the dispatch point now.
`MSTeamsAppOn` overload added with the typed
`IMessageSubmitActionInvokeActivity` ctx, slotted between the SSO
overloads and the `activity` catch-all so `activity` stays last.
This leaves only `message`, `conversationUpdate`, and `messageReaction`
flowing through `app.on("activity", ...)` → `handler.run`. Promoting
those is the path to deleting the catch-all entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): fall back to block delivery when partial-mode stream fails mid-flight
codex #5 / Galin F5 on PR #76262. `reply-stream-controller.ts` previously
re-threw any non-cancel error from `stream.emit` during partial streaming
and from `stream.emit`/`stream.close` during finalize. Combined with
`preparePayload` suppressing block delivery once `tokensEmitted` was
true, that meant a network blip or API error mid-stream produced a
truncated reply with no recovery — the user saw the prefix that made it
through and nothing else.
Add a `streamFailed` latch parallel to `canceledLocally` / `tokensEmitted`:
- `onPartialReply`: catch non-cancel errors, set `streamFailed = true`,
log a warn, don't propagate (the pipeline must keep running so
`preparePayload` can decide).
- `preparePayload`: when `tokensEmitted && streamFailed`, fall through to
block delivery instead of suppressing. The user may see a duplicate
(streamed prefix + full block reply); intentional — matches the
pre-migration `TeamsHttpStream.hasContent` recovery and is better than
truncated-only.
- `finalize`: same latch + warn on non-cancel close failure, swallow
rather than throw. The streamed content already reached the user; the
closing activity (AI-Generated marker, feedback channelData) is the
only loss, not worth blowing up the dispatcher.
- `isStreamActive` returns false once the stream has failed.
New tests cover crash-mid-stream after tokens were emitted (assert block
delivery payload is returned), happy-path no-duplicate behavior (assert
`preparePayload` still suppresses when nothing failed), and finalize
close-failure (assert no throw). The pre-existing "re-throws non-cancel"
test was inverted to assert non-throwing latch behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): declare @microsoft/teams.api as a runtime dependency
Type-only `import("@microsoft/teams.api/dist/...").TypeName` references
in `sdk.ts` (added when typed `MSTeamsApp.on` overloads were introduced)
are picked up by the `extension-runtime-dependencies` contract test as
genuine runtime imports. Declaring `@microsoft/teams.api` as a direct
dep makes the contract pass; the package was already coming in
transitively via `@microsoft/teams.apps`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(msteams): keep SSO on SDK signin routes
* test(msteams): avoid redundant signin handler assertion
* docs(msteams): clarify Teams cloud support
* fix(msteams): use current SDK string helper
* fix(msteams): gate SDK invoke side effects
* test(msteams): avoid implicit any in lifecycle tests
* fix(msteams): preserve SDK user agent and matrix check
* fix(msteams): expose SDK common dependency
* fix(msteams): use SDK user agent merge
* fix(msteams): fall back when stream close no-ops
* chore(msteams): drop unrelated merge artifacts
* chore(msteams): restore unrelated main files
* chore(msteams): restore unrelated main files
* chore(msteams): restore unrelated main files
* test(msteams): type stream close mock result
* fix(msteams): configure Teams cloud service URL
* chore(msteams): refresh shrinkwrap
* chore(deps): refresh shrinkwrap locks
* chore(ci): rerun guards after main sync
* chore(deps): refresh shrinkwrap for node 24
* chore(config): refresh docs baseline
* fix(msteams): preserve Teams SDK proactive references
* fix(msteams): harden SDK proactive sends
* fix(msteams): align service url contract
* test: fix bonjour beacon type narrowing
* fix(msteams): ignore ambient service url
* fix(msteams): fall through submit invokes
* test: align shrinkwrap override policy with Teams SDK deps
* fix(msteams): ack invoke routes promptly
* fix(msteams): support china cloud boundaries
* test: sync PR with current CI gates
* test: isolate channel setup registry metadata
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Recover Codex compaction paths when a stale app-server thread binding returns an unstructured `thread not found` failure. The raw missing-thread response now shares the same recovery behavior as structured missing/stale binding failures for preflight, queued compaction, and CLI fallback.
Fixes#87736.
Co-authored-by: Paul Frederiksen <paul@paulfrederiksen.com>
Summary:
- The PR reorders embedded attempt cleanup to release the session write lock before session/MCP/LSP teardown, treats sessions_yield cleanup as abort-like for flush timing, and adds focused regression tests.
- PR surface: Source +14, Tests +71. Total +85 across 3 files.
- Reproducibility: yes. Source inspection shows current main releases the cleanup lock only after runtime tear ... R body’s terminal proof exercises the same ordering with production cleanup and filesystem lock primitives.
Automerge notes:
- PR branch already contained follow-up commit before automerge: Merge branch 'main' into fix/session-lock-release-before-teardown
Validation:
- ClawSweeper review passed for head 178192fa0e.
- Required merge gates passed before the squash merge.
Prepared head SHA: 178192fa0e
Review: https://github.com/openclaw/openclaw/pull/87747#issuecomment-4566994280
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Generated-media completions now use the existing idempotent direct-media fallback when active requester wake has already failed and the requester-agent handoff hits a session write-lock-shaped no-response error. Generic requester-agent handoff errors still fail visibly instead of direct-sending after an unknown side effect.
Release-note context: fixes a message-delivery loss path for generated images, music, and video where the artifact had been created but the final handoff could be reported as failed after a session write lock.
Verification:
- GitHub CI run 26601111985 passed at b0be994332.
- Blacksmith Testbox through Crabbox tbx_01ksr2jtt3fnz0zqvwmqq513h7 covered the exact lock fallback and qa-channel generated-media smoke.
- git diff --check origin/main...refs/remotes/pull/87741/head passed before merge.
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
Reuses the current plugin metadata snapshot in facade activation checks when the resolved boundary config matches, avoiding repeated manifest registry loads on the facade path.
Falls back to manifest registry loading when the current snapshot is missing or belongs to a different config/environment. Adds regression coverage for snapshot mismatch, snapshot reuse, and Windows path normalization.
Co-authored-by: 郑苏波 (Super Zheng) <superzheng@tencent.com>
Bound aggregate tool-result history at the provider prompt boundary without rewriting persisted session entries.
Provider-visible prompt history now trims older aggregate tool results before newer evidence, while canonical session history, slash/extension command handlers, and context-engine afterTurn snapshots stay unmodified.
Co-authored-by: luyifan <al3060388206@gmail.com>
* fix(nvidia): load featured model catalog
Co-authored-by: CaptainTimon <CaptainTimon@users.noreply.github.com>
* fix(nvidia): widen catalog fetch timeout
* fix(nvidia): cover catalog registration
* fix(picker): include provider catalog loader
* fix(nvidia): guard featured catalog fetch
* fix(nvidia): sync bundled catalog with live API
Replace minimaxai/minimax-m2.5 (MiniMax M2.5) with minimaxai/minimax-m2.7 (Minimax M2.7) and z-ai/glm5 (GLM-5) with z-ai/glm-5.1 (GLM 5.1) in the bundled fallback catalog to match NVIDIA's public featured-models endpoint.
Update docs table and all extension test expectations.
* fix(nvidia): retain shipped catalog refs
* fix(picker): keep alias catalog rows
* fix(nvidia): restore live catalog priority
---------
Co-authored-by: CaptainTimon <CaptainTimon@users.noreply.github.com>
Summary:
- The PR changes three TUI final chat-event early returns to call `tui.requestRender(true)` and adds focused event-handler assertions for those branches.
- PR surface: Source 0, Tests +25. Total +25 across 2 files.
- Reproducibility: yes. Current main and the latest release still have the three unforced final-event repaint calls, and the linked source PR includes PTY terminal proof showing the changed behavior after the patch.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(tui): force repaint final chat events
Validation:
- ClawSweeper review passed for head 570dc3af86.
- Required merge gates passed before the squash merge.
Prepared head SHA: 570dc3af86
Review: https://github.com/openclaw/openclaw/pull/87423#issuecomment-4558845936
Co-authored-by: Ted Li <tl2493@columbia.edu>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Narrow the abort-settle timeout helper to the env keys it reads and keep the dynamic live-model hook unit test from loading provider normalization/runtime plugins.\n\nProof: focused Vitest for live-model-dynamic-candidates, oxfmt/oxlint/diff checks, autoreview clean, AWS Crabbox run_8a485e593c2e corepack pnpm check:changed exit 0, and PR CI green.
Summary:
- The PR updates the bundled MiniMax music provider to request streaming hex responses, decode SSE/audio bodie ... while preserving JSON/url fallbacks, and adds provider tests for streaming, fallback, and timeout behavior.
- PR surface: Source +148, Tests +152. Total +300 across 2 files.
- Reproducibility: yes. by source inspection and live proof, though I did not run a fresh live reproduction. C ... s provider fallback, and the source PR reports a 130s live MiniMax provider run succeeding after the patch.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(minimax): stream music generation responses
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8456…
Validation:
- ClawSweeper review passed for head 806b0b40f2.
- Required merge gates passed before the squash merge.
Prepared head SHA: 806b0b40f2
Review: https://github.com/openclaw/openclaw/pull/84764#issuecomment-4504175527
Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Render Slack progress-mode updates as native task-card progress blocks, with bounded Slack chunk text and stable fallback behavior.
Also deep-merge Slack account streaming objects over top-level defaults while preserving legacy scalar account overrides, and keep the plugin SDK fetch runtime import path from evaluating guarded-fetch dispatcher code.
Verification:
- pnpm test extensions/slack/src/progress-blocks.test.ts extensions/slack/src/accounts.test.ts src/plugin-sdk/fetch-runtime.test.ts
- pnpm lint --threads=8
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode local
- GitHub PR checks green on #87748 at 4803e98820
Refs #82258
Co-authored-by: Simon van Laak <32648751+simonvanlaak@users.noreply.github.com>
Support grouped skill folders while keeping skill invocation flat via frontmatter names.
Includes bounded nested SKILL.md discovery, refresh/watch coverage for grouped folders, plugin symlink containment, and docs for grouped skill organization.
Verification:
- Node 24 targeted skill discovery and refresh tests passed locally.
- Docs checks passed locally and in CI.
- Autoreview clean.
- Crabbox live OpenAI proof showed nested foo/bar skills listed and visible in the agent system prompt.
- CI run 26595118581 passed.
Summary:
- The branch preserves current Claude Haiku 4.5 refs in the Anthropic resolver and doctor migration, repoints the bare `haiku` family alias to `claude-haiku-4-5`, and updates regression tests.
- PR surface: Source +5, Tests +21. Total +26 across 4 files.
- Reproducibility: yes. Current main source maps the bare `haiku` alias and explicit Haiku 4.5 migration path ... de-sonnet-4-6`; the PR body also supplies before/after terminal proof for the resolver and migration tests.
Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.
Validation:
- ClawSweeper review passed for head 64429e23b3.
- Required merge gates passed before the squash merge.
Prepared head SHA: 64429e23b3
Review: https://github.com/openclaw/openclaw/pull/87719#issuecomment-4566419633
Co-authored-by: alkor2000 <200923177@qq.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Cap Dreaming short-term recall stores so repeated recall recording, repair, and promotion application cannot grow the JSON artifact without bound.
The fix keeps full normalized snippets for recall identity and contamination checks before truncating persisted snippets, exposes the new overflow audit code through the SDK facade, and adds regression coverage for recording, repair, promotion rehydration, and deterministic retention ties.
Fixes#87095.
Verification:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs extensions/memory-core/src/short-term-promotion.test.ts src/commands/doctor-memory-search.test.ts src/plugin-sdk/memory-core-engine-runtime.test.ts
- pnpm tsgo:prod
- pnpm check:test-types
- pnpm lint --threads=8
- git diff --check
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- PR CI run 26594527697: unrelated current-main failures only in checks-node-agentic-plugin-sdk and checks-node-agentic-agents; same failures reproduced on main run 26594198639.
Co-authored-by: ai-hpc <mail.speedy.hpc@hotmail.com>
Wrap Ollama native streams with the shared plain-text tool-call compatibility wrapper so local/plain-text tool requests are delivered as structured toolCall events when matching tools are available.
Verified with live local Ollama proof, focused Testbox Vitest, Testbox check:changed, and autoreview.
Summary:
- The branch filters OpenClaw CLI image-cache paths out of prompt image-reference detection and adds parser/helper regression tests.
- PR surface: Source +17, Tests +65. Total +82 across 3 files.
- Reproducibility: yes. source-level reproduction is high confidence: current main still scans replayed prompt ... ectImageReferences and has no cache-path exclusion before loadPromptRefImages can reload stale image paths.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(images): skip CLI image cache refs
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-8750…
Validation:
- ClawSweeper review passed for head dfe0408df8.
- Required merge gates passed before the squash merge.
Prepared head SHA: dfe0408df8
Review: https://github.com/openclaw/openclaw/pull/87523#issuecomment-4560945125
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Summary:
- The PR changes the Control UI chat session picker blur handler to skip empty-query search application and adds a regression test that picker options remain clickable after an empty search blur.
- PR surface: Source +4, Tests +52. Total +56 across 2 files.
- Reproducibility: yes. The issue steps, before recording, and current-main source path all point to the same ... r clearing picker state before click delivery; I did not rerun a live browser repro in this read-only pass.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(ui): preserve session picker on empty search blur
Validation:
- ClawSweeper review passed for head bb14687756.
- Required merge gates passed before the squash merge.
Prepared head SHA: bb14687756
Review: https://github.com/openclaw/openclaw/pull/87682#issuecomment-4565441074
Co-authored-by: Ryan Weng <14496969+ryan4559@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Surface inbound bundle-MCP structuredContent as the model-visible result when present so agents can read Codex MCP threadId values and continue with codex-reply. Preserve non-structured content behavior, preserve the empty-result fallback, and keep details.structuredContent for internal consumers.
Also remove an unused secrets path helper that was breaking the latest prod-type gate on main.
Fixes#87511.
Verification:
- node scripts/run-vitest.mjs src/agents/agent-bundle-mcp-tools.materialize.test.ts
- pnpm exec oxfmt --check src/secrets/path-utils.ts src/agents/agent-bundle-mcp-materialize.ts src/agents/agent-bundle-mcp-tools.materialize.test.ts
- pnpm tsgo:prod
- local check-guards shard commands
- live Codex MCP smoke with codex__codex and codex__codex-reply same-thread continuation
- autoreview clean
- CI run 26587222874 green
Co-authored-by: Pluviobyte <Pluviobyte@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Fix replay handling for voice-call webhooks so duplicate signed requests do not mint or expose realtime stream tokens.
- Return token-free Twilio replay TwiML before realtime setup shortcuts.
- Cache bounded non-Twilio first responses for idempotent replay XML while skipping duplicate side effects.
- Cover Twilio realtime replay and Plivo replay behavior with regression tests.
- Remove an unused secrets path helper that was tripping latest-main prod type CI.
Fixes#87497.
Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
Fixes#87016.
Empty preflight compaction recovery now resets stale token snapshots immediately, preserves valid legacy transcript rows during cleanup, and avoids re-persisting stale context-budget or compaction metadata after a successful retry.
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Add read-only MCP visibility to `tools.effective` by projecting MCP tools only after a session catalog has already been warmed by an agent turn. Keep the gateway additive: no `tools.effective.refresh`, no forced MCP startup, and no behavior change for MCP loading.
Verification:
- `git diff --check origin/main..HEAD`
- `node scripts/run-vitest.mjs run --config test/vitest/vitest.agents.config.ts --reporter=verbose src/agents/tools-effective-inventory.test.ts`
- GitHub checks green on `a8a7f8442adb216f60da24d50118374a15c62e06`, including `Real behavior proof`, `check-guards`, `check-prod-types`, `check-test-types`, `build-artifacts`, `Critical Quality (gateway-runtime-boundary)`, and `Critical Quality (network-runtime-boundary)`.
Co-authored-by: David Huang <nxmxbbd@gmail.com>
The anthropic-transport-stream was overwriting thinkingSignature on each
signature_delta event instead of appending. Since Anthropic sends the
thinking block signature across multiple streaming chunks, only the last
chunk survived. The truncated signature was persisted to session JSONL,
causing all subsequent replay attempts to fail with HTTP 400:
thinking or redacted_thinking blocks in the latest assistant message
cannot be modified
This permanently bricked sessions with no user recovery path.
Fix: accumulate signature_delta values by concatenating instead of
overwriting, matching the correct implementation in the LLM provider
layer (src/llm/providers/anthropic.ts:629-634).
Includes real-scenario proof against live Anthropic API validating that
correct signatures replay successfully while truncated signatures are
rejected.
Fixes#87574
Refs #80625, #85781, #87475
* fix(agents): preserve reasoning_content replay across DeepSeek tier suffixes
OpenCode Zen exposes DeepSeek V4 as `deepseek-v4-flash-free`, which keeps the upstream DeepSeek thinking-mode contract that requires `reasoning_content` to be passed back on follow-up requests. The existing replay allowlist only matched the bare ids (`deepseek-v4-flash`, `kimi-k2-thinking`, ...), so the tier-suffixed id missed every candidate and the sanitizer stripped `reasoning_content` from the assistant turn. DeepSeek then rejected the second API call with HTTP 400 and the session deadlocked.
Strip the well-known tier suffixes (`-free`, `-paid`, `-trial`) when generating allowlist candidates so the base model id matches and the reasoning replay survives. Existing matching for prefixed / colon-suffixed routes is unchanged.
Fixes#87575
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(agents): avoid spread-rebuild when iterating allowlist candidates
oxlint flagged the [...candidates] spread as an unnecessary array copy. Use an explicit baseCount loop bound instead so we still iterate the original entries while pushing tier-stripped variants onto the same array.
Co-authored-by: Cursor <cursoragent@cursor.com>
* test(opencode): add live DeepSeek replay probe
* test(opencode): avoid forced tool choice in live replay
---------
Co-authored-by: Pluviobyte <Pluviobyte@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Fixes#58012.
Applies strict9 replay tool call id sanitization to OpenRouter Mistral-family model routes, including unprefixed Mistral/Codestral/Devstral aliases, while preserving existing passthrough behavior for Gemini and other OpenRouter-backed routes.
Adds focused unit coverage plus a live OpenRouter model catalog test so new Mistral-family routes are checked against the replay policy. Also keeps the current core lint gate green by switching the tool schema cache key sort to a non-mutating sorted array.
Co-authored-by: Pluviobyte <Pluviobyte@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve explicit gateway service identity when package/update refreshes the managed service environment. This keeps caller-selected systemd units ahead of stale persisted service env and applies the same precedence to launchd labels and Windows task names during service-state inspection.
Fixes#87490
Verification:
- node scripts/run-vitest.mjs src/daemon/service-env.test.ts src/daemon/service.test.ts src/cli/update-cli.test.ts src/cli/update-cli/restart-helper.test.ts src/cli/daemon-cli/install.test.ts src/daemon/systemd.test.ts
- git diff --check origin/main...pr/87556
- Crabbox AWS Linux systemd install/refresh proof: run_f3374bd610f7, lease cbx_754e69eb6c3a, provider aws, target linux
- autoreview --mode branch --base origin/main: clean, no accepted/actionable findings
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Summary:
- Replace the legacy iOS shell with Pro Command, Chat, Agents, and Settings tabs.
- Wire iOS chat/session/settings/diagnostics and realtime Talk flows through gateway-backed APIs.
- Add gateway/session and shared chat coverage for the new iOS flow.
Verification:
- git diff --check
- node scripts/run-vitest.mjs src/gateway/server.sessions.create.test.ts src/gateway/talk-realtime-relay.test.ts
- swift test --filter ChatViewModelTests (apps/shared/OpenClawKit)
- xcodebuild build for Nimrod's iPhone succeeded; install succeeded; launch was blocked because the phone was locked
Known follow-up:
- Preserve traceLevel in sessions.create parent runtime inheritance and keep the changelog credit in the follow-up patch.
Increase the code-mode wait-timeout test timeout so CI shard load does not trip the worker startup guard before the test reaches the intended pending-tool wait path.
Reduce repeated gateway warning noise in startup/auth retry paths while preserving credential mismatch and rate-limit audit visibility.
Also hardens empty embedded-assistant retry handling by carrying lifecycle state through the missing-assistant guard, and keeps the relevant regression coverage in gateway and agent tests.
Wire QA fallback models into live gateway config, fix Slack allowlist-block coverage, and keep WhatsApp live artifacts useful while redacting raw credential metadata.\n\nVerification: focused QA Vitest; autoreview clean; AWS Crabbox pnpm check:changed run_0207de7d47aa; QA-Lab branch-defined transport run 26565521272 with Matrix transport 56/56 and Slack/Discord/Telegram/parity clear. WhatsApp remains blocked by stale shared Convex WhatsApp Web credentials returning Baileys 401 before scenarios.
* fix(telegram): enable TCP keepalive on getUpdates connections to prevent NAT timeout stalls
Long-polling connections to api.telegram.org stay idle for up to the
getUpdates timeout (~900 s). Most home/office NAT tables expire idle TCP
entries after 60–1800 s (commonly ~1000 s). When the NAT entry is
silently dropped the connection hangs rather than returning an error,
leaving the grammY runner stuck until the 90 s stall watchdog fires and
forces a restart cycle.
Fix: unconditionally set `keepAlive: true` and
`keepAliveInitialDelay: 30_000` (30 s) on the undici Agent `connect`
options built in `buildTelegramConnectOptions`. OS-level TCP keepalive
probes sent every ~75 s (OS default) will:
1. Refresh the NAT table entry before it expires.
2. Surface dead connections immediately with ETIMEDOUT instead of
hanging forever.
The `return Object.keys(connect).length > 0 ? connect : null` guard is
also removed; `connect` is now always non-empty so it always returns the
object.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 92e454c0614256201cdf6f0f73c7897d006616d4)
* fix(telegram): stop self-flagging disconnected on poll-cycle start; widen channel connect grace to 300s
(cherry picked from commit 1ca963a05dac0d9d605e9a15dc97fced9cf7725e)
* fix(telegram): catch hung polling startups that preserve inherited connected:true
The widened 300s channel connect grace and the removal of connected:false from
notePollingStart left a path where a polling restart could hang forever
looking healthy. notePollingStart clears lastConnectedAt, lastEventAt, and
lastTransportActivityAt but deliberately omits connected, so server-channels'
patch-merge inherits a connected:true from the previous lifecycle. After grace,
evaluateChannelHealth's stale-socket branch requires lastTransportActivityAt
to be non-null and the connected:false branch is masked, so the channel sits
healthy with no first getUpdates.
Add a post-grace branch to evaluateChannelHealth that flags polling channels
as stale-socket when connected:true is paired with null lastConnectedAt and
null lastTransportActivityAt and a non-null lastStartAt. Scoped to mode:polling
so webhook channels and channels without continuous transport tracking are
not falsely flagged. Align TELEGRAM_POLLING_CONNECT_GRACE_MS in the Telegram
status diagnostic with DEFAULT_CHANNEL_CONNECT_GRACE_MS so openclaw channels
status agrees with the shared health monitor on the grace window. Refresh
the notePollingStart comment to point at the new evaluateChannelHealth branch.
Addresses clawsweeper review on #83304 (P1 connect-grace startup-hang, P2
diagnostic grace drift). Tests cover the new flagged path, the in-grace happy
path, and the prior-successful-connect happy path.
* fix(telegram): clear polling connected state on startup
* fix(gateway): add defense-in-depth health-policy branch for hung polling startups
Defense in depth on top of 87db46c576's notePollingStart connected:false fix.
The primary path (notePollingStart writes connected:false explicitly so
evaluateChannelHealth's existing connected===false branch catches a hung
restart) is unchanged. This adds a defensive post-grace branch that catches
the same hang via a different signature -- inherited connected:true paired
with null lastConnectedAt and null lastTransportActivityAt -- in case a
future code path forgets to clear the inherited connected flag on lifecycle
start. Scoped to mode:polling so webhook channels and channels without
continuous transport tracking are not falsely flagged.
Also bump lastStartAt: Date.now() - 121_000 to 301_000 in the spool-handler
timeout test added by upstream #83505 so it falls past the widened 300s
TELEGRAM_POLLING_CONNECT_GRACE_MS suppression window (mirroring the same
fixup already applied to the two adjacent polling-startup tests).
* revert(telegram,gateway): keep connect grace at 120s
Drop the 120s -> 300s widening from this PR after maintainer feedback that
the extra grace masks real startup bugs. The defense-in-depth checks added
in earlier commits (notePollingStart clearing inherited connected state,
the stale-socket policy branch, the per-snapshot startup grace test) all
work fine at 120s and remain valuable on their own.
Reverts in:
- src/gateway/channel-health-policy.ts: DEFAULT_CHANNEL_CONNECT_GRACE_MS 300 -> 120
- extensions/telegram/src/status-issues.ts: TELEGRAM_POLLING_CONNECT_GRACE_MS 300 -> 120
- extensions/telegram/src/status.test.ts: lastStartAt 301_000 -> 121_000 (3 cases)
The new channel-health-policy.test.ts cases use explicit channelConnectGraceMs:
10_000 in the policy, so they are unaffected by the default constant change.
* fix(telegram): narrow polling keepalive fix
---------
Co-authored-by: Yibei Ou <yibeiou@Yibeis-Mac-mini.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Harden QQBot direct media URL uploads by downloading through the local SSRF guard before QQ upload, disabling redirects, bounding fetch/setup and body reads, and routing downloaded buffers through the existing one-shot/chunked size gate.
Co-authored-by: Agustin Rivera <agustin@rivera-web.com>
Default `openclaw status --json` stays on the lean health-probe path while preserving the JSON task summary, local update/install metadata, explicit probe timeouts, and configured gateway handshake timeouts. Deeper memory, registry, remote git, and local status-RPC diagnostics remain behind `status --json --all`.
Also keeps generated diffs viewer output in its built form and ignores it in oxfmt so `pnpm build` leaves a clean tree.
Proof:
- `node scripts/run-vitest.mjs src/commands/status.scan.fast-json.test.ts src/commands/status-json-payload.test.ts src/commands/status.scan.shared.test.ts`
- `OPENCLAW_LOCAL_CHECK=0 node scripts/run-oxlint-shards.mjs --threads=8`
- `node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo`
- `node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main`
- GitHub checks green for head `47a63f87ea7c2351994fdb71e8cc18041aa0b64e`
Thanks @andyylin.
Co-authored-by: Andy <andyylin@users.noreply.github.com>
Forward canonical inbound media metadata to plugin message_received hooks so plugins can inspect the same mediaPath, mediaUrl, mediaType, mediaPaths, mediaUrls, and mediaTypes fields already available to inbound_claim.
Verification:
- node scripts/run-vitest.mjs src/hooks/message-hook-mappers.test.ts
- /Users/steipete/Projects/agent-scripts/skills/autoreview/scripts/autoreview --mode branch --base origin/main
Refs: https://github.com/openclaw/openclaw/pull/87297
Co-authored-by: WarrenJones <8704779+WarrenJones@users.noreply.github.com>
Stop heartbeat runs from directly returning non-ack durable pending final text. Heartbeats now only clear ack-only pending state and otherwise continue the heartbeat turn, so stale prior final answers cannot be replayed through a later heartbeat/default route.
Keep the isolated heartbeat active-run guard so an immediate/manual heartbeat cannot overwrite an isolated heartbeat session that is still running.
Proof:
- node scripts/run-vitest.mjs src/auto-reply/reply/get-reply.fast-path.test.ts src/infra/heartbeat-runner.skips-busy-session-lane.test.ts
- git diff --check
- autoreview --mode local
- autoreview --mode branch --base origin/main
- GitHub CI 26543804437, CodeQL 26543804438, Critical Quality 26543804441, OpenGrep PR Diff 26543804440 rerun job 78197443511, Real behavior proof 26544027357
Refs #74257.
Co-authored-by: kesslerio <martin@kessler.io>
Stabilize isolated cron prompt cache affinity by deriving a stable prompt cache key per cron job/session/model and forwarding it separately from the rotating run session id.
Thread the key through embedded runs, stream resolution, provider options, proxy forwarding, custom streams, and prompt-cache observability. Keep OpenAI-compatible payloads valid by using hyphen-safe keys, clamping upstream prompt_cache_key values, and omitting affinity when cache retention is disabled.
Thanks @ferminquant.
Co-authored-by: Fermin Quant <ferminquant@hotmail.com>
Rewrites non-canonical api_key fields in auth-profiles.json to canonical key via openclaw doctor --fix, with backups, while preserving canonical key/keyRef credentials and active-agent auth stores.
Fixes#57389.
Co-authored-by: alkor2000 <200923177@qq.com>
* fix(sessions): preserve Matrix room-id case in session keys (#75670)
Matrix room IDs (and thread event IDs) are opaque, case-sensitive per the
Matrix spec, but session-key canonicalization lowercased them. That forked
one room into duplicate sessions and produced 403 M_FORBIDDEN on recovery /
delivery paths that reconstruct the target from the (lowercased) session key,
even though deliveryContext.to stayed correct.
Introduce a generic, opt-in case-preservation registry (CASE_PRESERVING_PEERS)
consulted at all three lowercasing sites:
- construction: normalizeSessionPeerId
- store canonicalization: normalizeSessionKeyPreservingOpaquePeerIds
- gateway send: explicit request.sessionKey
Signal group preservation is encoded to match prior behavior exactly (segment
span, unscoped, thread suffix still lowercased). Matrix channel/group enrolls
the opaque tail (room id with embedded :server + any 🧵<event> suffix).
Exact mixed-case keys now win over folded legacy aliases in
resolveSessionStoreEntry and delivery-info lookup; existing lowercased rows
collapse on the next write. Matrix DM/MXID and non-enrolled channels keep the
default lowercase behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): guard Matrix folded alias delivery proof
* test(agents): cover cold OpenAI gpt-5.5 fallback
* fix(sessions): preserve non-opaque alias freshness
* fix(sessions): prevent Matrix cross-room thread recovery
* build(protocol): refresh tools effective Swift models
* test(codex): include effective cwd in startup fixture
* test(codex): align startup failure cleanup expectation
* fix(sessions): keep Signal folded aliases fresh
* fix(sessions): preserve unscoped Matrix room keys
* fix(sessions): recover legacy Matrix thread aliases
* fix(sessions): preserve Matrix keys in state migrations
* fix(sessions): keep Matrix structural alias freshness
* fix(sessions): preserve unscoped Matrix migration keys
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Fix iMessage native exec approval routing so approval prompts bind to the sent GUID without duplicate sends after RPC timeout. Also keeps chat.db GUID recovery on the local imsg path while avoiding local DB recovery for configured or detected SSH wrappers.
Thanks @kevinslin.
Avoid stale restart continuation reuse after a session key has rotated.
Queued restart agent turns now carry the session id they were queued for and fall back to a system wake if the key points at a different session by delivery time. Normal completed-run lifecycle fields stay reusable for fresh sessions, while new-session creation clears stale lifecycle markers.
Closes#86593.
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Closes#87210.
Gateway probe now waits for GatewayClient.stopAndWait() before resolving so callers do not observe a successful probe while the client socket is still draining. If the drain fails, probe falls back to stop().
Adds mocked probe coverage plus a real WebSocket regression test that verifies no client socket handle remains when probeGateway() resolves.
Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Show active subagent detail rows in /status with labels and elapsed runtime while keeping completed-subagent summary behavior. Thanks @simplyclever914.
Fixes#83935.
Summary:
- clear stale legacy openai-codex auto route pins only when the canonical OpenAI provider is still using the Codex harness for the same model
- preserve usable Codex auth profiles while clearing stale route state
- keep explicit/custom OpenAI API route pins intact
Verification:
- git diff --check
- pnpm exec oxfmt --check --threads=1 src/auto-reply/reply/model-selection.ts src/auto-reply/reply/model-selection.test.ts src/auto-reply/reply/agent-runner-execution.ts src/auto-reply/reply/agent-runner-execution.test.ts
- fnm exec --using 24.15.0 node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo
- .agents/skills/autoreview/scripts/autoreview --mode local
- CI: https://github.com/openclaw/openclaw/actions/runs/26542490863
Co-authored-by: Paul Frederiksen <paul@paulfrederiksen.com>
Fixes#87191. Keeps Brave and Gemini runtime-injected web search provider config readable by providers without re-exposing legacy tools.web.search provider objects to config validation.
Fix Slack draft cleanup after final-visible delivery.
Track when Slack has already delivered a visible final reply and stop reusing the draft finalizer for later same-turn final/error payloads. This keeps the first fallback cleanup for transient previews while preventing late cleanup from deleting a visible answer.
Fixes#87363
Co-authored-by: tianxiaochannel-oss88 <tianxiaochannel@gmail.com>
The compaction retry loop checked the delivery-timeout deadline before
choosing a fixed backoff delay, then slept that whole delay. When the
remaining window was shorter than the next backoff entry, the final
retry could sleep past the deadline, overrunning the delivery timeout
the retry is meant to stay within. Clamp the wait to the remaining
window (min(scheduledDelay, deadline - now)) and stop retrying once no
time remains, so compaction waiting never exceeds the delivery timeout.
Addresses the near-deadline overrun raised in ClawSweeper review of #86606.
Follow-up to #85489. Active requester steering treated a `compacting`
outcome from queueEmbeddedPiMessageWithOutcome as a terminal wake
failure and fell through to the requester-agent/direct fallback, even
though the active run becomes steerable again as soon as compaction
finishes.
Introduce a shared resolveActiveWakeWithRetries helper used by both the
steer path (maybeSteerSubagentAnnounce) and the generated-completion
active wake (sendSubagentAnnounceDirectly). The helper treats
`compacting` as transient and waits through compaction, retrying the
same wake. Waiting is bounded by the active wake's delivery timeout (not
just the backoff schedule): the backoff schedule controls the gap
between attempts, and once it is exhausted its last delay is reused until
the delivery deadline, so a compaction that finishes after the schedule
but within the delivery timeout still re-steers. The best-effort
transcript-commit retry and the compaction retry share one loop, so a
run that compacts and then reports transcript_commit_wait_unsupported
still gets the best-effort retry. Other wake failures keep their
existing single-attempt fallback.
Fixes#86566
Preserve pending agent-job error diagnostics as non-terminal timeout snapshots so the retry grace path can still recover when the lifecycle later starts and completes.
Local proof:
- node scripts/run-vitest.mjs packages/sdk/src/index.test.ts src/gateway/server-methods/server-methods.test.ts src/gateway/server.chat.gateway-server-chat.test.ts src/agents/run-wait.test.ts src/agents/openclaw-tools.sessions.test.ts
- node scripts/run-oxlint.mjs packages/sdk/src/client.ts packages/sdk/src/index.test.ts src/gateway/server-methods/agent-job.ts src/gateway/server-methods/agent.ts src/gateway/server-methods/agent-wait-dedupe.ts src/agents/run-wait.ts src/agents/tools/sessions-send-tool.ts src/gateway/server-methods/server-methods.test.ts src/gateway/server.chat.gateway-server-chat.test.ts src/agents/run-wait.test.ts src/agents/openclaw-tools.sessions.test.ts
- autoreview --mode local: no accepted/actionable findings
- CI run 26536599850: success
Co-authored-by: Martin Garramon <martin@yulicreative.ai>
Include second-level precision in inbound metadata and auto-reply envelope timestamps, matching the timestamp helper contract used by providers and channel adapters.
Docs now show the weekday plus seconds form in date-time and timezone examples.
Verification:
- node scripts/run-vitest.mjs src/auto-reply/envelope.test.ts src/auto-reply/reply/inbound-meta.test.ts
- pnpm docs:list >/tmp/openclaw-docs-list-87360.log
- git diff --check origin/main...HEAD
- pnpm format:docs:check
- pnpm lint:docs
- pnpm lint:extensions:bundled
- pnpm lint
- PR CI green on 495bb6c10fFixes#87257
Co-authored-by: GarlicGo <582149912@qq.com>
Expire browser-origin Control UI/WebChat device tokens when shared gateway auth rotates by tagging those tokens with the shared-auth generation and enforcing it during verification.
Preserve the issuer tag when a shared-auth-derived device token reconnects through a non-browser client, so reconnect rotation cannot turn it into an untagged long-lived token.
Proof:
- OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/gateway/server.shared-auth-rotation.test.ts src/infra/device-pairing.test.ts src/gateway/control-ui.http.test.ts
- GitHub CI run 26535632102: relevant build/runtime/test-type checks green; inherited lint reds match origin/main.
- GitHub CodeQL Critical Quality run 26535631610: network-runtime-boundary green.
Co-authored-by: Pavan Kumar Gondhi <pavangondhi@gmail.com>
Fixes repeated Tool Search catalog registration for unchanged effective tool sets by reusing a fingerprinted catalog snapshot across embedded-agent run cleanup.
The reusable catalog is guarded by catalog-affecting fields, parameters, and executable identity, and reuse now rebinds the current run/session refs before returning. Embedded-agent prep logging only suppresses the catalog line when reuse actually happened.
Verification:
- pnpm test src/agents/tool-search.test.ts -- --reporter=verbose
- pnpm check:changed, Testbox tbx_01ksney4f00wgk9n39yv7jsh4m
- Real behavior proof, GitHub Actions run 26534896284
- CI rerun for unrelated model-picker timeout passed, GitHub Actions run 26534489215
- autoreview clean: no accepted/actionable findings
Closes#86887
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Avoids a self-wait in embedded agent session event hooks by skipping the queue drain only for hooks running inside the current session event processing chain. Detached or external hook work still drains the queue before taking the session write lock.
Verification:
- node scripts/run-vitest.mjs run --config test/vitest/vitest.agents-embedded-agent.config.ts src/agents/embedded-agent-runner/run/attempt.session-lock.test.ts
- node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json src/agents/embedded-agent-runner/run/attempt.session-lock.test.ts src/agents/embedded-agent-runner/run/attempt.session-lock.ts --threads=8
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- GitHub CI: https://github.com/openclaw/openclaw/actions/runs/26533883763
Thanks @luoyanglang.
Co-authored-by: luoyanglang <hanwanlonga@gmail.com>
Make plugin-state enforce the plugin-wide live-row fuse by evicting only from the namespace currently being written, preserving sibling namespace rows and still failing atomically when the current namespace cannot free enough rows.
Raise the plugin-wide cap to 6,000 rows, keep Telegram's persistent message-cache namespace at 3,000 entries, and document the updated SDK runtime contract. Harden legacy plugin-state import so capacity pressure cannot archive a source after losing imported keys, with focused regression coverage for Telegram-shaped namespaces and migration rollback.
Also restore the Docker runtime-assets preflight step in full release validation so release workflow contract tests stay aligned.
Verification: focused plugin-state, migration, Telegram, workflow-contract, lint, deprecated-API, diff-check, Blacksmith Testbox, CI, CodeQL, Workflow Sanity, OpenGrep, and autoreview all passed on PR head fee021cfa6.
Co-authored-by: Keshav's Bot <keshavbotagent@gmail.com>
Use read-only Telegram account inspection for prompt-time channel actions, inline buttons, and reaction guidance so unresolved SecretRef tokens retain configured non-secret behavior before runtime snapshot hydration.
Match runtime Telegram account lookup for normalized config keys and multi-account fallback guards, while keeping sends/actions on the existing strict credential resolution path.
Fixes#75433.
Co-authored-by: Shubhankar Tripathy <reach2shubhankar@gmail.com>
Fixes #87331.\n\nPersist Codex native hook relay generations for real app-server resumes, keep a bounded legacy-binding grace path, and rotate generation on fresh-thread fallback so stale hook commands stay rejected.\n\nCo-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
Document that automation should pipe `models auth paste-token` credentials over stdin instead of passing token material in argv, keeping the existing secret-handling path explicit in the CLI docs.
Also include accepted auth-profile credential types in invalid-profile warning logs so malformed local auth stores are easier to repair.
Fixes#63042.
Thanks @liaoandi.
Clarify the Codex Computer Use docs around inferred opt-in, read-only status checks, and marketplace root versus marketplace JSON path setup.
The docs now match current source-backed behavior: autoInstall opts Computer Use in, status does not mutate plugin setup, and marketplacePath is for a local marketplace JSON file while source registers a marketplace root.
Verification:
- pnpm docs:list
- GitHub CI check-docs passed
- Real behavior proof passed via maintainer proof override for this docs-only PR
Thanks @bdjben.
Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
Co-authored-by: Sally O'Malley <somalley@redhat.com>
Split the diffs viewer Shiki language pack into an external publishable plugin.
The diffs plugin keeps the default curated syntax set, while the new @openclaw/diffs-language-pack package carries the extended Shiki languages for npm and ClawHub distribution. The install metadata includes the external ClawHub spec, and the curated C# alias set keeps both c# and cs supported without the language pack.
Co-authored-by: Dallin Romney <dallinromney@gmail.com>
Fix non-interactive and wizard onboarding reruns so existing agent lists and bindings are preserved unless the user explicitly resets config.
Isolate legacy `plugins.installs` migration into its own write so the config size-drop allowance cannot mask unrelated config loss, while preserving new or repaired install records for the final plugin-index commit. Also keep shrinkwrap generation pinned to pnpm-locked transitive patch versions only when the dependency edge still allows that version, and isolate the tooling Vitest shard that mutates process state.
Fixes#84692.
Replaces #84748.
Co-authored-by: yetval <yetvald@gmail.com>
Use this only when the patch is actually unstaged/staged/untracked in the
current checkout. For committed, pushed, or PR work, point the helper at the commit
or branch diff instead; do not force `--mode local` / `--uncommitted` just
current checkout. `--mode uncommitted` is accepted as an alias for `--mode local`.
For committed, pushed, or PR work, point the helper at the commit
or branch diff instead; do not force dirty modes just
because the helper docs mention dirty work first. A clean local review
only proves there is no local patch.
@@ -164,6 +165,7 @@ If installed from `agent-scripts`, path is:
The helper:
- chooses dirty local changes first
- accepts `--mode uncommitted` as an alias for `--mode local`
- otherwise uses current PR base if `gh pr view` works
- otherwise uses `origin/main` for non-main branches
- supports `--engine codex`, `claude`, `droid`, and `copilot`; default is `AUTOREVIEW_ENGINE` or `codex`; Codex should remain the default when nothing is set
@@ -98,7 +98,7 @@ Do not close from title alone. If closing as done on main or nonsensical, prove
When asked for `5 new`, exclude refs already surfaced in the session and refill from the archive until there are 5 live-open candidates. If fewer than 5 remain open, list all open ones and say how many short.
When asked to `update`, `refresh`, `recheck`, `check again`, or similar, return an updated live-open candidate list. Do not fill the main list with items that merely merged/closed since the last pass; put those numbers in a short bottom line.
When asked to `update`, `refresh`, `recheck`, `check again`, or similar, return an updated live-open candidate list. Sort by maintainer importance, not recency: high-impact ready fixes first, then useful-but-review-first, then open/not-ready items. Do not include a "changed since last pass" section or bottom-line merged/closed summary unless the user explicitly asks for churn.
Prefer:
@@ -142,18 +142,20 @@ No Markdown tables. Compact bullets. Use color/risk markers:
Required line shape:
```markdown
- **PR #81244** `@whatsskill.``+118/-1``bug` 🟢 verifiable: yes. This prevents chat action buttons from overlapping short assistant replies. Blast: web chat rendering, low.
- **Issue #81245** `@alice``LOC n/a``bug` 🟡 verifiable: partial. This reports duplicate Telegram replies when reconnecting after gateway restart. Blast: Telegram channel runtime, medium.
- **PR #81244** `@whatsskill.``+118/-1``bug` 🟢 https://github.com/openclaw/openclaw/pull/81244 - Prevents chat action buttons from overlapping short assistant replies. Verifiable: yes. Blast: web chat rendering, low.
- Always include `verifiable: yes|partial|no` plus the shortest proof hint when helpful.
- If status is not open, still show it only when the user asked for all surfaced refs; use ✅ or ⚪ and state merged/closed.
- For refresh-style asks, bottom line: `Merged/closed since last pass: #81016 merged, #81026 closed.` Omit if none.
- For refresh-style asks, prefer section order: `Best Open Now`, `Useful But Review First`, `Still Open / Not Ready`. Omit merged/closed churn by default.
DISCRAWL_NO_AUTO_UPDATE=1 discrawl --json sql "select count(*) from messages;"
```
Report absolute date spans, channel/DM names, counts, and known gaps. Use read-only SQL for exact counts/rankings. Never use `--unsafe --confirm` unless the user explicitly requests a reviewed DB mutation.
## SQL
Boundaries: bot sync needs configured Discord bot credentials. Wiretap reads local Discord Desktop artifacts only; do not extract user tokens, call Discord as the user, or write to Discord storage. Git-share snapshots must not include secrets or `@me` DM rows.
Use `discrawl sql` for exact counts, joins, and ranking queries when normal
CLI reads are too coarse. The command is read-only by default, accepts SQL as
args or stdin, and supports `--json` for agent parsing.
Useful examples:
```bash
DISCRAWL_NO_AUTO_UPDATE=1 discrawl --json sql "select count(*) as messages from messages;"
DISCRAWL_NO_AUTO_UPDATE=1 discrawl --json sql "select coalesce(nullif(c.name, ''), m.channel_id) as channel, count(*) as messages from messages m left join channels c on c.id = m.channel_id group by m.channel_id order by messages desc limit 20;"
DISCRAWL_NO_AUTO_UPDATE=1 discrawl --json sql "select coalesce(nullif(mm.display_name, ''), nullif(mm.global_name, ''), nullif(mm.username, ''), m.author_id) as author, count(*) as messages from messages m left join members mm on mm.guild_id = m.guild_id and mm.user_id = m.author_id group by m.guild_id, m.author_id order by messages desc limit 20;"
```
Never use `--unsafe --confirm` unless the user explicitly asks for a database
mutation and the write has been reviewed.
When the installed CLI lacks a new feature, build or run from a verified
`openclaw/discrawl` checkout before concluding the feature is missing.
## Discord Boundaries
Bot API sync requires configured Discord bot credentials; do not invent token
availability. Desktop wiretap mode reads local Discord Desktop artifacts and
must not extract credentials, use user tokens, call Discord as the user, or
write to Discord application storage. Wiretap/Desktop cache DMs are local-only
and must not be described as part of the published Git snapshot. Git-share
snapshots must not include secrets or `@me` DM rows.
## Verification
For repo edits, prefer existing Go gates:
```bash
GOWORK=off go test ./...
```
Then run targeted CLI smoke for the touched surface, for example:
- Publishing fails with HTTP 422 if required fields are missing or the private fork still has open PRs.
- A payload that looks correct in shell can still be wrong if Markdown was assembled with escaped newline strings.
- Advisory PATCH sequencing matters; separate field updates when GHSA API constraints require it.
- Public hardening/no-publish comments and draft text should avoid raw commit hashes, PR titles/numbers, and fix-mechanism summaries. Prefer patched-version fields or release-only wording; keep SHAs, PRs, and implementation notes in internal evidence.
description: "Draft or post OpenClaw beta/stable Discord release announcements from changelog, GitHub release, registry, and validation evidence. Use when announcing a beta, stable release, release candidate, or asking what users should test after an OpenClaw release."
---
# OpenClaw Release Announcement
Use with `release-openclaw-maintainer` after a beta or stable release is live.
Use with `openclaw-discord` when actually posting to Discord.
## Evidence First
Before drafting focus areas, read real release evidence:
1. Current GitHub release body for the tag.
2.`CHANGELOG.md` section for the released base version.
3. Commits since the previous shipped version or the operator-specified base.
4. Registry/package metadata for the exact version and current dist-tag.
5. Validation status that is relevant to user confidence.
Do not claim a full changelog audit unless you did it. If you only read the
generated release notes or top changelog section, say that and either audit
properly or draft with that limitation.
For beta focus areas, prioritize user-observable changes over internal test or
CI mechanics:
- install/update paths
- OS/platform-specific behavior
- Gateway startup/restart, config, and runtime behavior
- provider/model/runtime routing
- plugin loading and local plugin development
- channels and media paths
- security/data-loss/user-impact fixes
Do not let late release-branch fixes automatically dominate the announcement.
If the version includes a large delta from the previous shipped version, rank
focus areas by the whole release delta and expected user impact; mention late
fixes in their natural category.
## Required Copy
Every beta announcement must make beta status explicit and include:
- exact version, e.g. `OpenClaw 2026.5.25-beta.1`
- one-sentence risk framing: beta, useful for testing, not stable promotion
- focused test areas derived from evidence, not guesswork
- update command promoted near the top:
```sh
openclaw update --channel beta --yes
openclaw --version
```
- fresh install path:
`Install from https://openclaw.ai`
- GitHub release link
- concise validation note, without making CI the headline
Do not suggest npm install commands in beta announcements unless the operator
explicitly asks for npm-specific copy or troubleshooting text. It is fine to use
registry metadata as evidence; do not turn that into public install guidance.
For stable announcements, use the stable channel wording:
```sh
openclaw update --channel stable --yes
openclaw --version
```
Fresh installs still point to `https://openclaw.ai`.
## Style
- Discord Markdown, no tables.
- Keep it skimmable: short intro, bullets, commands, links.
- Lead with what users can feel or test, not proof plumbing.
- Mention validation only after install/update instructions.
- Be specific about where feedback is useful.
- Do not mention private local proof paths in public announcements.
- Do not overstate unverified platforms, channels, or provider behavior.
## Posting
When asked to post, use the configured Discord workflow from
`openclaw-discord` or the approved OpenClaw relay. Never print tokens.
For public channels, inspect the final body before sending.
short_description:"Draft Discord beta/stable release announcements from evidence."
default_prompt:"Use this skill to draft an OpenClaw beta or stable Discord announcement from changelog, release notes, npm/GitHub release proof, and validation evidence."
description: Triage OpenClaw security advisories, drafts, and GHSA reports with shipped-tag and trust-model proof.
description: "Triage OpenClaw security advisories, drafts, and GHSA reports with shipped-tag and trust-model proof."
---
# Security Triage
@@ -87,11 +87,19 @@ When preparing a maintainer-ready close reply:
- exact reason for close
- exact code refs
- exact shipped tag / release facts
-exact fix commit or canonical duplicate GHSA when applicable
-fix provenance or canonical duplicate GHSA when applicable
- optional hardening note only if worthwhile and functionality-preserving
Keep tone firm, specific, non-defensive.
## Public Wording Hygiene
- Keep raw commit hashes, PR titles/numbers, and fix-mechanism summaries out of public advisory text. Use the patched release/version field only.
- Keep exact commit SHAs, PRs, and implementation notes in internal notes and verification files.
- For hardening/no-publish outcomes, do not add exploit-heavy details, "Fixed by" text, or a "Fix Commit(s)" section. Thank reporters, preserve credit, state the `SECURITY.md` boundary, and say clearly that the GHSA will close without publication.
- For published CVE/GHSA text, prefer `### Patched Versions` with the fixed release. Do not explain how the patch works unless Peter explicitly asks for that public detail.
- Keep GHSA ids out of changelog and release-note wording unless Peter explicitly asks.
## Discussion Mode
When Peter is manually posting GHSA comments, use this flow:
Do not speculate or infer beyond the evidence. If a narrative section cannot be answered from the available evidence, respond with exactly `NOT_ENOUGH_INFO`.
If this is a plugin beta-release blocker, rename the issue title to `Beta blocker: <plugin-name> - <summary>` and apply the `beta-blocker` label after filing.
Please only report one issue per submission. Break multiple issues up into separate submissions.
echo "It does not sign, notarize, or upload macOS assets."
echo
echo "Next step:"
echo "- Run \`openclaw/releases-private/.github/workflows/openclaw-macos-validate.yml\` with tag \`${RELEASE_TAG}\` and wait for the private mac validation lane to pass."
echo "- Run \`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml\` with tag \`${RELEASE_TAG}\` and \`preflight_only=true\` for the full private mac preflight."
echo "- For the real publish path, run the same private mac publish workflow from \`main\` with the successful private preflight \`preflight_run_id\` so it promotes the prepared artifacts instead of rebuilding them."
echo "- For stable releases, the private publish workflow also publishes the signed \`appcast.xml\` to public \`main\`, or opens an appcast PR if direct push is blocked."
echo "- Run \`openclaw/releases/.github/workflows/openclaw-macos-validate.yml\` with tag \`${RELEASE_TAG}\` and wait for the macOS validation lane to pass."
echo "- Run \`openclaw/releases/.github/workflows/openclaw-macos-publish.yml\` with tag \`${RELEASE_TAG}\` and \`preflight_only=true\` for the full macOS preflight."
echo "- For the real publish path, run the same macOS publish workflow from \`main\` with the successful preflight \`preflight_run_id\` so it promotes the prepared artifacts instead of rebuilding them."
echo "- For stable releases, the publish workflow also publishes the signed \`appcast.xml\` to public \`main\`, or opens an appcast PR if direct push is blocked."
@@ -57,6 +57,7 @@ Skills own workflows; root owns hard policy and routing.
- External official plugins own package/deps and are excluded from core dist; core uses registry-aware `facade-runtime` or generic contracts.
- Externalizing a bundled plugin: update package excludes, official catalogs, docs, tests, and prove core runtime paths resolve installed plugin roots before root-dep removal.
- Runtime reads canonical config only. No silent compat for old/malformed config keys. If a config change invalidates existing files, add a matching `openclaw doctor --fix` migration. Core/auth config repairs live in core doctor; plugin-owned config repairs live in that plugin's doctor contract (`legacyConfigRules` / `normalizeCompatibilityConfig`).
- CLI setup flows are public API when external docs, installers, or integrations can copy them. Changes to `openclaw onboard`, `openclaw configure`, their documented flags, non-interactive behavior, or generated config shape are compatibility-sensitive API contract changes; prefer additive flags/aliases, deprecation windows, and backward-preserving migrations over breaking existing snippets.
- Fix shape: default to clean bounded refactor, not smallest patch. Move ownership to right boundary; delete stale abstractions, duplicate policy, dead branches, wrappers, fallback stacks.
- Fix observed local failures with generic product rules; do not hardcode names, ids, log phrases, or user examples in prod code unless they are an explicit contract.
- Tests may use observed examples, but prod literals need a short contract reason.
@@ -71,6 +72,7 @@ Skills own workflows; root owns hard policy and routing.
- Plugin SDK exception: shipped external API gets new API first plus named compat/deprecation, small tests/docs if useful, removal plan.
- Migrate internal/bundled callers to modern API in the same change. Do not let internal compat become permanent architecture.
- Channels are implementation under `src/channels/**`; plugin authors get SDK seams. Providers own auth/catalog/runtime hooks; core owns generic loop.
- Agent run terminal state: normalize/merge via `src/agents/agent-run-terminal-outcome.ts`; do not rederive timeout/cancel precedence in projections.
- Hot paths should carry prepared facts forward: provider id, model ref, channel id, target, capability family, attachment class. Do not rediscover with broad plugin/provider/channel/capability loaders.
- Do not fix repeated request-time discovery with scattered caches. Move the canonical fact earlier; reuse prepared runtime objects; delete duplicate lookup branches.
- Gateway/plugin metadata is process-stable: installs, manifests, catalogs, generated paths, bundled metadata. Changes require restart or explicit owner reload/install/doctor flow.
@@ -211,6 +213,7 @@ Skills own workflows; root owns hard policy and routing.
- Lockfiles/shrinkwrap are security surface: review `pnpm-lock.yaml`, `npm-shrinkwrap.json`, `package-lock.json`; root/plugin npm packages ship shrinkwrap, not package-lock.
- Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
- Releases/publish/version bumps need explicit approval. Use `$release-openclaw-maintainer`.
- Backport means apply to newest open `release/` branch unless user names another target.
- Crabbox/WebVNC human demos: keep remote desktop visible/windowed; no fullscreen remote browser unless video/capture-style output.
- ClawSweeper ops: `$clawsweeper`. Deployed hook sessions may post one concise `#clawsweeper` note only when surprising/actionable/risky; if using message tool, reply exactly `NO_REPLY`.
- Generated-media completions wake the requester agent first. Requester visible-reply config decides final text vs message tool; direct media send is fallback/recovery only.
- Memory wiki prompt digest stays tiny; prefer `wiki_search` / `wiki_get`; verify contact data before use; source-class provenance for generated people facts.
- Rebrand/migration/config warnings: run `openclaw doctor`.
- Memory: add a core OpenAI-compatible embedding provider for local and hosted OpenAI-style endpoints, with config, doctor, and docs support. (#85269) Thanks @dutifulbob.
- Plugin SDK: mark memory-specific embedding provider registration as deprecated compatibility and surface non-bundled usage in plugin compatibility diagnostics. (#85072) Thanks @mbelinky.
- Plugins: externalize Tokenjuice as the official `@openclaw/tokenjuice` plugin with npm and ClawHub publish metadata.
- Plugins: externalize the GitHub Copilot agent runtime as the official `@openclaw/copilot` plugin with npm and ClawHub publish metadata.
- Plugins: make PixVerse external-plugin ClawHub metadata explicit and keep it out of bundled dist builds.
- Providers: bound generated media downloads from OpenAI, Runway, xAI, MiniMax, BytePlus, DashScope-compatible, FAL, OpenRouter, Google, Vydra, and Comfy providers.
- Providers: cap GitHub Copilot OAuth request timeouts before creating abort signals.
- Cron: retry recurring jobs after transient model rate limits before waiting for the next scheduled slot.
## 2026.5.28
### Highlights
- Agent and Codex runtime recovery is steadier: subagents keep cwd/workspace separation, hook context stays prompt-local, session locks release on timeout abort, stale restart continuations are avoided, and Codex app-server/helper failures no longer tear down shared runtime state. (#87218, #86875, #87409, #87399, #87375)
- Channel delivery and session identity got safer across outbound plugin hooks, Matrix room ids, iMessage reactions/approvals, Slack final replies, Discord recovered tool warnings, and Microsoft Teams service URL trust checks. (#73706, #75670, #87366, #87451, #87334)
- Mobile and chat surfaces got a broader refresh: the iOS Pro UI, Gateway chat transport, onboarding, Talk permissions, WebChat reconnect delivery, and session picker behavior now preserve more state across reconnects and empty searches. (#87367, #87531, #87682)
- CLI, auth, doctor, and provider paths fail faster and recover more clearly: malformed numeric/version options are rejected, OAuth and local service startup requests are bounded, legacy `api_key` auth profiles migrate to canonical form, and restart guidance is actionable. (#87398, #86281, #87361)
- Plugin and Gateway hot paths do less repeated work while preserving cache correctness for install records, config JSON parsing, tool search catalogs, session stores, manifest model rows, auto-enabled plugin config, browser tokens, and viewer assets. (#86699)
- Release, QA, and E2E validation now bound more log, artifact, harness, and cross-OS waits so failing lanes produce proof instead of hanging or false-greening.
### Changes
- Status: show active subagent details in status output.
- Diffs: split the default language pack and expand default Diffs language coverage while keeping the host floor aligned. (#87370, #87372) Thanks @RomneyDa.
- ClawHub: add plugin display names plus skill verification and trust surfaces. (#87354, #86699) Thanks @thewilloftheshadow and @Patrick-Erichsen.
- iOS: refresh the dev app with Pro Command, Chat, Agents, and Settings tabs wired to gateway sessions, diagnostics, chat, and realtime Talk. (#87367) Thanks @Solvely-Colin.
- PDF/tools: use ClawPDF for PDF extraction and surface MCP structured content in agent tool results. (#87670)
### Fixes
- Agents: fall back to local config pruning when the optional `agents delete` Gateway probe cannot authenticate, so offline installs can still delete agents without removing shared workspaces.
- Agents/Codex: keep spawned agent cwd/workspace state separated, keep hook context prompt-local, release session locks on timeout abort, avoid session event queue self-wait, preserve shared app-server state across startup or helper failures, keep native hook relay alive across restarts, route workspace memory through tools, resolve Codex runtime models first, report quarantined dynamic tools, format `skills` command output, and bound compaction/steering retries. (#87218, #86875, #86123, #87399, #87375, #87383, #87400) Thanks @mbelinky, @Alix-007, @luoyanglang, @yetval, and @sjf.
- Codex Supervisor: keep real-home app-server MCP session listing on the loaded/state-DB path, bound stored history scans, and close WebSocket probes cleanly.
- Channels: thread canonical session keys into outbound hooks, preserve Matrix room-id case, keep fallback tool warnings mention-inert, retain delivered Slack final replies during late cleanup, continue iMessage polling after denied reactions, suppress duplicate native exec approvals, preserve Telegram SecretRef prompt config, suppress Discord recovered tool warnings, and block untrusted Teams service URLs. (#73706, #75670, #87366, #87451, #87334) Thanks @zeroaltitude, @lukeboyett, @xiaotian, and @eleqtrizit.
- CLI/auth/doctor/providers: reject malformed numeric/timeout/subcommand-version inputs, wait for respawn child shutdown, bound Codex and GitHub Copilot OAuth/token requests, warm provider auth off the main thread, honor Codex response timeouts, bound local service startup, resolve GPT-5.5 without cached catalog, migrate legacy memory auto-provider config, rewrite non-canonical `api_key` auth profiles, and make doctor restart follow-ups actionable. (#87398, #86281, #87361) Thanks @Patrick-Erichsen, @samzong, @giodl73-repo, and @alkor2000.
- Gateway/security/session state: expire browser tokens after auth rotation, scope assistant idempotency dedupe, drain probe client closes, avoid stale restart continuation reuse, preserve retry-after fallbacks, bound webchat image and artifact transcript scans, include seconds in inbound metadata timestamps, and evict current plugin-state namespaces at row caps.
- Config/parsing/network: reject partial numeric parsing, parse provider/Discord retry headers and dates strictly, honor IPv6 and bare IPv6 `no_proxy` entries, canonicalize secret target array indexes, and reject malformed media content lengths, inspected TCP ports, marketplace content lengths, cron epochs, and sandbox stat fields.
- File transfer: handle late tar stdin pipe errors after archive validation or unpacking has already settled.
- Performance: trust install-record caches between reloads, prefer native JSON parsing, reuse unchanged tool-search catalogs, skip unchanged store serialization, add precomputed session patch writers, reduce store clone allocations, cache manifest model catalog rows and auto-enabled plugin config, and slim current metadata identity caches.
- Docker/release/QA: package runtime workspace templates, stream cross-OS served artifacts, preserve sparse Crabbox run artifacts, bound OpenClaw instance logs, plugin gauntlet relay logs, MCP channel buffers, kitchen-sink scans, agent-turn assertions, and release scenario logs, and keep release/google live guards current.
## 2026.5.27
### Highlights
- Safer local/runtime boundaries: OpenClaw now rejects unsafe command wrappers, malformed CLI numeric options, unsafe Node runtime env overrides, no-auth Tailscale exposure, and non-admin device-role pairing approvals before they can affect live runs. (#87308, #87305, #87292, #87146)
- Matrix and auto-reply delivery are steadier: mention previews stay inert, final mention replies deliver normally, shared-DM notices are awaited, MXID parsing ignores filenames, and reasoning-prefixed `NO_REPLY` responses stay suppressed.
- Provider and agent reliability improved across OpenAI-compatible embeddings, cached token usage, Anthropic/Codex/Claude runtime state, unsupported tool-schema quarantine, heartbeat templates, and session fallback errors. (#85269, #82062, #85416, #86855)
- Plugin and package release paths got tighter: Pixverse ships as an external video plugin with region selection, package exclusions and shrinkwrap inventory match the published npm shape, and release/package smoke commands fail bounded instead of hanging.
- Gateway hot paths do less rediscovery by reusing current plugin metadata fingerprints, stable plugin index fingerprints, read-only session metadata, active working stores, status fast paths, and auth/env snapshots. (#86439)
### Changes
- Memory: add a core OpenAI-compatible embedding provider for local and hosted OpenAI-style endpoints, with config, doctor, and docs support. (#85269) Thanks @dutifulbob.
- Plugin SDK: mark memory-specific embedding provider registration as deprecated compatibility and surface non-bundled usage in plugin compatibility diagnostics. (#85072) Thanks @mbelinky.
- Pixverse: add video generation provider support, API region selection, and external plugin publishing.
- Plugins: expose approval action metadata for plugin-driven approval surfaces.
- Doctor: validate runtime tool schemas for every configured embedded agent while skipping ACP-only profiles, so bad non-default plugin or MCP tools are reported before assistant turns.
- Telegram: route `sendMessage` action replies through durable outbound delivery so completed agent responses remain retryable when the gateway send path times out. (#87261) Thanks @mbelinky.
- Gateway/security: require `operator.admin` for node and other non-operator device-role pairing approvals, including trusted-proxy sessions, while keeping pairing-only approvals available for operator-role requests. (#87146)
- Agents/providers: add OpenAI-compatible cache retention, forward cached token usage in chat completions, preserve runtime context before active user turns, strip stale Anthropic thinking, load Claude CLI OAuth for Pi auth profiles, avoid false Codex runtime live switches, and quarantine unsupported tool schemas. (#82062, #87167, #86855)
- Gateway/performance: cache plugin metadata fingerprints and stable plugin index fingerprints, borrow read-only session metadata safely, keep the active session working store hot, keep status on a bounded fast path, and preserve model auth profile suffixes. (#86439)
- Package/install/release: align npm package exclusions and inventory, omit unpacked test helpers, skip Homebrew until macOS packages need it, cap tsdown heap in containers, bound install/release smoke waits, and harden post-publish verification.
- Codex/Auth: bound ChatGPT OAuth token exchange and refresh requests, and honor cancellation across Codex and Anthropic OAuth login flows.
- QA/E2E/CI: bound Telegram, kitchen-sink, Open WebUI, ClawHub, MCP, Discord, realtime, labeler, and GitHub API waits; fail empty explicit test, live-media, gateway CPU, startup benchmark, plugin gauntlet, and beta-smoke runs instead of false-greening.
- Agents/Codex: keep spawned agent bootstrap files rooted in the agent workspace while running task commands, transcripts, and compaction from the requested cwd. (#87218) Thanks @mbelinky.
## 2026.5.26
@@ -49,7 +114,7 @@ Docs: https://docs.openclaw.ai
- Voice: share activation-name matching and consult-transcript screening through the realtime voice SDK so Discord, browser voice, and meeting surfaces can reuse one implementation.
- Cron: default `cron.maxConcurrentRuns` to 8 so scheduled automations and their isolated agent turns can make progress in parallel without explicit configuration.
- QA-Lab: add `qa coverage --match <query>` so focused proof selection can discover matching scenarios from existing metadata before running live or remote lanes.
- Discord/model picker: surface an alpha-bucket select (e.g. `A–G (12) · H–N (18) · O–Z (5)`) when the provider list or a provider's model list exceeds 25 items, so configs with `provider/*` wildcards stay one click from the right page instead of paginating through prev/next; falls back to numeric chunks when every item shares the same first letter.
- Discord/model picker: surface an alpha-bucket select (e.g. `A–G (12) · H–N (18) · O–Z (5)`) when the provider list or a provider's model list exceeds 25 items, so configs with `provider/*` wildcards stay one click from the right page instead of paginating through prev/next; falls back to numeric chunks when every item shares the same first letter. (#86181) Thanks @rendrag-git.
- Control UI: add an ephemeral Activity tab for sanitized live tool activity summaries without persisting raw telemetry. Fixes #12831. Thanks @BunsDev.
- Build: include `ui:build` in the `full` and `ciArtifacts` profiles of `scripts/build-all.mjs` so `pnpm build` always rebuilds `dist/control-ui` after `tsdown` cleans `dist`, removing the second-command requirement and the missing-asset failure mode for source/runtime installs and CI artifact uploads. (#85206)
- iOS: improve Talk mode with direct realtime voice sessions, compact toolbar status, and responsive voice waveform feedback. (#86355) Thanks @ngutman.
- Maintainer skills: add `openclaw-landable-bug-sweep` for producing five small, reviewed, CI-green OpenClaw bugfix PRs from issue/PR sweeps.
- Control UI/chat: add search and Load More pagination to the chat session picker, keeping initial session loads bounded while making older conversations reachable. (#85237) Thanks @amknight.
- CLI/onboarding: start classic onboarding when bare `openclaw` runs before an authored config exists, while keeping configured installs on Crestodian. (#72343) Thanks @fuller-stack-dev.
- Agents/runtime: internalize the former Pi agent runtime into OpenClaw, remove legacy package dependencies, and keep Pi-named SDK aliases only as deprecated plugin compatibility.
- Discord: allow configuring a bounded `agentComponents.ttlMs` callback registry lifetime for long-running component workflows, with per-account overrides and a 24-hour cap. (#84189) Thanks @100menotu001.
- xAI/Grok: reuse xAI OAuth auth profiles for Grok `web_search`, thread active-agent auth through web search, add Grok model aliases, and let media providers declare default operation timeouts. (#85182) Thanks @fuller-stack-dev.
- Plugin SDK: add row-level session workflow helpers and deprecate `loadSessionStore` so plugins can read and patch sessions without depending on the legacy whole-store shape. (#84693) Thanks @efpiva.
<li>Stronger security and content boundaries: group prompt text is kept out of the system prompt, repeated-dot hostnames are normalized, side-effecting command wrappers and unsafe Node runtime env overrides are blocked, no-auth Tailscale exposure is rejected, and node/device-role approvals now require admin authority. (#87144, #87305, #87292, #87308, #87146) Thanks @eleqtrizit and @pgondhi987.</li>
<li>More reliable Codex app-server runs: Codex runtime models resolve first, workspace memory is routed through tools, shared app-server clients survive startup and spawned-helper failures, native hook relay generations survive restarts and rotate on fresh fallbacks, and false runtime live switches are avoided. (#87383, #87403, #87375, #72574, #87428) Thanks @yetval.</li>
<li>Faster Gateway and reply paths: session reads, plugin metadata fingerprints, auth env snapshots, auto-enabled plugin config, tool-search catalogs, and stable metadata caches do less hot-path rediscovery while visible replies no longer inherit hidden cleanup timeouts. (#86439, #87044) Thanks @keshavbotagent.</li>
<li>Better provider and model coverage: OpenAI-compatible embedding providers are core, DeepInfra catalog browsing loads the full credential-aware model set, Pixverse adds video generation and API region selection, VLLM thinking params are wired, Claude CLI OAuth overlays load for PI auth profiles, and bare direct Anthropic model ids work. (#85269, #84549, #87167) Thanks @dutifulbob, @ats3v, and @joshavant.</li>
<li>Channel delivery is steadier: Telegram <code>sendMessage</code> actions use durable outbound delivery, iMessage suppresses duplicate native exec approval prompts and sends, Slack keeps delivered final replies during late cleanup, Matrix mention previews/finals are stricter, QQBot fallback approval buttons honor slash-command auth, Discord guild requester checks are tighter, recovered Discord tool-warning artifacts stay out of successful replies, and Google Chat stops thread sends in DMs. (#87261, #87154) Thanks @mbelinky and @eleqtrizit.</li>
<li>Release, package, and CI proof paths are harder to wedge: npm/package inventory honors dist exclusions, shrinkwrap override pins merge correctly, Docker runtime workspace templates are packaged and smoked, release postpublish checks are stricter, beta smoke rejects empty runs, and E2E log/probe waits are bounded.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Memory: add a core OpenAI-compatible embedding provider for local and hosted OpenAI-style endpoints, with config, doctor, and docs support. (#85269) Thanks @dutifulbob.</li>
<li>Plugin SDK: mark memory-specific embedding provider registration as deprecated compatibility and surface non-bundled usage in plugin compatibility diagnostics. (#85072) Thanks @mbelinky.</li>
<li>Providers: add the Pixverse video generation provider, API region selection, docs, and external plugin packaging support.</li>
<li>DeepInfra: load the full model catalog when users browse models during onboarding, preserve configured API-key catalogs, refresh media/video defaults, and keep pricing/default model metadata aligned. (#84549) Thanks @ats3v.</li>
<li>Plugin SDK: expose plugin approval action metadata and stop exporting Vitest test helpers from the public SDK surface. (#87120) Thanks @RomneyDa.</li>
<li>Channel SDK: move channel message compatibility into core, remove old channel turn runtime aliases, and preserve runtime catalog markdown metadata for plugins.</li>
<li>ClawHub: add plugin display metadata so catalog/package listings use cleaner names. (#87354) Thanks @thewilloftheshadow.</li>
<li>Agents: split the heartbeat runtime template out of docs assets and add compatibility repair for legacy heartbeat template content. (#85416) Thanks @hxy91819.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security/content boundaries: route untrusted group prompt metadata outside system prompts, normalize repeated trailing hostname dots, block side-effecting command wrappers, reject unsafe Node runtime env overrides, reject no-auth Tailscale exposure, block untrusted Microsoft Teams service URLs, enforce <code>/allowlist configWrites</code> origin policy, gate QQBot fallback approval buttons, and require admin for node/device-role approvals. (#87144, #87305, #87292, #87308, #87146, #87154, #87334) Thanks @eleqtrizit and @pgondhi987.</li>
<li>Codex: resolve Codex runtime models before generic routing, route workspace memory through tools, preserve shared app-server clients after startup and spawned-helper failures, preserve native hook relay generations across restarts and fresh fallbacks, keep raw reasoning/source-reply guards intact, report quarantined dynamic tools, keep the attempt watchdog armed for queued terminal turns, and route Codex OAuth compaction through OpenAI-Codex. (#87383, #87403, #87375, #72574, #87428) Thanks @yetval.</li>
<li>Agents/runtime: avoid session event queue self-waits, bound compaction wake and steering retries, preserve grace for pending error diagnostics, avoid false Codex runtime live switches, avoid stale restart continuation reuse, preserve session fallback errors, suppress duplicate Claude CLI skill prompts, keep runtime context before active user turns, strip stale Anthropic thinking, quarantine unsupported tool schemas, recover completed write timeouts safely, release retained session write locks on timeout abort, and validate forced plugin harness support before pinning. (#86123, #55424, #86855, #74341, #87278) Thanks @luoyanglang, @cathrynlavery, and @openperf.</li>
<li>Reply/session delivery: keep visible turn admission unbounded, keep visible fallback delivery on latest targets, preserve bridge hook context, classify direct fallback targets by channel grammar, report approval resolutions in bridge mode, and avoid stale source-reply artifacts. (#87044) Thanks @keshavbotagent.</li>
<li>Channels: make Telegram <code>sendMessage</code> action replies durable and preserve SecretRef prompt config, suppress duplicate iMessage native exec approval prompts and sends, keep iMessage approval polling alive after denied reactions, keep Slack delivered final replies during late cleanup, keep Matrix mention previews/finals mention-inert and normally delivered, ignore filename-embedded Matrix IDs, suppress recovered Discord tool-warning artifacts from successful replies, suppress Google Chat thread sends in DMs, and harden Discord guild requester checks. (#87261, #87452) Thanks @mbelinky.</li>
<li>Memory: salvage QMD search JSON after nonzero exits and keep workspace memory routing through the Codex tool path where possible. (#87225, #87383, #87403) Thanks @osolmaz.</li>
<li>Providers/models: forward cached token usage in OpenAI-compatible chat completions, load Claude CLI OAuth overlays for PI auth profiles, send bare direct Anthropic model ids, wire configured VLLM thinking params, honor OpenAI-compatible cache retention, normalize OpenAI Responses replay tool ids, resolve OpenAI <code>gpt-5.5</code> without a cached catalog, preserve <code>retry-after</code> fallback handling, bound GitHub Copilot auth requests, and load DeepInfra custom/live catalogs consistently. (#82062, #87167, #84549) Thanks @caz0075, @joshavant, and @ats3v.</li>
<li>Gateway/performance: borrow read-only session metadata and active session working stores, cache current/stable plugin metadata fingerprints, cache auto-enabled plugin config, slim metadata identity caches, trust current metadata lifecycle caches, stabilize isolated cron prompt-cache affinity, persist model auth profile suffixes, drain probe client closes, expire browser tokens after auth rotation, and keep default status fast paths bounded. Thanks @ferminquant.</li>
<li>CLI/help/config: reject loose or malformed numeric options for gateway timeouts, model limits, directory limits, message options, webhooks, and partial values; respect subcommand version options; route generated/root/plugin help targets correctly; keep skills JSON output flushing naturally; and keep plugin descriptor loading quiet in root help. (#87398) Thanks @Patrick-Erichsen.</li>
<li>Plugin state/tool search: evict the current namespace when plugin rows hit caps, reuse unchanged tool-search catalogs, align the release catalog reuse wrapper, and keep fallback tool warnings mention-inert.</li>
<li>Install/package/release: match npm globstar exclusions, honor dist package exclusions in inventory, omit unpacked test helpers, skip Homebrew until macOS packages need it, package Docker runtime workspace templates, smoke Docker runtime templates during full validation, merge nested shrinkwrap override pins, preserve forked shrinkwrap pins, pin aged <code>lru-cache</code>, harden postpublish verification, accept main full-validation proof, and reject empty beta smoke runs.</li>
<li>E2E/QA/Crabbox: bound Telegram, Open WebUI, ClawHub, Matrix, Tool Search, MCP, gateway network, bundled runtime, kitchen-sink, codex media, config reload, and agent-turn assertion waits; prefer Azure for Windows targets; reinitialize invalid changed-gate git dirs; full-sync sparse container runs; and fail empty explicit test requests. (#87186)</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
<li>Exec approvals: remove the old <code>cat SKILL.md && printf ... && <skill-wrapper></code> allowlist compatibility path so skill files must be loaded with the read tool and only the real skill executable is auto-allowed.</li>
<li>Discord: let voice sessions follow configured Discord users into voice channels, with allowed-channel checks, multi-user handoff, bounded reconciliation, and DAVE recovery preservation. (#84264) Thanks @fuller-stack-dev.</li>
<li>Discord/voice: include bounded <code>IDENTITY.md</code>, <code>USER.md</code>, and <code>SOUL.md</code> profile context in realtime voice session instructions by default, with <code>voice.realtime.bootstrapContextFiles: []</code> available to disable it. (#84499) Thanks @fuller-stack-dev.</li>
<li>Dependencies: bump the bundled Codex harness to <code>@openai/codex</code> <code>0.132.0</code> and refresh the app-server model-list docs for the new catalog.</li>
<li>CLI/policy: add the bundled Policy plugin for policy-backed channel conformance checks, doctor lint findings, and opt-in workspace repair. (#80407) Thanks @giodl73-repo.</li>
<li>Agents/config: allow <code>agents.list[].experimental.localModelLean</code> so lean local-model mode can be enabled for one configured agent instead of globally.</li>
<li>Providers/xAI: add device-code OAuth login so remote and headless setups can authorize xAI without a localhost browser callback. (#84005) Thanks @fuller-stack-dev.</li>
<li>Providers/OpenRouter: honor provider-level <code>params.provider</code> routing policy for OpenRouter requests, with model and agent params overriding the defaults. Thanks @amknight.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>CLI/tasks: include stale-running task maintenance decisions in <code>openclaw tasks maintenance --json</code> so retained and reconcile candidates explain backing-session, cron, CLI, and wedged-subagent state. (#84691) Thanks @efpiva.</li>
<li>Codex app-server: keep system-prompt reports working when bootstrap hooks provide workspace files with only a path and content, so hook-supplied SOUL/IDENTITY/TOOLS/USER context still reports injected characters correctly. (#84736) Thanks @JARVIS-Glasses.</li>
<li>Providers/MiniMax music: stop advertising <code>durationSeconds</code> control and remove prompt-injected duration hints, so <code>music_generate</code> reports MiniMax duration as an unsupported override instead of suggesting MiniMax can enforce track length. Fixes #84508. Thanks @neeravmakwana.</li>
<li>Doctor: warn when sandbox tool policy hides configured MCP server tools before provider requests. (#84699) Thanks @nxmxbbd.</li>
<li>WhatsApp: update Baileys to <code>7.0.0-rc12</code>.</li>
<li>Build: suppress per-locale <code>rolldown-plugin-dts:fake-js</code> CommonJS dts warnings emitted while bundling the intentionally-inlined <code>zod/v4/locales/*.d.cts</code> files, so <code>pnpm build</code> output stays readable after the 0.25.1 plugin bump. Thanks @romneyda.</li>
<li>CLI/nodes: route lazy plugin-registration logs to stderr for JSON-mode <code>openclaw nodes</code> commands so stdout stays parseable. (#84684) Thanks @TurboTheTurtle.</li>
<li>Approvals: route manual <code>/approve</code> decisions through the trusted approval runtime so active exec and plugin approvals no longer look unknown or expired.</li>
<li>Mac app: update the About settings copyright year to 2026. (#84385) Thanks @pejmanjohn.</li>
<li>Dependencies: update <code>@openclaw/fs-safe</code> to <code>0.2.7</code> so OpenClaw's default Python-helper-off policy keeps best-effort Node write fallbacks for private stores, secret writes, run logs, and media attachments on Linux/macOS.</li>
<li>Infra/secrets: restore the fail-closed contract for <code>tryReadSecretFileSync</code> so credential loaders that pass <code>rejectSymlink: true</code> (Telegram, LINE, Zalo, IRC, Nextcloud Talk tokens) refuse symlinked credential files instead of silently accepting them, and the infra-state CI shard's secret-file symlink test passes again. Thanks @romneyda.</li>
<li>Browser: honor the configured image sanitization limit for screenshots and labeled snapshots so browser-captured images follow the same resize policy as other image results. (#84595)</li>
<li>Doctor: remove unrecognized <code>models.providers.*.models[*].compat.thinkingFormat</code> values during <code>doctor --fix</code> so stale provider model config can validate after upgrade. Fixes #77803.</li>
<li>Doctor: warn when <code>openclaw.json</code> stores plaintext secret-bearing config fields, including model provider API keys and sensitive provider headers. (#84718) Thanks @lukaIvanic.</li>
<li>Status: show the configured default, session-selected model, reason, clear hint, and docs link when a session remains pinned to a model that differs from <code>agents.defaults.model.primary</code>.</li>
<li>WebChat: clear stale typing indicators when session change events mark the active chat run complete.</li>
<li>Mac app: keep local packaging signed with a stable app identity for permission testing and fix Control UI production builds under current Vite/Highlight.js exports.</li>
<li>macOS app: update the embedded Peekaboo bridge to 3.2.1 so OpenClaw-hosted UI automation works with current Peekaboo CLI capture flows.</li>
<li>Cron: deliver preferred final assistant output for successful scheduled runs when trailing plain tool warnings remain in diagnostics instead of marking the run failed.</li>
<li>fix(mattermost): fail closed on missing channel type [AI]. (#84091) Thanks @pgondhi987.</li>
<li>CLI: keep the private QA subcommand out of exported command descriptors unless <code>OPENCLAW_ENABLE_PRIVATE_QA_CLI=1</code>, so root help and subcommand markers match runtime registration. (#84519)</li>
<li>CLI/cron: bound <code>openclaw cron show</code> job lookup pagination so non-advancing or unbounded <code>cron.list</code> responses fail instead of hanging the command. Fixes #83856. (#83989)</li>
<li>Agents/messages: stop message-tool-only turns after a successful source-channel <code>message</code> send while keeping transcript mirrors under the session write lock. (#84289)</li>
<li>Agents: filter silent heartbeat response-tool transcript artifacts out of embedded context snapshots so later user turns are not polluted by heartbeat no-op messages. (#83477) Thanks @fuller-stack-dev.</li>
<li>Agents/OpenAI: log repeated strict tool-schema downgrade diagnostics once per provider/model/tool signature, reducing duplicate debug noise while preserving <code>strict=false</code> fallback behavior. Fixes #82930. (#82933) Thanks @galiniliev.</li>
<li>Agents/code mode: spell out the <code>exec</code> tool's JavaScript/TypeScript, no Node module, and catalog-bridge constraints in model-visible schema text so agents can use enabled tools without trial-and-error. (#84269) Thanks @Kaspre.</li>
<li>Codex: give <code>image_generate</code> dynamic-tool calls a 120s default watchdog when no per-call or configured image timeout is set, so image generation no longer falls back to the generic 30s bridge timeout. (#84254) Thanks @moritzmmayerhofer.</li>
<li>Codex: avoid duplicate dynamic tool terminal diagnostics while large diagnostic backlogs drain without blocking tool responses. (#82937) Thanks @galiniliev.</li>
<li>CLI/message: include a stable top-level <code>messageId</code> in <code>openclaw message --json</code> output when channel sends return one. (#84191) Thanks @100menotu001.</li>
<li>Cron: preserve legacy top-level array <code>jobs.json</code> stores when loading or adding scheduled jobs so old cron jobs are no longer treated as an empty store during upgrade. Fixes #60799. (#84433) Thanks @IWhatsskill.</li>
<li>Gateway/agents: use an agent's <code>identity.name</code> in Gateway agent summaries when <code>agents.list[].name</code> is unset, so configured agent labels remain visible in clients. (#84355; refs #57835) Thanks @luoyanglang.</li>
<li>Channels/replies: keep normal <code>/verbose</code> failed-tool progress compact in message-tool replies and prevent late text-only tool output from appearing after the final answer. (#84303) Thanks @VACInc.</li>
<li>Plugins/hooks: apply a default 30-second timeout to <code>before_compaction</code> and <code>after_compaction</code> hooks so a hung plugin handler no longer blocks compaction completion. (#84153)</li>
<li>Discord: preserve disabled presentation buttons when adapting and rendering Discord message controls. (#84188) Thanks @100menotu001.</li>
<li>Twitch: add a test-only client-manager registry reset helper so non-isolated Twitch tests can clear cached managers between cases. Fixes #83887. (#84244) Thanks @hclsys.</li>
<li>Cron: run main-session scheduled work on a cron-owned wake lane while preserving reply delivery context, so background cron turns no longer block human main-session chat. Fixes #82766. (#82767) Thanks @galiniliev.</li>
<li>Cron: use structured embedded-run denial metadata for isolated scheduled tasks so blocked exec requests fail the job without treating ordinary assistant prose as a denial. (#84067) Thanks @abnershang.</li>
<li>Cron: keep recovered tool warnings diagnostic for successful scheduled runs so final cron output is delivered instead of being replaced by a post-processing warning. (#84045) Thanks @abnershang.</li>
<li>Plugins/perf: thread explicit plugin discovery results through <code>loadBundledCapabilityRuntimeRegistry</code>, <code>resolveBundledPluginSources</code>, and <code>listChannelCatalogEntries</code> so callers that already hold a discovery result skip redundant filesystem walks. Thanks @SebTardif.</li>
<li>Docker: keep the bundled Codex plugin in official release image keep lists so the default OpenAI agent harness remains available after Docker pruning. Fixes #83613. (#83626) Thanks @YuanHanzhong.</li>
<li>CLI/channels: preserve the first line of <code>openclaw channels logs</code> output when the rolling tail window starts exactly on a line boundary, mirroring the already-fixed <code>readLogSlice</code> behavior in <code>src/logging/log-tail.ts</code>.</li>
<li>Control UI: treat terminal session status as authoritative over stale active-run flags so completed terminal runs stop showing abort/live UI. (#84057)</li>
<li>CLI: preserve embedded equals signs in inline root option values instead of truncating after the second separator. (#83995) Thanks @ThiagoCAltoe.</li>
<li>Matrix/config: accept <code>messages.queue.byChannel.matrix</code> queue overrides and keep queue provider schema/type keys aligned for Matrix, Google Chat, and Mattermost. Thanks @bdjben.</li>
<li>CLI: format <code>openclaw acp client</code> failures through the shared error formatter so object-shaped errors stay readable instead of printing <code>[object Object]</code>. Fixes #83904. (#84080)</li>
<li>Providers/Ollama: default unknown-capabilities models to tool-capable so discovered native Ollama models can use tools when <code>/api/show</code> omits capabilities. (#84055) Thanks @dutifulbob.</li>
<li>Installer/Windows: launch <code>install.ps1</code> onboarding as an attached child process so fresh native Windows installs do not freeze visibly at <code>Starting setup...</code> or corrupt the wizard's terminal rendering.</li>
<li>CLI/update: keep restart health checks working across one-version CLI/Gateway protocol skew and use the managed Gateway service Node for all follow-up commands even when the package root is unchanged, so <code>openclaw update</code> no longer silently switches the gateway to a different Node binary when multiple Node installations are present. Thanks @amknight.</li>
<li>CLI/gateway: include the running Gateway version in <code>gateway status</code> JSON output, preserving existing server metadata while falling back to status RPC data for read probes. Fixes #56222. Thanks @galiniliev.</li>
<li>Memory/search: close local embedding providers when active-memory searches time out so pending local model loads and embedding contexts are aborted and released. (#83858) Thanks @brokemac79.</li>
<li>CLI/nodes: request pending node surface approval scopes before <code>openclaw nodes approve</code> so exec-capable node approval can use admin-scoped Gateway credentials instead of failing with <code>missing scope: operator.admin</code>. (#84392) Thanks @joshavant.</li>
<li>Gateway: reject slow node event sends before outbound buffers grow unbounded and log the rejected payload diagnostic. (#84387) Thanks @samzong.</li>
<li>Agents: include bounded trajectory queued-writer diagnostics in <code>pi-trajectory-flush</code> timeout warnings so flush stalls show pending writes, queued bytes, and append state. Fixes #82961. (#82962) Thanks @galiniliev.</li>
<li>Agents/subagents: recover stale completion announces by retrying unsupported transcript-wait wakes without transcript waiting and forcing a message-tool handoff when the requester run is already stale. Fixes #83699. (#83700) Thanks @galiniliev.</li>
<li>Agents/subagents: constrain wildcard subagent target allowlists to configured agents while preserving explicitly listed compatibility targets. Fixes #84040. (#84357) Thanks @joshavant.</li>
<li>Providers/Anthropic: route Anthropic model refs selected with Claude CLI auth through the Claude CLI runtime so shorthand refs such as <code>anthropic/opus-4.7</code> no longer fall back to embedded Anthropic billing. Fixes #84222. (#84374) Thanks @joshavant.</li>
<li>Agents: honor explicit <code>models.providers.<id>.timeoutSeconds</code> values above the default idle watchdog for cloud and self-hosted providers, so long first-token waits no longer fall back at ~120s when the provider timeout is higher. (#83979) Thanks @yujiawei.</li>
<li>Agents/Codex: keep encrypted Responses reasoning replay provenance-bound so stale mirrored Codex transcripts drop invalid encrypted content before request assembly while preserving matching same-session replay. Fixes #83836. (#84367) Thanks @joshavant.</li>
<li>Agents/subagents: skip stale embedded-run wake probes for dormant completion requesters, so late subagent completions go straight to requester-agent/direct handoff instead of producing <code>reason=no_active_run</code> queue noise. (#82964) Thanks @galiniliev.</li>
<li>CLI: retry config snapshot reads after a transient failure so one rejected read no longer poisons later commands in the same process. (#83931) Thanks @honor2030.</li>
<li>Media: decode URL path basenames before using them as remote media fallback filenames, so files like <code>My%20Report.pdf</code> are surfaced as <code>My Report.pdf</code>. Fixes #84050. (#84052) Thanks @jbetala7.</li>
<li>WhatsApp: clarify inbound group diagnostics so observed but unregistered groups point to <code>channels.whatsapp.groups</code> without changing routing or sender authorization. (#83846) Thanks @neeravmakwana.</li>
<li>WhatsApp: drain pending outbound deliveries on a 30s periodic timer in addition to the reconnect handler, so messages enqueued while the provider is already connected no longer wait for the next reconnect to send. (#79083) Thanks @Oviemudiaga.</li>
<li>CLI/TUI: include gateway plugin slash commands in TUI autocomplete, so connected sessions can suggest plugin-owned commands exposed by the running Gateway. (#83640) Thanks @se7en-agent.</li>
<li>Gateway/mobile: restore QR setup-code handoff of bounded operator tokens for iOS and Android onboarding while keeping admin and pairing scopes out of bootstrap. (#83684) Thanks @ngutman.</li>
<li>iOS: repair Release archive compilation for the TestFlight build. (#84255) Thanks @ngutman.</li>
<li>Agents/compaction: bound plugin-owned CLI transcript compaction with the host safety timeout so a hung context engine can no longer stall post-turn cleanup. (#84083) Thanks @100yenadmin.</li>
<li>Control UI/usage: truncate long context skill, tool, and file names in the usage panel while keeping the full name available on hover. (#42197) Thanks @Rain120.</li>
<li>Codex: respect explicit <code>models auth order set</code> and <code>config.auth.order</code> precedence over stale <code>lastGood</code> in <code>/codex account</code>, and show <code>no working credential</code> when every explicit-order profile is ineligible instead of marking a lower-ranked profile as active. Fixes #84386. (#84412) Thanks @openperf.</li>
<li>Agents: honor <code>messages.suppressToolErrors</code> for mutating tool failures so configured chat surfaces do not receive separate warning payloads. (#81561) Thanks @moeedahmed.</li>
<li>Agents/fallback: surface billing guidance for mixed rate-limit plus billing fallback exhaustion instead of generic failure copy. Fixes #79396. (#79489) Thanks @aayushprsingh.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.