Compare commits

..

595 Commits

Author SHA1 Message Date
Alex Knight
0a623ed028 fix llm-only allowlist handling 2026-05-03 22:58:19 +10:00
Peter Steinberger
0459bff556 refactor: share package cleanup helpers 2026-05-03 13:51:21 +01:00
Peter Steinberger
6f9a9241a6 perf(gateway): defer early maintenance startup 2026-05-03 13:51:02 +01:00
Peter Steinberger
6a653888fd build(protocol): refresh generated Swift models 2026-05-03 13:48:17 +01:00
Peter Steinberger
f30dd51d5f fix(gateway): stop lazy cron startup on hot reload 2026-05-03 13:44:28 +01:00
Peter Steinberger
ecb901ca39 ci: record tested ref in performance reports 2026-05-03 13:43:30 +01:00
Craig
baf8b8effe fix: continue update runs after restart (#74362) (thanks @100menotu001) 2026-05-03 18:13:25 +05:30
Steven Chou
fa533101d8 Run doctor after global gateway updates 2026-05-03 13:43:00 +01:00
Peter Steinberger
74f9a2aedd test: allow capability provider runtime registry lookup 2026-05-03 13:35:42 +01:00
Peter Steinberger
fbe9e2296f chore: remove redundant npmignore 2026-05-03 13:33:40 +01:00
Peter Steinberger
706132c655 perf(gateway): add startup CPU profile option 2026-05-03 13:30:35 +01:00
Peter Steinberger
0b1fbeabed perf(gateway): defer cron and sentinel startup work 2026-05-03 13:30:35 +01:00
Peter Steinberger
fd5e6ae9f1 chore: remove stale root tooling files 2026-05-03 13:29:34 +01:00
Peter Steinberger
a7b76835d4 ci: ignore generated extension viewer asset in lint 2026-05-03 13:28:30 +01:00
Peter Steinberger
ca69917153 test(sandbox): cover registry migration 2026-05-03 13:25:32 +01:00
Peter Steinberger
1402997489 fix(sandbox): move registry file migration to doctor 2026-05-03 13:25:32 +01:00
Peter Steinberger
1cebe32d76 fix(sandbox): harden sharded registry storage 2026-05-03 13:25:32 +01:00
Vincent Koc
164dfc4218 fix(sandbox): remove registry helper generics 2026-05-03 13:25:32 +01:00
hobo
975891153f perf(sandbox): shard container registry into per-entry files to remove cross-session lock contention
The sandbox registry stores one JSON document per scope (containers
and browsers), with every writer serialized through
`acquireSessionWriteLock` against that single file. In a host running
several sessions in parallel — multiple pairings, subagent spawns, or
just an `ensureSandboxContainer` landing at the same moment as a
`removeRegistryEntry` — each writer waits up to 60s for the lock, and
a crashed process can leave the lock file behind long enough to
wedge every subsequent sandbox operation until the stale-lock
threshold elapses. The lock's only job is to keep entries from
trampling each other inside one JSON blob, so it is a whole-file
mutex gating reads/writes that touch disjoint entries.

Each container already has a unique name (enforced at creation), so
each entry's storage can be disjoint too. This change turns the
`~/.openclaw/sandbox/containers.json` and `browsers.json`
monolithic files into per-entry JSON files under
`~/.openclaw/sandbox/containers/` and `~/.openclaw/sandbox/browsers/`
directories. `writeJsonAtomic` (tmp-file + rename) keeps each
per-entry write crash-safe, and because concurrent writers only
touch their own files there is nothing left to serialize across.

Changes:

- `src/agents/sandbox/constants.ts`: add `SANDBOX_CONTAINERS_DIR`
  and `SANDBOX_BROWSERS_DIR` sibling to the existing monolithic
  paths. The old paths stay exported because the one-shot migration
  still needs to locate the legacy file.
- `src/agents/sandbox/registry.ts`: replace the
  `withRegistryLock` / `readRegistryFromFile("strict")` /
  `writeRegistryFile` loop with per-entry read/write/remove
  primitives against the sharded directories, and drop the
  `acquireSessionWriteLock` import. The existing upstream additions
  are preserved: the zod `RegistryEntrySchema`, the
  `backendId`/`runtimeLabel`/`configLabelKind` fields on
  `SandboxRegistryEntry`, and `normalizeSandboxRegistryEntry` still
  decorate reads. Upsert merge semantics (preserve `createdAtMs` and
  `image` from the prior entry, prefer the newer `configHash`) are
  kept bit-for-bit.
- `src/agents/sandbox/registry.ts`: add `readRegistryEntry(name)`
  for O(1) single-container lookup. The previous hot path in
  `ensureSandboxContainer` had to read the whole registry and
  `Array.find` the one entry it wanted; the new API avoids both the
  full directory scan and the JSON round-trip on every other entry.
- `src/agents/sandbox/registry.ts`: add a one-shot
  `migrateMonolithicIfNeeded` helper invoked at the top of every
  public read/write. If a legacy `containers.json` / `browsers.json`
  exists, its entries are fanned out into per-entry files, the old
  file and its `.lock` are removed, and subsequent calls skip the
  migration branch entirely. Malformed legacy files are dropped
  rather than throwing forever, because a corrupt single-file
  registry that has already been superseded by the new storage
  would otherwise block every sandbox ensure/remove on every boot.
  Live per-entry files still go through the same schema validation
  the upstream strict path used — a corrupt per-entry file is
  simply skipped during enumeration so that one bad file cannot
  hide every other running container from the operator.
- `src/agents/sandbox/docker.ts`: swap the `readRegistry()` +
  `Array.find` lookup in `ensureSandboxContainer` for the new
  `readRegistryEntry(containerName)`. This is the only in-tree
  caller that needed the full scan just to pick one entry.
- `src/agents/sandbox/registry.test.ts`: rewrite around the new
  per-file semantics. The old tests covered two properties that no
  longer exist — "the lock serializes concurrent update/remove so
  the later write cannot resurrect a removed entry" and "a
  malformed monolithic file makes every `update` throw" — both of
  which were artifacts of the single-file design. The rewrite keeps
  the normalizeSandboxRegistryEntry contract, the
  concurrent-updates-succeed contract (now without any lock in
  play), the malformed-legacy-migration contract, and adds coverage
  for `readRegistryEntry`, the stale-`.lock` cleanup, and the
  "corrupt per-entry file does not hide its siblings" guarantee.
- `src/agents/sandbox/docker.config-hash-recreate.test.ts`: update
  the mock module to expose `readRegistryEntry` instead of
  `readRegistry`, and return single-entry objects or `null` rather
  than `{ entries: [...] }`.

Other in-tree consumers (`manage.ts`, `prune.ts`, `browser.ts`,
`context.ts`) only call the public `readRegistry` / `updateRegistry`
/ `remove*` surface, whose return shapes and observable behavior
are unchanged; their existing tests (`manage.test.ts`,
`browser.create.test.ts`, `sandbox.resolveSandboxContext.test.ts`)
all pass unmodified.

Default behavior is unchanged from the operator's point of view:
the first boot on the new code sees the legacy files, migrates them
in place, and deletes them. Subsequent boots never touch the
migration path. No config surface, no types, and no public exports
are removed.
2026-05-03 13:25:32 +01:00
HCL
deb7b821c1 fix(plugins): include selected context-engine slot plugin in gateway startup (#76576)
External context-engine plugins (e.g. lossless-claw) register via
api.registerContextEngine at load time but ship without
activation.onStartup in their manifest. The gateway startup planner
only considered memory plugins and explicit sidecar plugins, so a
selected non-legacy context engine was omitted from the startup load
plan and never loaded before agent turns resolved the active engine,
producing the "Context engine X is not registered; falling back to
default engine legacy" warning.

Fix: add resolveContextEngineSlotStartupPluginId mirroring the memory
slot pattern; pass contextEngineSlotStartupPluginId into
shouldConsiderForGatewayStartup so the selected context-engine plugin
is included in pluginIds regardless of its manifest activation shape.

Tests: added four regression cases covering include, exclude, legacy
bypass, and id normalization. 82 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 13:22:47 +01:00
Peter Steinberger
d00bcf555b test(plugins): cover config-origin tool cold load diagnostics 2026-05-03 13:22:47 +01:00
HCL
a3b94f3910 fix(plugins): restore cold-registry load for path-based plugin tools (#76598)
`resolvePluginTools` returned an empty tool list when no pre-warmed
channel/active registry was found after startup — the on-demand fallback
removed by PR #76004 was only added back for memory and capability-provider
surfaces, leaving path-based (origin "config") plugin tool factories silent.

Fix: when `resolvePluginToolRegistry` returns null, trigger a standalone
registry load via `ensureStandaloneRuntimePluginRegistryLoaded`, then retry.
Adds regression test asserting tools are resolved without pre-warming.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 13:22:47 +01:00
Conan-Scott
8ebf86cdff fix(plugins): preserve external capability provider fallback (#76536)
* fix(plugins): preserve external capability provider fallback

* docs: move changelog entry to avoid merge conflict

---------

Co-authored-by: Clawdbot <clawdbot@apilab.us>
2026-05-03 13:22:34 +01:00
Peter Steinberger
4fff25438c fix: propagate stream timeout abort reason (#76633) 2026-05-03 13:21:02 +01:00
mkdev11
ffd3dfa4f5 fix agents stream timeout heartbeat 2026-05-03 13:21:02 +01:00
Peter Steinberger
4760ee4055 chore: remove root assets 2026-05-03 13:20:26 +01:00
Peter Steinberger
2b82c05a7f fix(plugins): include inherited tts persona providers at startup 2026-05-03 13:17:24 +01:00
Peter Steinberger
4bc82fc787 docs: note config dry-run schema validation fix 2026-05-03 13:17:13 +01:00
Peter Steinberger
81fea91fda fix: restore config dry-run schema validation 2026-05-03 13:16:20 +01:00
Peter Steinberger
9a49d143c8 test: update config patch schema fixture 2026-05-03 13:16:10 +01:00
Peter Steinberger
0f66ad4243 ci: pin fixed Kova benchmark 2026-05-03 13:12:31 +01:00
Peter Steinberger
6e2f394473 test(auto-reply): guard message-tool-only reply privacy 2026-05-03 13:12:26 +01:00
Peter Steinberger
869103684f chore: move swabble into apps 2026-05-03 13:10:25 +01:00
Peter Steinberger
0031ef3120 refactor: keep legacy secretref migration in doctor 2026-05-03 13:10:00 +01:00
Peter Steinberger
e0a83c0046 test: fix tui command completion typecheck 2026-05-03 13:03:11 +01:00
Peter Steinberger
45a5374ca8 perf: reduce raw gateway config startup work 2026-05-03 13:03:11 +01:00
Peter Steinberger
73be4ea901 ci: fix full release validation gates 2026-05-03 13:01:14 +01:00
Peter Steinberger
0fbb06e6df ci: use org-owned Kova benchmark 2026-05-03 12:57:39 +01:00
Peter Steinberger
adc4fd453b chore: move test tsconfigs 2026-05-03 12:56:52 +01:00
byungskers
f7522edb96 fix(plugins): preserve sibling npm installs
Run npm install from the managed npm-root manifest so sequential @openclaw/* plugin installs preserve siblings on disk.

Fixes #76571.
Thanks @byungskers and @crpol.
2026-05-03 12:51:50 +01:00
Peter Steinberger
b8a4d6a58a test: move root contract fixture 2026-05-03 12:48:16 +01:00
Chunyue Wang
c1b9af2770 fix(ollama): restore catalog-driven num_ctx for native /api/chat (#76181)
Merged via squash.

Prepared head SHA: d3142252d5
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Reviewed-by: @openperf
2026-05-03 19:47:36 +08:00
Peter Steinberger
1507c6dac7 perf: reduce gateway startup overhead 2026-05-03 12:44:23 +01:00
Alex Knight
8142e67d63 fix(plugins): start configured speech providers (#76540)
* fix(plugins): start configured speech providers

* fix(plugins): mirror tts provider selection
2026-05-03 21:41:50 +10:00
Alex Knight
d0dc72bf32 test: harden flaky CI assertions (#76624) 2026-05-03 21:41:47 +10:00
volcano303
1d657b9d5f fix(active-memory): preserve setup grace for embedded recall
Apply setupGraceTimeoutMs to the embedded recall runner as well as the outer Active Memory watchdog.

Co-authored-by: volcano303 <75143900+volcano303@users.noreply.github.com>
2026-05-03 12:41:19 +01:00
Alex Knight
8a0e3b6422 test(ui): clean up navigation teardown (#76625) 2026-05-03 21:41:08 +10:00
Peter Steinberger
5ab4e6f9d9 chore: clean up editor metadata 2026-05-03 12:39:15 +01:00
Alex Knight
54a81e0080 fix: expose session-specific thinking levels (#76548)
* fix: expose session-specific thinking levels (#76482)

* fix: preserve lightweight sessions.list contract, fix consumer-side fallbacks only

* fix: include thinking levels in lightweight session rows for Control UI (#76482)

The Control UI cannot resolve provider-specific thinking levels client-side
(ui/src/ui/thinking.ts always returns base 5 levels). The gateway must
provide them even in lightweight rows. listThinkingLevelOptions is a cheap
in-memory lookup — negligible perf impact vs the transcript/cost/model ops
that the lightweight flag still skips.

Also update existing test assertions that expected thinkingOptions: [] for
lightweight rows (flagged by ClawSweeper review).

* test: add e2e regression tests for thinking level pipeline (#76482)
2026-05-03 21:38:32 +10:00
Alex Knight
a92e2b13b8 fix(agents): detect incomplete tool-use turns with pre-tool text (#76477) (#76544)
* fix(agents): detect incomplete tool-use turns with pre-tool text (#76477)

When the last assistant message ended with stopReason=toolUse, pre-tool
text alone (payloadCount > 0) was suppressing the incomplete-turn guard.
The model expected to continue after tool results but the post-tool
response was never produced, silently dropping the final answer.

Fix isIncompleteTerminalAssistantTurn to always flag toolUse stop reason
as incomplete regardless of pre-tool text, and update the early-return
condition in resolveIncompleteTurnPayloadText to not skip the check when
the last assistant ended with a tool call.

* fix(agents): mark tool-use terminal with pre-tool text as abandoned in lifecycle (#76477)

The lifecycle handler's derivedWorkingTerminalState was emitting
'working' for interrupted tool-use turns with pre-tool text because
it required !hasAssistantVisibleText for the 'abandoned' state.

Update the derivation to also mark as 'abandoned' when
incompleteTerminalAssistant is true, so lifecycle consumers see a
consistent state with the runner's terminal result.
2026-05-03 21:32:06 +10:00
Peter Steinberger
79f77d877e docs: move incident response plan 2026-05-03 12:30:11 +01:00
Peter Steinberger
f273083378 fix(doctor): match stale plugin records exactly 2026-05-03 12:26:42 +01:00
Peter Steinberger
1584acb124 fix(secrets): stabilize credential matrix docs 2026-05-03 12:25:08 +01:00
Peter Steinberger
c850d1bb0d fix(qqbot): harden clientSecret SecretRefs 2026-05-03 12:25:08 +01:00
xialonglee
40f970a13d feat(qqbot): resolve clientSecret SecretRefs and add secret contract 2026-05-03 12:25:08 +01:00
Ray
153e4c59cf docs(active-memory): document setup grace cold starts
Docs-only follow-up for setupGraceTimeoutMs and first-recall cold-start troubleshooting.\n\nThanks @RayWoo.
2026-05-03 12:24:35 +01:00
Peter Steinberger
5f4fd05074 ci: speed up full release validation 2026-05-03 12:24:24 +01:00
Peter Steinberger
5e9135f2e2 fix: keep active memory tools available 2026-05-03 12:24:03 +01:00
Peter Steinberger
02c2160478 chore: clean up root clutter 2026-05-03 12:20:52 +01:00
Peter Steinberger
4ec1efbcbc fix(catalog): pin prerelease channel npm specs 2026-05-03 12:18:56 +01:00
Peter Steinberger
8dd6a2d323 fix(channels): preserve degraded voice text and mention boundaries 2026-05-03 12:17:11 +01:00
Alex Knight
1e4098134a fix: enable browser tools with full profile (#76557)
Summary:
- The PR makes `tools.profile: "full"` resolve to a wildcard allowlist, teaches plugin optional-tool allowlist checks to honor `*`, and updates regression tests, docs, and the changelog for browser tool availability.
- Reproducibility: yes. source-level reproduction is high confidence: current main makes `full` resolve to no  ...  plugin allowlist helpers do not accept `*`. I did not run a live browser session in this read-only review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: docs: update full profile description and add changelog for #76507

Validation:
- ClawSweeper review passed for head b5329de33c.
- Required merge gates passed before the squash merge.

Prepared head SHA: b5329de33c
Review: https://github.com/openclaw/openclaw/pull/76557#issuecomment-4365736091

Co-authored-by: Alex Knight <aknight@atlassian.com>
2026-05-03 11:12:30 +00:00
Vincent Koc
9772ce6ce9 docs(changelog): move @romneyda logs --follow notice fix to Unreleased
#75372 added `[logs] gateway reconnected` notice and JSON `notice`
records as a follow-up to #75059 and landed today, but its changelog
entry was placed under `## 2026.4.29` (already released). Move it next
to the related #75059 entry under `## Unreleased ### Fixes` so the
released section stays frozen and the credited contributor lands in the
right release window. Thanks @romneyda.
2026-05-03 03:28:33 -07:00
Vincent Koc
ae87f7800b test(matrix): isolate IndexedDB persistence fixtures 2026-05-03 03:18:00 -07:00
Vincent Koc
4545a0ed61 fix(plugins): keep launch specs production-ready 2026-05-03 03:08:32 -07:00
Vincent Koc
26f2241a87 fix(onboarding): limit ClawHub npm fallback 2026-05-03 03:05:48 -07:00
Vincent Koc
07e0342106 fix(update): trust catalog-matched npm updates 2026-05-03 03:04:25 -07:00
Vincent Koc
423b5d6981 fix(update): trust externalized npm bridges 2026-05-03 03:02:16 -07:00
Vincent Koc
0393ec5b53 fix(catalog): type channel ClawHub specs 2026-05-03 03:00:36 -07:00
Vincent Koc
961575ddf7 fix(catalog): preserve channel ClawHub specs 2026-05-03 02:59:49 -07:00
Vincent Koc
a4c1c28a17 fix(doctor): preserve catalog repair specs 2026-05-03 02:57:34 -07:00
Dallin Romney
4bb4127a33 feat(cli/logs): announce --follow gateway reconnect and add JSON notice parity (#75372) 2026-05-03 17:55:58 +08:00
Vincent Koc
3ee5df618a Revert "fix(plugins): align beta external launch metadata"
This reverts commit 34581bf46c.
2026-05-03 02:53:36 -07:00
Vincent Koc
34581bf46c fix(plugins): align beta external launch metadata 2026-05-03 02:51:18 -07:00
Vincent Koc
e7b6e0ff90 fix(plugins): pin beta-only external launch specs 2026-05-03 02:50:10 -07:00
Vincent Koc
310b1987e1 fix(cron): persist startup state sidecar repairs 2026-05-03 02:45:59 -07:00
Jesse Merhi
84a30e213e Fix managed proxy TLS hostname validation (#76442)
Summary:
- The PR wraps managed global-agent HTTPS CONNECT socket creation to preserve the target TLS host/servername, adds a Discord-style regression e2e, and records the fix in the changelog.
- Reproducibility: yes. #74809 provides exact config, logs, and a minimal global-agent repro, and source inspection confirms current main does not pass the CONNECT target host into TLS options.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(proxy): document global-agent TLS shim
- PR branch already contained follow-up commit before automerge: refactor(proxy): narrow global-agent patch typing
- PR branch already contained follow-up commit before automerge: Fix managed proxy TLS hostname validation
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-7644…

Validation:
- ClawSweeper review passed for head 058ae37663.
- Required merge gates passed before the squash merge.

Prepared head SHA: 058ae37663
Review: https://github.com/openclaw/openclaw/pull/76442#issuecomment-4365375603

Co-authored-by: Jesse Merhi <jessejmerhi@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-03 09:42:45 +00:00
Vincent Koc
6a823a4f23 test(onboarding): assert channel status surfaces 2026-05-03 02:38:55 -07:00
scoootscooob
85e4ec1fb1 fix(doctor): persist group visible reply default (#76513) 2026-05-03 02:32:41 -07:00
Dallin Romney
de88b379c9 fix(plugins): clean up plugins search output formatting (#76000) 2026-05-03 17:30:03 +08:00
Vincent Koc
e02377f522 docs(changelog): credit @shashank-poola for logs --follow auto-reconnect
#75059 (fixes #74782) added user-facing CLI behavior — bounded
exponential reconnect for `openclaw logs --follow` on transient
gateway disconnect — and updated docs/cli/logs.md, but landed without a
`## Unreleased` entry. Add the missing line so the credited human
contributor is captured in the active release window. Thanks
@shashank-poola.
2026-05-03 02:28:54 -07:00
Vincent Koc
4473c56b85 fix(clawhub): clarify unreleased plugin artifacts 2026-05-03 02:26:27 -07:00
Vincent Koc
2a1c6cf179 test(plugins): expose discord onboarding lane 2026-05-03 02:24:24 -07:00
hcl
bdf91fab9c fix(realtime): strip originator header from browser WebRTC SDP offer (#76435)
Remove server-side-only OpenAI attribution headers from browser WebRTC SDP offer headers while preserving Gateway-side attribution.

Closes #76435.
Thanks @hclsys.
2026-05-03 02:24:03 -07:00
Vincent Koc
058b625154 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(cli): auto-reconnect logs --follow on transient gateway disconnect #74782 (#75059)
2026-05-03 02:20:38 -07:00
Vincent Koc
2e608ad516 Revert "fix(onboarding): prefer clawhub diagnostics installs"
This reverts commit 3338581c20.
2026-05-03 02:19:06 -07:00
Shashank
23fe3559e5 fix(cli): auto-reconnect logs --follow on transient gateway disconnect #74782 (#75059)
* fix(cli): auto-reconnect logs --follow on transient gateway disconnect

* fix(cli): honor errorLine return value in follow retry warning
2026-05-03 17:18:50 +08:00
Vincent Koc
f9a1f86e64 test(secrets): audit external channel SecretRefs (#76589) 2026-05-03 02:17:41 -07:00
Vincent Koc
3338581c20 fix(onboarding): prefer clawhub diagnostics installs 2026-05-03 02:15:51 -07:00
buyitsydney
aba97a4c7c fix(memory): reindex archived session transcript updates 2026-05-03 02:15:20 -07:00
Vincent Koc
478887083e test(plugins): decouple config-gated install fixture 2026-05-03 02:14:42 -07:00
Vincent Koc
31e2276fe9 fix(memory): load unconfigured lancedb metadata 2026-05-03 01:57:36 -07:00
Vincent Koc
5ecd01ff94 fix(plugins): trust managed npm peer links 2026-05-03 01:49:24 -07:00
Vincent Koc
9ef35ea5c7 fix(plugin-sdk): classify channel facades 2026-05-03 01:48:53 -07:00
solodmd
d1365fef16 fix: handle ENOSPC file watcher errors gracefully (#73357)
Merged via squash.

Prepared head SHA: ce2dd6ed3e
Co-authored-by: solodmd <51304754+solodmd@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-05-03 11:42:38 +03:00
Vincent Koc
4781b46056 fix(channels): load third-party official channel packages 2026-05-03 01:30:43 -07:00
Vincent Koc
8af6add03b test(ci): update plugin registry fixture assertion 2026-05-03 01:23:00 -07:00
Vincent Koc
84cb9108ec docs(changelog): move @amknight Teams and Matrix restart fixes to Unreleased
Both #75585 (msteams sent-message marker persistence) and #75586 (matrix
approval reaction target persistence) landed on main 2026-05-03 but
appended their changelog entries under `## 2026.4.30`, which was
finalized on 2026-05-01. Move them under `## Unreleased ### Fixes` so
the released section stays frozen and the new fixes are credited in the
right release window. Thanks @amknight.
2026-05-03 01:22:28 -07:00
Vincent Koc
ea45950a9d test(plugins): add lifecycle matrix coverage
Add plugin lifecycle matrix Docker E2E coverage, resource metrics, fixture registry version support, and gauntlet handling for bundled plugin ids / required config.
2026-05-03 01:18:31 -07:00
buyitsydney
2ffdb5d248 fix(memory): keep archive transcript visibility safe
Keep reset/deleted session archives searchable while preserving visibility filtering, and keep internal cron-run archives opaque when live ownership metadata is gone.\n\nRefs #56131.\nThanks @buyitsydney.
2026-05-03 01:17:45 -07:00
Vincent Koc
d583662fd9 test(tooling): isolate a2ui copy env 2026-05-03 01:07:58 -07:00
Vincent Koc
d89be34360 fix(onboarding): trust official web search installs 2026-05-03 00:48:37 -07:00
Neerav Makwana
b6cbd9225c fix(cli): load memory plugin for doctor/status when registry is cold (#76393)
Summary:
- The PR adds a scoped standalone memory-slot plugin load for doctor/status memory resolution, updates memory-runtime regression tests, and adds a changelog fix entry.
- Reproducibility: yes. source-reproducible: current main's doctor/status path reads getMemoryRuntime after on ...  registers that runtime only during plugin activation. I did not run a live macOS LaunchAgent reproduction.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(cli): load memory plugin for doctor/status when registry is cold

Validation:
- ClawSweeper review passed for head a6a1967316.
- Required merge gates passed before the squash merge.

Prepared head SHA: a6a1967316
Review: https://github.com/openclaw/openclaw/pull/76393#issuecomment-4365255585

Co-authored-by: Neerav Makwana <261249544+neeravmakwana@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-03 07:38:55 +00:00
Vincent Koc
39bc94e4dd fix(onboarding): trust official optional plugin installs 2026-05-03 00:29:04 -07:00
Alex Knight
6ae09d029c msteams: persist sent-message markers best-effort (#75585)
* msteams: persist sent-message markers best-effort

* docs: clarify Teams restart persistence changelog

* msteams: remove redundant sent-message TTL comment

* msteams: preserve sent-message marker TTL on recovery
2026-05-03 17:25:20 +10:00
Vincent Koc
882ddc4665 fix(gateway): keep agent image attachment checks accurate 2026-05-03 00:21:04 -07:00
Vincent Koc
74f243a0d0 fix(cli): keep plugin toggles out of channel config (#76525) 2026-05-03 00:19:37 -07:00
Alex Knight
f27ecffc0c matrix: persist approval reaction targets best-effort (#75586)
* matrix: persist approval reaction targets best-effort

* docs: refine matrix approval changelog
2026-05-03 17:17:01 +10:00
Vincent Koc
b74401074b fix(gateway): keep models list read-only fast
Fixes https://github.com/openclaw/openclaw/issues/76382
2026-05-03 00:10:54 -07:00
Vincent Koc
a6d25c1c2e test(plugins): assert local install uninstall cleanup 2026-05-03 00:04:05 -07:00
Vincent Koc
f1da57a4a8 test(update): keep global install sidecar failure covered 2026-05-02 23:59:23 -07:00
Peter Steinberger
95cee64ca6 fix(cli): keep empty agent replies silent
* fix(cli): keep empty agent replies silent

* fix(commands): preserve empty gateway status summaries

---------

Co-authored-by: Peter Steinberger <steipete@steipete-macstudio.local>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-02 23:47:59 -07:00
Vincent Koc
c7bbb3f9af refactor(plugins): declare static runtime assets in package metadata 2026-05-02 23:47:25 -07:00
Vincent Koc
188c3b74ba fix(plugins): declare host peer in npm runtime packs 2026-05-02 23:47:25 -07:00
Vincent Koc
25ceffbf25 refactor(plugins): centralize npm runtime package planning 2026-05-02 23:47:25 -07:00
Vincent Koc
fb6893cf48 docs(changelog): note plugin runtime package fix 2026-05-02 23:47:25 -07:00
Vincent Koc
13d2bfb742 test(plugins): add npm runtime build sweep 2026-05-02 23:47:25 -07:00
Vincent Koc
b44cbecdf8 fix(plugins): keep package dry-run json clean 2026-05-02 23:47:25 -07:00
Vincent Koc
11a5b30f3e fix(plugins): build package-local npm runtimes 2026-05-02 23:47:25 -07:00
Vincent Koc
ac7e7f0512 docs(changelog): credit sqlite-vec report 2026-05-02 23:47:04 -07:00
Vincent Koc
95001d6c41 fix(memory): keep sqlite-vec optional 2026-05-02 23:44:01 -07:00
Vincent Koc
140c274335 test(cli): cover official external npm installs without integrity
Add catalog-derived coverage so official external npm plugin aliases without integrity pins still use the trusted official install path.
2026-05-02 23:42:26 -07:00
Vincent Koc
2a22eb68aa fix(plugins): require provenance for official npm trust
Require OpenClaw-owned install provenance before granting official npm plugin scanner trust. Direct npm package names now scan normally; catalog, onboarding, and doctor paths pass explicit provenance.\n\nValidation:\n- pnpm test:serial src/plugins/install.npm-spec.test.ts src/cli/plugins-cli.install.test.ts src/commands/onboarding-plugin-install.test.ts src/commands/doctor/shared/missing-configured-plugin-install.test.ts src/channels/plugins/contracts/channel-catalog.contract.test.ts src/commands/auth-choice.apply.plugin-provider.test.ts\n- pnpm test:serial src/plugins/install.test.ts src/plugins/provider-auth-choices.test.ts src/plugins/provider-install-catalog.test.ts src/commands/channel-setup/plugin-install.test.ts\n- pnpm exec oxfmt --check --threads=1 ...\n- node scripts/run-oxlint.mjs ...\n- Crabbox cbx_6157440c9bbe / run_cbd813956eed: pnpm check:changed passed\n\nThanks @fede-kamel and @vincentkoc.
2026-05-02 23:30:45 -07:00
Vincent Koc
f249b1c6df fix(plugins): clean managed git uninstall roots 2026-05-02 23:30:01 -07:00
Chris Zhang
cb7b2850e4 fix(build): externalize Feishu Lark SDK
Externalize @larksuiteoapi/node-sdk from the bundled Feishu ESM runtime so packaged startup loads the SDK as a plugin-local runtime dependency instead of inlining the SDK's ESM __dirname path.

Adds changelog credit and a tsdown-config regression assertion.

Fixes #76291.
Fixes #76494.

Co-authored-by: Chris Zhang <4436110+zqchris@users.noreply.github.com>
2026-05-02 23:27:13 -07:00
Vincent Koc
14312ff570 fix(feishu): avoid duplicate voice reply text 2026-05-02 23:18:42 -07:00
Vincent Koc
3c51692543 fix(config): bound clobber recovery snapshots (#76483) 2026-05-02 23:13:56 -07:00
Vincent Koc
b0a6543838 fix(agents): keep delayed sessions_send replies alive (#76484) 2026-05-02 23:08:10 -07:00
Jesse Merhi
207aa18c40 Add shell command explainer (#75004)
Summary:
- The PR adds an internal Tree-sitter-backed shell command explainer under `src/infra`, parser runtime/tests, dependency/build-policy updates, an index export, and a changelog entry.
- Reproducibility: not applicable. this is a feature PR rather than a bug report. For the prior PR blocker, source inspection shows byte-to-string span conversion and focused Unicode span coverage on the exact head.

Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: Repair shell command explainer automerge blockers
- Included post-review commit in the final squash: fix(clawsweeper): address review for automerge-openclaw-openclaw-7500…

Validation:
- ClawSweeper review passed for head 47577579e9.
- Required merge gates passed before the squash merge.

Prepared head SHA: 47577579e9
Review: https://github.com/openclaw/openclaw/pull/75004#issuecomment-4351322592

Co-authored-by: Jesse Merhi <jessejmerhi@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-03 06:05:29 +00:00
Vincent Koc
e27b7c2d74 docs(changelog): credit secretref channel fix 2026-05-02 22:55:31 -07:00
Arnab Saha
b83b2e3f1c fix(openai-codex): honor providerConfig.baseUrl in dynamic-model synthesis fallback (#76428)
* fix(openai-codex): honor providerConfig.baseUrl in dynamic-model synthesis fallback

The synthesis fallback in resolveCodexForwardCompatModel hardcoded
OPENAI_CODEX_BASE_URL when the model registry had no template row to
clone, which meant openai-codex providers configured with a custom
baseUrl (e.g. a local proxy that forwards Codex traffic) silently
fell back to api.openai.com / chatgpt.com - bypassing the proxy and
typically failing the auth contract.

Synthesis now reads ctx.providerConfig.baseUrl when present, with the
existing OPENAI_CODEX_BASE_URL constant as the fallback. No effect on
template-clone or registry-find paths, which already inherit the
configured baseUrl through the cloned template.

* docs(changelog): add Unreleased Fixes entry for #76428 codex synthesis baseUrl honor
2026-05-02 22:52:29 -07:00
Marvinthebored
73a95d3af4 fix(gateway): read-only persisted fast path for models.list catalog (#76406)
* fix(gateway): read-only fast path for models.list catalog loading

The gateway model catalog refresh calls loadModelCatalog without
readOnly, triggering ensureOpenClawModelsJson (60-70s), full PI SDK
registry instantiation, auth storage discovery, and live provider
plugin augmentation on every Control UI list/refresh. None of this
is needed for a read-only UI listing.

Three changes:

1. Gateway catalog refresh now passes readOnly: true to loadModelCatalog.
2. In readOnly mode, skip augmentModelCatalogWithProviderPlugins — live
   provider discovery is explicit admin/background work, not a UI list
   operation.
3. Add a persisted models.json fast path: when readOnly is true, first
   try reading the existing models.json directly and converting
   providers.<provider>.models[] to catalog rows. Falls back to the
   full PI registry path if the file is missing or unreadable.

Observed improvement on a production install:
  loadGatewayModelCatalog: 967 entries / 4651ms → 89 entries / 8ms
  Live models.list during startup: ~18s → ~2s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(gateway): preserve full model catalog view

* fix(agents): preserve read-only catalog defaults

* fix(agents): preserve provider catalog defaults

---------

Co-authored-by: Marvinthebored <peter@lindsey.jp>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-05-02 22:48:55 -07:00
Vincent Koc
de24a05d6d test(gateway): satisfy shard splitter lint 2026-05-02 22:40:00 -07:00
Vincent Koc
833a42c253 test(gateway): split full-suite gateway-server shard 2026-05-02 22:40:00 -07:00
Vincent Koc
3ad0ad994a test(gateway): avoid stuck gateway-server fork shard 2026-05-02 22:40:00 -07:00
Vincent Koc
2e593d07f7 fix(plugins): preserve registry manifest fast path 2026-05-02 22:40:00 -07:00
Vincent Koc
d69d610bf0 fix(ui): guard app custom element registration 2026-05-02 22:40:00 -07:00
Bek
411df59916 fix(plugins): resolve official plugin install aliases
Resolve bare official external plugin IDs through the official catalog before generic npm fallback, preserving explicit npm semantics and catalog integrity through the hook-pack fallback.\n\nFixes #76373.\n\nThanks @bek91 and @vincentkoc.
2026-05-02 22:27:13 -07:00
Vincent Koc
f696be950b fix(gateway): keep runtime metadata on session rows 2026-05-02 22:10:35 -07:00
openclaw-clownfish[bot]
22748b1c36 feat(whatsapp): support native outbound mentions (#73961)
Merged via squash.

Prepared head SHA: bb1df9e681
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Reviewed-by: @BunsDev
2026-05-02 23:50:54 -05:00
Josh Avant
b1f8172867 fix(secretrefs): resolve external channel contracts (#76449) 2026-05-02 23:48:11 -05:00
pashpashpash
8f4eaa9c00 Stop heartbeat tool turns from asking for HEARTBEAT_OK (#76338)
* fix heartbeat tool prompt sentinel

* fix: remove agent runtime fallback config
2026-05-03 13:46:26 +09:00
Vincent Koc
775c27433f docs(changelog): credit oversized transcript fix 2026-05-02 21:44:25 -07:00
Vincent Koc
fda6ba3818 docs(changelog): credit lightweight session list fix 2026-05-02 21:42:15 -07:00
Vincent Koc
a7d3da71f7 test(gateway): expect lightweight session list rows 2026-05-02 21:37:06 -07:00
Vincent Koc
b1d7901a79 style(gateway): format lightweight session row path 2026-05-02 21:35:01 -07:00
Vincent Koc
5a9cf2c43f fix(gateway): preserve oversized transcript tree leaves 2026-05-02 21:34:36 -07:00
Marvinthebored
7fe4ba013f fix(gateway): add lightweight row path for sessions.list to reduce event-loop blocking
sessions.list calls buildGatewaySessionRow for every visible session,
running transcript usage fallback, display model inference, cost/context
recomputation, thinking level enumeration, agent runtime metadata, and
plugin extension projection per row. On installs with 30-50+ sessions
this blocks the event loop for 20-80+ seconds, starving Discord
heartbeats and Control UI RPCs.

Add skipTranscriptUsageFallback and lightweightListRow flags to
buildGatewaySessionRow. In lightweight mode, skip transcript usage
fallback, display model inference, cost/context recomputation, thinking
level options, agent runtime metadata, and plugin extension projection.
Use persisted entry fields directly for cost, tokens, and model identity.

listSessionsFromStoreAsync now passes both flags for bulk list rows.
Detail endpoints and single-row loads are unaffected.

Observed improvement on a production install (33 sessions):
sessions.list row construction dropped from ~82s to ~6s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 803879ec54)
2026-05-02 21:34:29 -07:00
Marvinthebored
4c9a557533 fix(gateway): skip oversized JSONL lines to prevent event-loop starvation
Large transcript JSONL records (multi-MB tool results, file content)
block the event loop via JSON.parse before truncation logic can skip
them. Add a 256 KiB line-size guard to parseTailTranscriptRecord and
extractUsageSnapshotFromTranscriptLine, and replace the full transcript
index scan in readSessionTitleFieldsFromTranscriptAsync with the
existing bounded sync reader.

Observed improvement on a production install (33 sessions):
chat.history dropped from 13-16s to ~1.2s, event loop utilization
from 0.999 to normal, steady-state CPU from ~100% to 0.2-0.3%.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-02 21:34:21 -07:00
Vincent Koc
d122a3492d fix(gateway): preserve oversized transcript tree leaves 2026-05-02 21:31:53 -07:00
Omar Shahine
1a5ad6104d docs(changelog): move file-transfer highlight to Unreleased
The 2026.4.30 changelog section maps to a beta-only tag with no public
release page, so the file-transfer highlight was invisible on the
releases page. Moving to Unreleased so it lands in the next published
release.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 04:30:54 +00:00
Val Alexander
2810f1219a fix(ui): surface compaction checkpoints in chat history
Fixes #76415.

- Explains compacted history boundaries in WebChat.
- Adds an Open checkpoints action for pre-compaction recovery.
- Updates WebChat docs and changelog with Thanks @BunsDev.
- Validated targeted UI tests, formatting/diff checks, Testbox changed gate, and exact-head CI.

Security: UI/docs/tests/styles-only change that reuses existing checkpoint APIs; no new dependencies, filesystem reads, workflow changes, or secret handling.
2026-05-02 23:29:28 -05:00
Val Alexander
85c000de1e fix: keep ClawHub publish dry-run preflight
Preserve the ClawHub CLI dry-run preflight while making the printed publish preview include CLAWHUB_WORKDIR. Add regression coverage that stubs the ClawHub CLI and verifies --dry-run is forwarded through the publish script.
2026-05-02 23:27:44 -05:00
Vincent Koc
b258c3fc65 fix(secretrefs): preserve exec resolver env 2026-05-02 21:21:51 -07:00
clawsweeper[bot]
d04a8976b1 fix(feishu): repair media-aware message dedupe (#76408)
Summary:
- The PR adds a Feishu-local media-aware dedupe-key helper, wires it through inbound receive/debounce/persistent/broadcast dedupe paths, adds Feishu regression coverage, and adds an Unreleased changelog entry.
- Reproducibility: yes. Source inspection shows a high-confidence path: two Feishu audio events for the same a ... _key` values collide in current-main receive and persistent dedupe before media parsing distinguishes them.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head c0229f8a48.
- Required merge gates passed before the squash merge.

Prepared head SHA: c0229f8a48
Review: https://github.com/openclaw/openclaw/pull/76408#issuecomment-4365292618

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: SymbolStar <24540119+SymbolStar@users.noreply.github.com>
2026-05-03 04:20:02 +00:00
Vincent Koc
a32fe82bd2 fix(gateway): preserve oversized transcript placeholders 2026-05-02 21:16:16 -07:00
Ayaan Zaidi
e8756d99ae Preserve delivered assistant replies in session repair (#76420)
Summary:
- The PR removes session-file repair's trailing-assistant disk trim, updates regression coverage, clarifies transcript hygiene docs, and adds a changelog entry for the Telegram/WebChat history loss fix.
- Reproducibility: yes. Current main has a clear source path: a normal trailing assistant JSONL record is popped by `repairSessionFileIfNeeded`, and the main-branch test suite asserts that deletion.

Automerge notes:
- PR branch already contained follow-up commit before automerge: docs(agents): clarify session repair preservation
- PR branch already contained follow-up commit before automerge: fix(agents): preserve delivered assistant replies in session repair

Validation:
- ClawSweeper review passed for head 66c187fd76.
- Required merge gates passed before the squash merge.

Prepared head SHA: 66c187fd76
Review: https://github.com/openclaw/openclaw/pull/76420#issuecomment-4365323320

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-03 04:04:11 +00:00
NVIDIAN
6a3f5d0b1f fix(cli): reject missing plugin ids before config writes (#73554)
Merged via squash.

Prepared head SHA: f0d3e61de2
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-05-03 11:49:14 +08:00
NVIDIAN
c81c0171cd fix(cli): block gateway-owned package updates (#75819)
Merged via squash.

Prepared head SHA: acdf73e6d0
Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-05-03 11:40:36 +08:00
Peter Steinberger
55c738ad4b build(protocol): refresh Swift gateway models 2026-05-03 04:37:08 +01:00
Peter Steinberger
0135071833 fix(xai): allow slower image edits 2026-05-03 04:34:21 +01:00
Josh Avant
ba31afb099 fix(discord): surface stalled transport health (#76327)
* fix(discord): surface stalled transport health

* fix(discord): surface stalled transport health

* fix(discord): surface stalled transport health

---------

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 22:33:19 -05:00
Peter Steinberger
9891f30422 test(e2e): relax kitchen-sink diagnostic exhaustiveness 2026-05-03 04:25:15 +01:00
buyitsydney
5f5e0a3633 fix(memory): retry reindex on socket errors (#76311)
Summary:
- The PR broadens memory-core's embedding retry classifier for socket/network errors, adds focused classifier tests, and adds an Unreleased changelog fix.
- Reproducibility: yes. Current main's retry classifier rejects the socket/fetch samples, and the reindex embedding path delegates to that classifier; a read-only regex probe confirmed the PR accepts the target samples.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(memory): retry reindex on socket errors

Validation:
- ClawSweeper review passed for head b4618c4532.
- Required merge gates passed before the squash merge.

Prepared head SHA: b4618c4532
Review: https://github.com/openclaw/openclaw/pull/76311#issuecomment-4364956064

Co-authored-by: buyitsydney <buyitsydney@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-03 03:21:06 +00:00
Peter Steinberger
31ed93ff58 test(codex): accept current status prose 2026-05-03 04:13:17 +01:00
Vincent Koc
23e0be355a fix(gateway): bound async session list transcript reads
Keep async sessions.list title/preview hydration on bounded transcript head/tail reads instead of full transcript index builds.

Validation:
- pnpm test:serial src/gateway/session-utils.fs.test.ts
- pnpm test:serial src/gateway/server.sessions.list-changed.test.ts
- pnpm exec oxfmt --check --threads=1 src/gateway/session-utils.fs.ts src/gateway/session-utils.fs.test.ts CHANGELOG.md
- OPENCLAW_TESTBOX=1 pnpm check:changed on tbx_01kqnw1j8japk3d8z24s6cv141
2026-05-02 20:06:20 -07:00
Peter Steinberger
bfee47d321 ci(release): satisfy release smoke lint 2026-05-03 04:05:04 +01:00
Peter Steinberger
468656bc1b ci(release): recover Windows packaged upgrade smoke 2026-05-03 04:02:09 +01:00
Vincent Koc
8151231e0f test(plugins): guard generated inventory coverage 2026-05-02 19:41:29 -07:00
Vincent Koc
2d3aa041c4 docs(plugins): clarify on-demand official inventory 2026-05-02 19:41:29 -07:00
Vincent Koc
9895236ebf test(e2e): surface update channel fixture install logs 2026-05-02 19:41:29 -07:00
Vincent Koc
7886b62c20 fix(release): use bundled channel in activation smoke 2026-05-02 19:41:16 -07:00
Vincent Koc
d002c2f0ee fix(release): raise plugin sdk api check heap 2026-05-02 19:41:16 -07:00
Vincent Koc
474b011ab6 docs(plugins): update npm-first reference pages 2026-05-02 19:41:16 -07:00
Vincent Koc
35d0db29ad docs(plugins): render npm-first install routes 2026-05-02 19:41:16 -07:00
Vincent Koc
82e7accf53 fix(onboarding): default dual-source installs to npm 2026-05-02 19:41:16 -07:00
Vincent Koc
ba3c0fc78e fix(plugins): roll back failed npm install debris 2026-05-02 19:41:16 -07:00
Vincent Koc
006bd56dd6 fix(plugins): trust reviewed official npm launch packages 2026-05-02 19:41:15 -07:00
Peter Steinberger
781c9b7ab0 fix(release): harden package update validation 2026-05-03 03:37:52 +01:00
Peter Steinberger
dda2cf4e73 test(qa-lab): use OpenAI plugin for mock image generation 2026-05-03 03:34:36 +01:00
Vincent Koc
994bfc1cb9 test(e2e): tolerate early runtime deps cleanup 2026-05-02 19:23:10 -07:00
clawsweeper[bot]
cb31616d88 fix(ui): clean up delete confirm popover listener (#76318)
Summary:
- The PR centralizes Control UI chat delete-confirm popover dismissal, adds listener-cleanup regression coverage and unit-UI test routing fixes, and records the fix in the changelog.
- Reproducibility: yes. Current-main source shows a high-confidence path: open the delete confirm, let `reques ... ncel, Delete, or same-button toggle; those paths remove the popover without removing the document listener.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(ui): clean up delete confirm popover listener
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): address review for automerge-openclaw-openclaw-7559…
- PR branch already contained follow-up commit before automerge: fix(clawsweeper): reconcile automerge-openclaw-openclaw-75590 with ma…
- PR branch already contained follow-up commit before automerge: fix(ui): repair delete confirm listener cleanup checks

Validation:
- ClawSweeper review passed for head 62240d8153.
- Required merge gates passed before the squash merge.

Prepared head SHA: 62240d8153
Review: https://github.com/openclaw/openclaw/pull/76318#issuecomment-4364990281

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Ricardo-M-L <69202550+Ricardo-M-L@users.noreply.github.com>
2026-05-03 02:21:10 +00:00
Tak Hoffman
f74983e442 fix(memory): preserve active recall tool agent context (#76380)
Summary:
- The PR threads the embedded run's trusted requester agent id into plugin tool context and memory-core tool availability/execution, adds regression tests, and records an Active Memory changelog fix.
- Reproducibility: yes. Current main shows Active Memory passing a synthetic `:active-memory:` session key plu ... ently derive memory scope from the session key; I did not run the regression test in this read-only review.

Automerge notes:
- No ClawSweeper repair was needed after automerge opt-in.

Validation:
- ClawSweeper review passed for head 33ab3d7fc7.
- Required merge gates passed before the squash merge.

Prepared head SHA: 33ab3d7fc7
Review: https://github.com/openclaw/openclaw/pull/76380#issuecomment-4365186657

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-05-03 02:16:48 +00:00
Peter Steinberger
31161abd40 chore(release): bump version to 2026.5.3 2026-05-03 03:08:47 +01:00
clawsweeper[bot]
c149046c45 fix(gateway,agent): only enforce session sendPolicy=deny when delivering (#76317)
Summary:
- This PR gates gateway `agent` send-policy rejection on `request.deliver === true`, adds denied non-delivery  ... plicit-delivery regression coverage, updates a gateway chat expectation, and adds a #73381 changelog entry.
- Reproducibility: yes. from source inspection: current main resolves `sendPolicy` and rejects before delivery ... agent` request with `deliver` omitted or false. I did not run local tests because this review is read-only.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(gateway,agent): only enforce session sendPolicy=deny when delivering

Validation:
- ClawSweeper review passed for head 5cfcb1c584.
- Required merge gates passed before the squash merge.

Prepared head SHA: 5cfcb1c584
Review: https://github.com/openclaw/openclaw/pull/76317#issuecomment-4364987993

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: wenxu007 <270593229+wenxu007@users.noreply.github.com>
2026-05-03 02:05:23 +00:00
Vincent Koc
3d64fcaf1f test(plugins): align persisted registry snapshot assertion 2026-05-02 18:55:47 -07:00
Vincent Koc
a89b0dda2f docs(config): refresh generated baseline hash 2026-05-02 18:50:23 -07:00
Vincent Koc
d520fa6229 test(e2e): stop probing ClawHub for npm installs 2026-05-02 18:43:01 -07:00
clawsweeper[bot]
00de585574 fix(gateway): preserve err.stack when chat.send/agent attachment parsing fails (#76351)
Summary:
- Adds stack-preserving gateway error logging for `chat.send` and agent attachment parse/stage failures, focused tests, and an Unreleased changelog entry.
- Reproducibility: yes. for the diagnostic gap: current main shows both affected catches returning `String(err ... g `Error` or `MediaOffloadError` values. I did not reproduce the separate iPad/Tailscale RangeError itself.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(gateway): preserve err.stack when chat.send/agent attachment pars…

Validation:
- ClawSweeper review passed for head 0e9bd18b31.
- Required merge gates passed before the squash merge.

Prepared head SHA: 0e9bd18b31
Review: https://github.com/openclaw/openclaw/pull/76351#issuecomment-4365116612

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: keen0206 <233564226+keen0206@users.noreply.github.com>
2026-05-03 01:40:27 +00:00
Vincent Koc
4ae9ae12b6 test(e2e): fix kitchen sink crabbox coverage (#76287)
* test(e2e): fix kitchen sink crabbox coverage

* test(e2e): update kitchen sink expected diagnostics

* fix(plugins): harden registry and package gates

* fix(plugins): load lazy tool middleware snapshots

* fix(ci): satisfy crabbox branch gates

* fix(plugins): await guarded fetch cleanup
2026-05-02 18:39:26 -07:00
Vincent Koc
d7dbf11504 fix(plugins): preserve npm plugin installs across repairs 2026-05-02 18:31:59 -07:00
clawsweeper[bot]
e8df05ed4f fix(slack): enable preview streaming in flat DMs (replyToMode: off) (#76330)
Summary:
- The PR enables Slack draft preview streaming for flat DMs in all non-off modes, updates Slack streaming tests/docs/config metadata/changelog, and refreshes small guard baselines.
- Reproducibility: yes. source-reproducible on current main: the helper returns false for `mode: "partial"` in ...  current test asserts that disabled path. I did not run tests because this review was explicitly read-only.

Automerge notes:
- Ran the ClawSweeper repair loop before final review.
- Included post-review commit in the final squash: fix(slack): enable preview streaming in flat DMs (replyToMode: off)
- Included post-review commit in the final squash: fix(clawsweeper): address review for automerge-openclaw-openclaw-5654…

Validation:
- ClawSweeper review passed for head 52e5d74ef9.
- Required merge gates passed before the squash merge.

Prepared head SHA: 52e5d74ef9
Review: https://github.com/openclaw/openclaw/pull/76330#issuecomment-4365017023

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: bob <637186+HangGlidersRule@users.noreply.github.com>
2026-05-03 01:30:36 +00:00
Vincent Koc
9765a5777c fix(doctor): defer channel plugin repair during updates 2026-05-02 18:29:57 -07:00
Jason
53bd718a1a fix(cli): avoid model warmup for message actions (#76312)
Summary:
- The PR skips eager context-window warmup for `openclaw message`, forwards Discord/Telegram execution-mode de ... reuses caller-owned manifest metadata during config materialization, and adds tests plus a changelog entry.
- Reproducibility: yes. Source inspection on current main shows `openclaw message` is still eligible for eager context-window warmup and the Discord/Telegram wrappers still drop the gateway execution-mode declarations.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix: type message action routing fallbacks
- PR branch already contained follow-up commit before automerge: docs: credit message latency fix contributor

Validation:
- ClawSweeper review passed for head 9606bb27d5.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9606bb27d5
Review: https://github.com/openclaw/openclaw/pull/76312#issuecomment-4364958708

Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-05-03 01:26:00 +00:00
Peter Steinberger
13dc14d43e chore(release): update macOS appcast for 2026.5.2 2026-05-03 02:15:13 +01:00
Peter Steinberger
e8f13c625e fix(cli): request admin scope for admin device approvals 2026-05-03 01:38:24 +01:00
Vincent Koc
e1a73d380d test(plugins): require reviewed npm critical findings 2026-05-02 17:35:39 -07:00
Vincent Koc
6548825083 fix(scanner): ignore full-line comments for source rules 2026-05-02 17:35:39 -07:00
Vincent Koc
52cd76a9e2 fix(providers): isolate model discovery test env guards 2026-05-02 17:35:39 -07:00
Vincent Koc
4be4c475ea fix(scanner): ignore benign member exec matches 2026-05-02 17:35:38 -07:00
Vincent Koc
3c8de6eb72 fix(qqbot): keep platform debug logging import 2026-05-02 17:35:38 -07:00
Vincent Koc
8409dbddd6 test(plugins): avoid release script imports in npm scan 2026-05-02 17:35:38 -07:00
Vincent Koc
85520f664d fix(qqbot): remove native ffmpeg subprocess fallback 2026-05-02 17:35:38 -07:00
Vincent Koc
d1c5e750ed fix(tlon): drop bundled cli tool wrapper 2026-05-02 17:35:37 -07:00
Vincent Koc
366f1ea706 fix(msteams): use manual delegated oauth setup 2026-05-02 17:35:37 -07:00
Vincent Koc
eb907508e8 test(ci): keep npm scan on plugin prerelease 2026-05-02 17:35:37 -07:00
Vincent Koc
8ec589c9be test(plugins): scan publishable npm packages 2026-05-02 17:35:37 -07:00
Vincent Koc
f2e342b82e fix(doctor): defer missing plugin payload repair during update 2026-05-02 17:34:46 -07:00
clawsweeper[bot]
004e871656 fix(cron): route CLI-runtime cron models through compatible backend (#76319)
Summary:
- The PR routes isolated cron executions through compatible configured CLI runtimes, threads agent identity into cron model selection, adds cron regression coverage, and records a changelog fix.
- Reproducibility: yes. The source PR describes cron jobs for agents with agentRuntime.id="claude-cli" selecti ... howing those canonical Anthropic attempts execute through claude-cli while OpenAI overrides stay on OpenAI.

ClawSweeper fixups:
- Included follow-up commit: fix(cron): route CLI-runtime cron models through compatible backend
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7584…
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head ba2781de8f.
- Required merge gates passed before the squash merge.

Prepared head SHA: ba2781de8f
Review: https://github.com/openclaw/openclaw/pull/76319#issuecomment-4364991459

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: vishutdhar <68405187+vishutdhar@users.noreply.github.com>
2026-05-03 00:31:31 +00:00
Vincent Koc
06cdb17ad2 test(memory): keep promotion signal fixture inside age window 2026-05-02 17:21:59 -07:00
Vincent Koc
4026af1a8b fix(doctor): reinstall missing configured plugin payloads 2026-05-02 17:21:07 -07:00
clawsweeper[bot]
10c9200f75 [AI-assisted] fix(feishu): probe status with account credentials (#76321)
Summary:
- The PR resolves Feishu setup/status probes through the selected/default account, adds a multi-account regression test, and adds an Unreleased changelog fix entry.
- Reproducibility: yes. Current main can be checked by calling the Feishu setup-status adapter with a config t ... hannels.feishu.accounts.<id>; the status path passes accountId but Feishu currently ignores it for probing.

ClawSweeper fixups:
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7406…
- Included follow-up commit: [AI-assisted] fix(feishu): probe status with account credentials
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head 427e8e8b07.
- Required merge gates passed before the squash merge.

Prepared head SHA: 427e8e8b07
Review: https://github.com/openclaw/openclaw/pull/76321#issuecomment-4364994746

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: brokemac79 <255583030+brokemac79@users.noreply.github.com>
2026-05-03 00:19:36 +00:00
Vincent Koc
bcfa5bc32b test(active-memory): avoid wall-clock fragile terminal recall assertions 2026-05-02 17:11:55 -07:00
Val Alexander
a81c7f5d32 fix(pr): prefer verified GitHub commits for prep pushes (#76323) thanks @BunsDev
Route maintainer prepare pushes through GitHub createCommitOnBranch by default so PR repair branches do not accumulate unsigned git-protocol commits. Keeps git-protocol pushes behind an explicit override.
2026-05-02 19:11:04 -05:00
clawsweeper[bot]
afe42fc977 fix(e2e): escape Windows stale update import regex (#75315) thanks @steipete
Fix the Windows stale-import guard regex used by the Parallels npm update smoke path, with related maintainer-flow and regression-test cleanup preserved on a verified branch.
2026-05-02 19:10:44 -05:00
Paul Frederiksen
f30dc0aeb4 fix(cron): persist manual run ids in history (#76288)
Summary:
- The PR carries manual `cron.run` acknowledgement IDs into finished cron events and `cron.runs` history, upda ...  surfaces, adds regression coverage, refreshes the SDK baseline hash, and records the fix in the changelog.
- Reproducibility: yes. Current main can be reproduced by source inspection: `cron.run` returns a `manual:...` ... r path omits it; the PR adds targeted assertions for the missing correlation and the task-ledger invariant.

ClawSweeper fixups:
- Included follow-up commit: chore(protocol): update generated cron models
- Included follow-up commit: chore(cron): document manual run id protocol surface
- Included follow-up commit: Preserve cron task ledger run IDs

Validation:
- ClawSweeper review passed for head 04ce879858.
- Required merge gates passed before the squash merge.

Prepared head SHA: 04ce879858
Review: https://github.com/openclaw/openclaw/pull/76288#issuecomment-4364868383

Co-authored-by: Paul Frederiksen <paul@paulfrederiksen.com>
2026-05-03 00:06:32 +00:00
clawsweeper[bot]
cf46dc54ff fix(slack): ignore no_reaction in remove helpers (#76320)
Summary:
- The PR adds a Slack `no_reaction` guard to `removeSlackReaction`, routes `removeOwnSlackReactions` through that helper, adds reaction tests, and records the fix in the changelog.
- Reproducibility: yes. A mocked Slack `WebClient` whose `reactions.remove` rejects with `{ data: { error: "no ... es current-main propagation in `removeSlackReaction` and the list/remove race in `removeOwnSlackReactions`.

ClawSweeper fixups:
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7630…

Validation:
- ClawSweeper review passed for head 1211ce06d3.
- Required merge gates passed before the squash merge.

Prepared head SHA: 1211ce06d3
Review: https://github.com/openclaw/openclaw/pull/76320#issuecomment-4364991477

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: HollyChou <128659251+Hollychou924@users.noreply.github.com>
2026-05-03 00:05:23 +00:00
Vincent Koc
4bc6b9d7cf fix(doctor): repair phantom configured plugin installs 2026-05-02 17:04:00 -07:00
Peter Steinberger
c8ab22997b fix: reset turns bypass active queue modes (#74144) (thanks @yelog) 2026-05-03 00:54:44 +01:00
Vincent Koc
4c33f7d751 test(e2e): keep matrix survivor installs internal 2026-05-02 16:52:04 -07:00
Vincent Koc
76fb2c4b87 test(e2e): accept external discord survivor installs 2026-05-02 16:51:28 -07:00
Omar Shahine
f30aca95c3 docs(changelog): add 2026.4.30 highlight for file-transfer plugin
The bundled file-transfer plugin landed in v2026.4.30-beta.1 via
PR #74742 but was missing from the 2026.4.30 changelog section.
Adds a Highlights bullet calling out the four agent tools, default-deny
per-node path policy, refused-by-default symlink traversal, and 16 MB
round-trip ceiling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 23:49:12 +00:00
mrinalgaur2005
2584d0d415 fix(gateway): preserve every client tool call when agent calls multiple tools per turn
Fixes #52288.

Co-authored-by: Mrinal Gaur <mrinalgaur2005@gmail.com>
2026-05-03 00:47:46 +01:00
Shakker
f7549079ce fix: prune legacy plugin runtime deps on install 2026-05-03 00:39:40 +01:00
Val Alexander
05c9492bff fix: reduce WebUI session latency churn (#76277) thanks @BunsDev
Reduce WebUI/Gateway latency churn by avoiding redundant session reloads, carrying session keys through transcript update events, and deferring explicit media provider discovery. Includes changelog attribution and closes the referenced runtime latency issues.
2026-05-02 18:39:06 -05:00
Vincent Koc
1c4d3e2f4f test(e2e): accept bundled configured plugins 2026-05-02 16:35:29 -07:00
MkDev11
9ef7f241f6 fix: keep media provider inventory internal (#75550)
Summary:
- The branch removes the compact image/video provider-inventory output bypass, adds media handler regression tests for hidden and verbose modes, and adds an Unreleased changelog fix entry.
- Reproducibility: yes. On current main, a synthetic image_generate or video_generate list result with details ... ut false reaches emitToolOutput; the existing media handler test locks in that old video_generate behavior.

ClawSweeper fixups:
- Included follow-up commit: chore: rerun ci
- Included follow-up commit: chore: move changelog entry below media fixes

Validation:
- ClawSweeper review passed for head 56069df903.
- Required merge gates passed before the squash merge.

Prepared head SHA: 56069df903
Review: https://github.com/openclaw/openclaw/pull/75550#issuecomment-4358608888

Co-authored-by: mkdev11 <MkDev11@users.noreply.github.com>
2026-05-02 23:34:44 +00:00
Vincent Koc
7be0d6e76d fix(ci): pass upgrade survivor matrix to package planning 2026-05-02 16:33:57 -07:00
pashpashpash
ad0e1a0d5d test: show bootstrap context in prompt snapshots (#76302) 2026-05-03 08:29:34 +09:00
Vincent Koc
a1054fbe1b test(e2e): allow npm configured plugin installs 2026-05-02 16:22:29 -07:00
Vincent Koc
282b9fe616 fix(feishu): split timeout env parsing from client 2026-05-02 16:20:54 -07:00
Vincent Koc
5ed7f1fd26 fix: trusted installs 2026-05-02 16:14:52 -07:00
Vincent Koc
dd43caa27a Fix Trinity main-session compatibility mismatch (#73388)
Summary:
- The PR marks Arcee Trinity Large Thinking tool-incompatible in catalog/config/runtime paths, updates Arcee docs and changelog, and adds provider regression tests.
- Reproducibility: yes. The linked reports provide concrete main-session failure logs, and current main still exposes Trinity without `compat.supportsTools:false` while the runtime sends tools unless that flag is false.

ClawSweeper fixups:
- Included follow-up commit: fix(arcee): disable Trinity tools in main sessions
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7338…
- Included follow-up commit: fix(arcee): repair Trinity main-session compatibility

Validation:
- ClawSweeper review passed for head 4c669d66cb.
- Required merge gates passed before the squash merge.

Prepared head SHA: 4c669d66cb
Review: https://github.com/openclaw/openclaw/pull/73388#issuecomment-4338585215

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 23:10:13 +00:00
Peter Steinberger
68359cacbf feat(webchat): add server-side dictation (#76021)
Summary:
- This PR adds WebChat server-side dictation through a new authenticated `chat.transcribeAudio` Gateway RPC, MediaRecorder composer controls, docs/changelog updates, and focused gateway/UI tests.
- Reproducibility: yes. Current main reproduces the missing feature by inspection: the Gateway method list, write scopes, docs, and WebChat voice-control test have no `chat.transcribeAudio` server-dictation path.

ClawSweeper fixups:
- Included follow-up commit: feat(webchat): add server-side dictation
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7602…

Validation:
- ClawSweeper review passed for head 850571380a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 850571380a
Review: https://github.com/openclaw/openclaw/pull/76021#issuecomment-4363514226

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 23:09:23 +00:00
Peter Steinberger
15bbf4f2f3 fix(channels): clarify remote install hints
Clarify remote channel install hints and align onboarding install source labels with progress-bar coverage.
2026-05-02 15:57:41 -07:00
Peter Steinberger
9a899a29b8 test(tooling): align plugin prerelease expectations 2026-05-02 23:53:41 +01:00
Peter Steinberger
550d6f5c43 fix: allow beta gateway refresh for same release config 2026-05-02 23:52:37 +01:00
Peter Steinberger
e857c795a8 fix(plugins): allow Discord install repair 2026-05-02 23:48:54 +01:00
Val Alexander
57d6e63f30 fix(gateway): keep requested plugin tools invokable (#76285) thanks @BunsDev
Keep directly requested plugin tools invokable under restrictive profiles, with the changelog update included on the verified branch.
2026-05-02 17:48:11 -05:00
Peter Steinberger
9404a4ddcd fix: stop bonjour stuck-announcing churn 2026-05-02 23:40:49 +01:00
Peter Steinberger
816f3f11a1 docs: remove alpha release references 2026-05-02 23:40:23 +01:00
Vincent Koc
dfce72d136 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  test(docker): expect discord onboard package lane
2026-05-02 15:37:24 -07:00
Peter Steinberger
9ef7c024c8 test(docker): expect discord onboard package lane 2026-05-02 23:36:43 +01:00
Vincent Koc
595bb6f240 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  Rename Codex runtime prompt snapshot directory (#76274)
  fix(plugins): canonicalize install provenance paths
2026-05-02 15:36:40 -07:00
pashpashpash
bcb2476ae7 Rename Codex runtime prompt snapshot directory (#76274)
* test: rename Codex runtime prompt snapshots

* test: refresh prompt snapshots with node24

* test: format prompt snapshot markdown in generator
2026-05-03 07:34:59 +09:00
Vincent Koc
e3d76d2e1f fix(channels): keep matrix and mattermost bundled 2026-05-02 15:32:29 -07:00
Peter Steinberger
dc005e1bcc fix(plugins): canonicalize install provenance paths 2026-05-02 23:32:00 +01:00
Vincent Koc
c8fa0fd1c9 fix(onboarding): surface official plugin installs 2026-05-02 15:26:48 -07:00
Vincent Koc
7a54076770 test(plugins): avoid kitchen sink config drift 2026-05-02 15:25:17 -07:00
Vincent Koc
a8f62725e5 test(plugins): pin kitchen sink npm fixture 2026-05-02 15:25:17 -07:00
Vincent Koc
1417008ff7 test(plugins): harden package plugin e2e lanes 2026-05-02 15:25:17 -07:00
clawsweeper[bot]
ae82a39150 fix(active-memory): fast-fail stalled recall paths (#76183)
Summary:
- This PR adds Active Memory transcript polling to fast-fail terminal zero-hit or unavailable recall tool results, filters timeout boilerplate, extends focused regressions, and adds a changelog fix entry.
- Reproducibility: yes. The PR includes focused regressions that reproduce terminal zero-hit search, unavailab ... rch, non-empty `details.results` with `debug.hits: 0`, memory_get misses, and timeout boilerplate behavior.

ClawSweeper fixups:
- Included follow-up commit: fix(active-memory): fast-fail stalled recall paths
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7576…
- Included follow-up commit: fix(clawsweeper): reconcile automerge-openclaw-openclaw-75761 with ma…
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head e5ea3f1a7a.
- Required merge gates passed before the squash merge.

Prepared head SHA: e5ea3f1a7a
Review: https://github.com/openclaw/openclaw/pull/76183#issuecomment-4364369591

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: codexGW <9350182+codexGW@users.noreply.github.com>
2026-05-02 22:23:02 +00:00
Peter Steinberger
9fdc0e7030 fix(codex): forward workspace bootstrap context 2026-05-02 23:21:29 +01:00
Vincent Koc
1f03b629be chore(config): refresh config docs baseline 2026-05-02 15:19:57 -07:00
Peter Steinberger
192e750035 fix: repair stale configured channel plugins 2026-05-02 23:12:11 +01:00
Peter Steinberger
123a507fa2 fix(ci): narrow active task restart blockers 2026-05-02 23:08:56 +01:00
Peter Steinberger
7f83ba8ddf fix: reserve auth CLI root from plugin allowlist gating 2026-05-02 23:07:25 +01:00
Peter Steinberger
2a7d6f6f13 fix(ci): satisfy lint after restart controls 2026-05-02 23:05:26 +01:00
Peter Steinberger
15dc7d3f57 test(release): align pack checks with externalized plugins 2026-05-02 23:00:04 +01:00
Peter Steinberger
e5f8c5195f fix(plugins): detect stale persisted registry metadata 2026-05-02 23:00:04 +01:00
Vincent Koc
00ad13b599 fix(plugins): use default tags for official plugin installs 2026-05-02 14:47:53 -07:00
Peter Steinberger
2fd1e7b32d fix: normalize LM Studio binary reasoning efforts 2026-05-02 22:46:44 +01:00
Vincent Koc
9f8744b140 docs(changelog): note beta upgrade fixes 2026-05-02 14:45:28 -07:00
Vincent Koc
f6f8d74419 fix(gateway): expose restart drain controls 2026-05-02 14:43:59 -07:00
Vincent Koc
624eaf5d4a docs(local-models): add hardware floor + backend picker, restructure stricter backend section as numbered triage flow 2026-05-02 14:43:51 -07:00
Vincent Koc
3dbf31885c docs(experimental): explain local model lean mode for operators 2026-05-02 14:43:51 -07:00
pashpashpash
9e57b98bb9 Improve Codex happy path prompt snapshots (#76229)
* test: add Codex model prompt layers to snapshots

* test: keep rendered prompt snapshots raw

* test: check prompt snapshot drift in ci

* test: prefer codex model cache for prompt fixtures

* fix: exclude publishable plugin dist from core package
2026-05-03 06:40:20 +09:00
Vincent Koc
5d6445417f fix(doctor): repair effective plugin installs 2026-05-02 14:40:03 -07:00
Peter Steinberger
c5013eaf43 docs: complete source-backed docs sweep 2026-05-02 22:37:01 +01:00
Vincent Koc
343e4723d8 fix(discord): persist slash command deploy hash 2026-05-02 14:35:57 -07:00
Vincent Koc
ce04ad83fa fix(status): trust live channel credential state 2026-05-02 14:33:23 -07:00
Vincent Koc
0fbf4636f5 fix(plugins): suppress mirrored provider env warnings 2026-05-02 14:31:32 -07:00
Vincent Koc
d68ca425bd fix(status): report beta registry channel 2026-05-02 14:30:18 -07:00
Peter Steinberger
cb9a97f211 test(ui): update home-relative media expectation 2026-05-02 22:30:03 +01:00
Vincent Koc
dc6d9973e9 fix(plugins): tolerate missing clawhub artifact resolver 2026-05-02 14:28:20 -07:00
Vincent Koc
871cd475af fix(status): show configured channels without gateway 2026-05-02 14:28:20 -07:00
Vincent Koc
0841bcdc01 fix(config): reject unavailable provider refs 2026-05-02 14:26:02 -07:00
Peter Steinberger
3312ce5acb fix: support home-relative media paths 2026-05-02 22:23:45 +01:00
Vincent Koc
24d0562d7d fix(doctor): preserve third-party plugin dependencies 2026-05-02 14:21:42 -07:00
Peter Steinberger
3afd4fdeeb fix(release): exclude publishable plugin dist trees 2026-05-02 22:19:28 +01:00
Peter Steinberger
282051a14f fix: install disabled external search providers 2026-05-02 22:14:37 +01:00
Peter Steinberger
929df0f556 fix(agents): lower session repair success logging 2026-05-02 22:09:42 +01:00
Vincent Koc
cd710bcfb2 fix(plugins): clarify unavailable clawhub artifacts 2026-05-02 14:06:50 -07:00
Peter Steinberger
fd83c49cff docs: update plugin npm distribution guidance 2026-05-02 22:00:37 +01:00
Vincent Koc
46d4238425 fix(plugins): install external search plugins during onboarding 2026-05-02 13:58:07 -07:00
Peter Steinberger
63a3a0e1ec fix: recover missing plugin payloads during update 2026-05-02 21:53:37 +01:00
Peter Steinberger
47375fd6dc fix: install codex runtime plugin during doctor 2026-05-02 21:46:28 +01:00
Peter Steinberger
2dfa4b082a docs: sync docs with source truth 2026-05-02 21:45:03 +01:00
Vincent Koc
4655ee803d Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  ci: use npm token for plugin publishes
2026-05-02 13:37:43 -07:00
Vincent Koc
94521a1cdd fix(plugins): satisfy external catalog lint 2026-05-02 13:37:10 -07:00
Peter Steinberger
0dafc37e57 ci: use npm token for plugin publishes 2026-05-02 21:37:00 +01:00
Vincent Koc
a53be2d2ce Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  Wizard: bound hatch TUI timeout (#76241)
  fix(cli): reject codex simple-completion probes
  fix: memoize plugin descriptor config keys (#76240)
  fix(heartbeat): make phase scheduling active-hours-aware (#75487) (#75597)
2026-05-02 13:32:51 -07:00
Vincent Koc
d4268b1b2b fix(plugins): catalog externalized npm installs 2026-05-02 13:30:07 -07:00
Josh Avant
86cc29274e Wizard: bound hatch TUI timeout (#76241)
* Wizard: bound hatch TUI timeout

* Scripts: avoid control regex in hatch stall repro

* Scripts: remove hatch stall repro harness

* Changelog: note hatch timeout fix

* Changelog: use PR reference for hatch timeout
2026-05-02 15:28:32 -05:00
Peter Steinberger
292bbcc292 fix(cli): reject codex simple-completion probes 2026-05-02 21:27:54 +01:00
Josh Avant
b779c45a78 fix: memoize plugin descriptor config keys (#76240) 2026-05-02 15:25:00 -05:00
Alex Knight
10448a0ad1 fix(heartbeat): make phase scheduling active-hours-aware (#75487) (#75597)
Summary:
- The PR adds active-hours-aware heartbeat phase seeking, wires runner scheduling and config reloads through it, adds scheduler/e2e coverage, and records the user-facing fix in the changelog.
- Reproducibility: yes. Current main can be reproduced with a `4h` heartbeat and an `Asia/Shanghai` active-hours window during a quiet-hours restart: main arms raw UTC-phase slots and only skips when the timer fires.

ClawSweeper fixups:
- Included follow-up commit: fix(heartbeat): recompute schedule when activeHours config changes vi…
- Included follow-up commit: fix(heartbeat): add iteration cap to active-hours seek + edge-case tests
- Included follow-up commit: chore: clean up redundant code comments
- Included follow-up commit: fix(heartbeat): make phase scheduling active-hours-aware (#75487)
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7559…

Validation:
- ClawSweeper review passed for head 02a1283c93.
- Required merge gates passed before the squash merge.

Prepared head SHA: 02a1283c93
Review: https://github.com/openclaw/openclaw/pull/75597#issuecomment-4358941180

Co-authored-by: Alex Knight <aknight@atlassian.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 20:17:53 +00:00
Vincent Koc
0fad53a192 feat(whatsapp): support newsletter targets in message tool (#73393)
Summary:
- Adds WhatsApp `@newsletter` target normalization, outbound allowFrom bypass, channel session routing, composing-presence suppression, docs/changelog updates, and focused tests.
- Reproducibility: yes. Source inspection on current main shows a `120363401234567890@newsletter` target normalizes to null before outbound send, and the current session route has only direct/group semantics.

ClawSweeper fixups:
- Included follow-up commit: fix(clownfish): address review for ghcrawl-156943-autonomous-smoke (1)
- Included follow-up commit: feat(whatsapp): support newsletter targets in message tool

Validation:
- ClawSweeper review passed for head 9ff3f88202.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9ff3f88202
Review: https://github.com/openclaw/openclaw/pull/73393#issuecomment-4338584612

Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 20:09:31 +00:00
Vincent Koc
a1dc8c0663 fix(gateway): reuse subagent registry snapshot in session listing (#75019)
Summary:
- The branch reuses a request-scoped subagent registry read index across Gateway `sessions.list` `spawnedBy` filtering and row enrichment, with focused regression tests and a changelog entry.
- Reproducibility: yes. On current main, `spawnedBy` filtering still calls registry read helpers independently ... ce inspection gives a high-confidence reproduction path for snapshot drift during active registry mutation.

ClawSweeper fixups:
- Included follow-up commit: fix(gateway): reuse subagent registry snapshot in session listing

Validation:
- ClawSweeper review passed for head 23ae624374.
- Required merge gates passed before the squash merge.

Prepared head SHA: 23ae624374
Review: https://github.com/openclaw/openclaw/pull/75019#issuecomment-4351613760

Co-authored-by: anyech <anyech@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 20:07:10 +00:00
Vincent Koc
08ce17c33d fix(gateway): surface unreachable status diagnostics (#74691)
Summary:
- The PR adds a `no_gateway_reachable` gateway probe warning, passes discovery count into warning construction, adds focused coverage, and updates the changelog.
- Reproducibility: yes. for the missing diagnostic: current main can reach an all-unreachable, zero-discovery  ... -count input. No for the underlying #49012 freeze itself; that remains a separate root-cause investigation.

ClawSweeper fixups:
- Included follow-up commit: fix(gateway): surface unreachable status diagnostics

Validation:
- ClawSweeper review passed for head 50fb29c359.
- Required merge gates passed before the squash merge.

Prepared head SHA: 50fb29c359
Review: https://github.com/openclaw/openclaw/pull/74691#issuecomment-4348514748

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 20:00:29 +00:00
Vincent Koc
b9eb31b54c ci: fold parity into QA release validation (#74622)
Summary:
- The PR deletes the standalone `Parity gate` workflow, renames QA parity wording from gate to lane, routes docs toward QA/release validation, and adjusts the Docker E2E boundary guard for package-backed live lanes.
- Reproducibility: not applicable. as a CI/docs refactor. The high-confidence review path is static comparison of the repaired PR diff against current workflow/docs code plus exact-head check status.

ClawSweeper fixups:
- Included follow-up commit: ci: fold parity into QA release validation
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head 3482654058.
- Required merge gates passed before the squash merge.

Prepared head SHA: 3482654058
Review: https://github.com/openclaw/openclaw/pull/74622#issuecomment-4359168336

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 19:57:15 +00:00
Peter Steinberger
3b1a020eba fix: repair stale gateway service on start 2026-05-02 20:56:35 +01:00
Peter Steinberger
9eb79bcf99 fix(mattermost): load config metadata from config surface 2026-05-02 20:48:14 +01:00
Peter Steinberger
7621208d4e fix: preserve terminal session lifecycle state 2026-05-02 20:41:20 +01:00
Peter Steinberger
4a7e60d05b fix(mattermost): expose bundled channel config metadata 2026-05-02 20:38:03 +01:00
Peter Steinberger
ab93e428c8 test: exercise Clownfish any-PR automerge opt-in (#74126)
Summary:
- The PR consists of one empty commit intended to live-test Clownfish any-PR automerge adoption and does not change repository files.
- Reproducibility: not applicable. this is an operational smoke PR rather than a code bug. The provided timeli ... clownfish automerge` attempts and bot responses, while the PR itself has no file diff to reproduce locally.

ClawSweeper fixups:
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head 03dde6b00a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 03dde6b00a
Review: https://github.com/openclaw/openclaw/pull/74126#issuecomment-4341323374

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-02 19:36:19 +00:00
Vincent Koc
5e1529c48b fix(tests): satisfy codex plugin smoke lint 2026-05-02 12:32:24 -07:00
Vincent Koc
838dd3a07b test(plugins): type persisted bridge fixtures 2026-05-02 12:29:34 -07:00
Peter Steinberger
42fed1f205 docs: clarify setup next steps 2026-05-02 20:27:31 +01:00
Vincent Koc
44f3b5ad89 fix(plugins): keep externalized launch installs on npm 2026-05-02 12:24:48 -07:00
Peter Steinberger
40b8cb5837 test: route cli backend live refs through runtime 2026-05-02 20:19:39 +01:00
Peter Steinberger
f969ae45a3 fix(plugins): follow beta channel for plugin updates 2026-05-02 20:19:03 +01:00
Peter Steinberger
154512f2e1 test: support published beta codex plugin smoke 2026-05-02 20:14:45 +01:00
Peter Steinberger
23ac9ccfd5 test: add codex npm plugin Docker live proof 2026-05-02 20:08:48 +01:00
Peter Steinberger
66db189962 docs(i18n): add plugin management glossary labels 2026-05-02 20:05:53 +01:00
Peter Steinberger
f8a5979469 docs(plugins): add management quickstart 2026-05-02 20:04:03 +01:00
Vincent Koc
cf21bcf9bf fix(plugins): keep bare installs on npm for launch 2026-05-02 12:00:06 -07:00
Peter Steinberger
a7a6d24147 fix(plugins): satisfy dependency status lint 2026-05-02 19:58:19 +01:00
Peter Steinberger
4a3ad3963b feat(plugins): report dependency install state 2026-05-02 19:58:19 +01:00
Vincent Koc
f4e70ec333 fix(plugins): normalize clawhub resolver metadata 2026-05-02 11:51:26 -07:00
Vincent Koc
559bf7df1f fix(plugins): accept legacy clawhub api ranges 2026-05-02 11:50:56 -07:00
Mariano
3b347d1c7e Add agent visibility to skills check (#75983)
Merged via squash.

Prepared head SHA: 63bac4340f
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-05-02 20:50:38 +02:00
Vincent Koc
91cc1df128 fix(plugins): normalize clawhub artifact resolver types 2026-05-02 11:47:47 -07:00
Peter Steinberger
4b4dfe429d ci: expand release upgrade baselines 2026-05-02 19:46:00 +01:00
Peter Steinberger
e18a383ff8 fix(config): preserve authored tilde paths on write 2026-05-02 19:42:58 +01:00
Vincent Koc
76c327c096 fix(plugins): remove unsupported bundle metadata 2026-05-02 11:42:17 -07:00
Vincent Koc
62aa4df3da fix(plugins): use clawhub artifact resolver for installs 2026-05-02 11:41:50 -07:00
Peter Steinberger
c3c2c31168 ci: update codex cli live smoke 2026-05-02 19:37:51 +01:00
Vincent Koc
a3f2f3a4eb feat(plugins): type clawhub security reports 2026-05-02 11:34:44 -07:00
Mariano
ba5723d38b [codex] Fix Codex OAuth status auth label (#76197)
Merged via squash.

Prepared head SHA: a0168232b5
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
2026-05-02 20:34:00 +02:00
Vincent Koc
38990c0e09 docs(plugins): clarify readiness-gated clawhub installs 2026-05-02 11:29:14 -07:00
Vincent Koc
e9e7c4325f fix(plugins): gate bare clawhub installs on readiness 2026-05-02 11:25:39 -07:00
Vincent Koc
e06e2d8c4c test(plugins): cover missing plugin uninstall teardown 2026-05-02 11:19:12 -07:00
Vincent Koc
f6aedd33e5 test(plugins): restore npm registry for live clawhub 2026-05-02 11:16:08 -07:00
Vincent Koc
43aaeeee15 test(plugins): pass live clawhub flag to docker 2026-05-02 11:10:47 -07:00
Vincent Koc
9c0c0ed127 test(plugins): add live clawhub docker switch 2026-05-02 11:07:05 -07:00
Peter Steinberger
93ffc80e9e ci: use gpt-5.4 for codex cli live smoke 2026-05-02 19:02:35 +01:00
Vincent Koc
b326e5c0f4 test(plugins): support live clawhub legacy zips 2026-05-02 11:01:54 -07:00
Vincent Koc
2400ae23b8 test(plugins): accept legacy clawhub artifacts 2026-05-02 11:00:53 -07:00
Vincent Koc
d7d80c05c3 Merge branch 'main' of https://github.com/openclaw/openclaw
* 'main' of https://github.com/openclaw/openclaw:
  fix(plugins): make uninstall teardown idempotent
  fix(lint): satisfy plugin e2e gate
  fix(build): externalize qrcode terminal
  chore(config): refresh generated config baseline
  chore(config): refresh generated config baseline
  chore(github): raise Dependabot PR limit
  fix(github): raise Barnacle active PR limit
2026-05-02 10:52:59 -07:00
Vincent Koc
336303e48b fix(plugins): make uninstall teardown idempotent 2026-05-02 10:51:02 -07:00
Vincent Koc
edfef73ffc fix(lint): satisfy plugin e2e gate 2026-05-02 10:51:02 -07:00
Vincent Koc
cb88d751b8 fix(build): externalize qrcode terminal 2026-05-02 10:51:02 -07:00
Vincent Koc
a45bcc429a chore(config): refresh generated config baseline 2026-05-02 10:46:40 -07:00
Vincent Koc
faf8a0774c chore(config): refresh generated config baseline 2026-05-02 10:41:57 -07:00
Vincent Koc
6557ca4e89 chore(config): refresh generated config baseline 2026-05-02 10:41:08 -07:00
Vincent Koc
5fb4fcd2b5 chore(github): raise Dependabot PR limit 2026-05-02 10:38:02 -07:00
Vincent Koc
1b951c565e fix(github): raise Barnacle active PR limit 2026-05-02 10:37:46 -07:00
Peter Steinberger
ac607044f1 docs: prepare 2026.5.2 release notes 2026-05-02 18:31:14 +01:00
Peter Steinberger
bb294bcd20 feat: support alpha releases 2026-05-02 18:29:13 +01:00
Vincent Koc
831958c5d4 fix(config): accept clawhub artifact install metadata 2026-05-02 10:26:40 -07:00
Vincent Koc
bc0f89074f fix(plugins): clean clawhub metadata import 2026-05-02 10:17:20 -07:00
Vincent Koc
7fae11b3b1 fix(plugins): persist clawhub artifact metadata 2026-05-02 10:17:19 -07:00
Peter Steinberger
aafdc5945a chore: delete stale memory host bridges 2026-05-02 18:15:26 +01:00
Peter Steinberger
9bedcff904 test(build): respect non-core plugin package metadata 2026-05-02 18:04:56 +01:00
Peter Steinberger
eeea77a559 fix(codex): resolve bundled managed binary root 2026-05-02 18:03:34 +01:00
Peter Steinberger
815665f839 fix(codex): resolve managed package binary fallback 2026-05-02 18:00:16 +01:00
Vincent Koc
03be4bfac5 fix(plugins): align clawhub clawpack downloads 2026-05-02 09:58:09 -07:00
Peter Steinberger
5c15ce3476 test(config): align legacy key validation expectations 2026-05-02 17:56:36 +01:00
Peter Steinberger
30e05211c1 test: tolerate unavailable release agent turn 2026-05-02 17:53:09 +01:00
Peter Steinberger
e5851cfcc2 test(plugins): align source contract registry expectations 2026-05-02 17:50:32 +01:00
Peter Steinberger
d3b6c805de ci: polish source performance report 2026-05-02 17:49:54 +01:00
Peter Steinberger
06a5469f47 test: stabilize anthropic stream abort smoke 2026-05-02 17:47:59 +01:00
Peter Steinberger
25ca5cc8df ci: add source performance probes 2026-05-02 17:46:10 +01:00
Peter Steinberger
d92a634fae perf(gateway): defer doctor legacy checks 2026-05-02 17:45:09 +01:00
Peter Steinberger
8d67ee112f fix(codex): preserve app-server exit diagnostics 2026-05-02 17:45:09 +01:00
Peter Steinberger
4e312d9b0e test(plugins): include source external plugin contracts 2026-05-02 17:45:01 +01:00
Peter Steinberger
a0d5372613 build(release): keep qrcode terminal external 2026-05-02 17:39:25 +01:00
Peter Steinberger
b79548b116 test(release): skip retryable codex harness timeouts 2026-05-02 17:33:44 +01:00
Peter Steinberger
1f7574148d test: align contract inventory with package excludes 2026-05-02 17:33:16 +01:00
Peter Steinberger
90682d7c44 docs: avoid retired bundle key in changelog 2026-05-02 17:33:16 +01:00
Peter Steinberger
5551d9fad4 fix: discover source-only plugins in checkouts 2026-05-02 17:33:15 +01:00
Chunyue Wang
cc8a8f1df1 fix(agents): keep state.messages intact across z.ai-style provider turns in embedded runs (#76056)
Merged via squash.

Prepared head SHA: ef305bb339
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Reviewed-by: @openperf
2026-05-03 00:31:51 +08:00
Peter Steinberger
3aaf30ffa6 perf(gateway): trim session list hot path 2026-05-02 17:26:55 +01:00
Peter Steinberger
da4ac53333 test(plugins): trust synthetic public artifact roots 2026-05-02 17:19:58 +01:00
Peter Steinberger
b4d0935557 test(release): align source checkout runtime expectations 2026-05-02 17:13:37 +01:00
Peter Steinberger
c336ab9e46 fix: repair bundled deps in release pack smoke 2026-05-02 17:05:56 +01:00
Peter Steinberger
5a4efa77fd test(gateway): remove stale config path binding 2026-05-02 17:05:45 +01:00
Peter Steinberger
20bb52e42c feat(gateway): profile watched gateway startup 2026-05-02 17:05:35 +01:00
Peter Steinberger
bd83f8a844 perf(plugins): prefer built bundled extensions 2026-05-02 17:05:35 +01:00
Peter Steinberger
d3f883e71b ci: initialize empty clawgrit report repo 2026-05-02 17:04:42 +01:00
Vincent Koc
437acb4184 test(plugins): exercise clawhub clawpack fixtures 2026-05-02 09:02:37 -07:00
Peter Steinberger
43de6ae725 perf(gateway): avoid extra session-list store work 2026-05-02 17:01:44 +01:00
Peter Steinberger
ea098bcafa test(release): tolerate unavailable live agent turns 2026-05-02 17:00:15 +01:00
pashpashpash
563dca82f4 Add Codex happy path prompt snapshots (#75807)
* Add Codex prompt snapshots

* Fix prompt snapshot scenario catalogs

* Harden prompt snapshot drift check

* Fix CLI compat build export

* fix: keep codex snapshots out of core plugin surface

* fix: harden prompt snapshot ci checks

* fix: accept readonly web search onboarding scopes

* fix: repair plugin sdk package boundary types

* fix: clear prompt snapshot ci regressions

* fix: clear latest main ci checks

* fix: resolve latest main discord helper overlap

* fix: refresh codex dynamic tool snapshots

* fix: align prompt snapshot branch with latest ci

* fix: isolate plugin auto enable tests

* test: refresh prompt dynamic tool snapshots

* fix: stabilize bundled channel auto enable

* fix: clean stale prompt snapshots
2026-05-03 00:59:55 +09:00
Peter Steinberger
4fb520d9b7 ci: pass clawgrit token state to kova run 2026-05-02 16:58:32 +01:00
Peter Steinberger
5a5180952c ci: detect clawgrit token at runtime 2026-05-02 16:55:15 +01:00
Peter Steinberger
7b4932f961 build: refresh config baseline hash 2026-05-02 16:53:17 +01:00
Peter Steinberger
e07960417c ci: tolerate missing performance report URL 2026-05-02 16:52:37 +01:00
Peter Steinberger
b22263720e ci: make performance workflow sanity nonblocking 2026-05-02 16:50:12 +01:00
Peter Steinberger
b63d098e8c fix: repair configured plugin installs (#76129)
Summary:
- The PR adds a 2026.5.2 doctor repair pass for actively used configured downloadable plugins, prefers ClawHub ... pm fallback, records installed plugin state, extends upgrade-survivor coverage, and updates docs/changelog.
- Reproducibility: yes. Static inspection of current main and the PR head gives a high-confidence reproduction ... d-plugin install pass, while the PR tests the new repair-only path, success stamping, and warning behavior.

ClawSweeper fixups:
- Included follow-up commit: test: cover configured plugin install update path
- Included follow-up commit: test: isolate channel option metadata cache
- Included follow-up commit: fix: keep configured plugin repair scoped

Validation:
- ClawSweeper review passed for head d3519ce42c.
- Required merge gates passed before the squash merge.

Prepared head SHA: d3519ce42c
Review: https://github.com/openclaw/openclaw/pull/76129#issuecomment-4364120658

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-05-02 15:49:52 +00:00
Vincent Koc
7b6b6401ce test(plugins): cover partial provider install catalog 2026-05-02 08:48:55 -07:00
Peter Steinberger
0be7a78479 ci: add OpenClaw performance reports 2026-05-02 16:48:33 +01:00
Val Alexander
4532e5d858 fix(control-ui): preserve Stop after reconnect
Fixes #70991.

Adds authenticated Gateway WebSocket protocol pings, exposes active session-run state to Control UI, and keeps session-scoped Stop available after reconnect or reload when the browser lost the local run id.

Validation:
- pnpm test ui/src/ui/app-chat.test.ts ui/src/ui/app-gateway.node.test.ts src/gateway/server.sessions.list-changed.test.ts src/gateway/server/ws-connection.test.ts
- OPENCLAW_LOCAL_CHECK=1 OPENCLAW_LOCAL_CHECK_MODE=throttled pnpm check:changed
- GitHub CI and high-signal security checks passed on head 1f4c8728c8
2026-05-02 10:41:27 -05:00
Val Alexander
aaa19fb9f3 fix(ui): tolerate malformed cron payloads
Fix Control UI blank sections caused by malformed persisted cron rows.

- filter invalid cron payloads at the cron.list UI boundary
- guard stale cron payload reads in render, edit, and detail paths
- add regression coverage for malformed cron rows from #55047 and #54439

Closes #55047.
Closes #54439.
Supersedes #54550.
Supersedes #54552.
2026-05-02 10:37:53 -05:00
Vincent Koc
33eebc29c3 test(plugins): cover kitchen sink clawhub cutover 2026-05-02 08:30:47 -07:00
Peter Steinberger
4eedc4723f test(config): remove runtime legacy compat wrapper 2026-05-02 16:29:10 +01:00
Peter Steinberger
15cb06430e fix(plugins): guard optional stock root cache key 2026-05-02 16:18:38 +01:00
Val Alexander
5fce2f6b0f fix(control-ui): allow configured chat message width
Adds validated gateway.controlUi.chatMessageMaxWidth support for grouped Control UI chat messages, carries it through the Gateway bootstrap payload into UI state, applies it as a CSS custom property, and documents the setting while preserving the existing default width.

Fixes #67935.

Validation:
- Targeted config, gateway, and Control UI tests passed locally.
- Config schema/docs checks passed.
- Testbox changed-file gate passed.
- GitHub CI and security checks are green on cea25a4ca9.
2026-05-02 10:18:08 -05:00
Peter Steinberger
a3564ae546 perf: optimize plugin schema validation 2026-05-02 16:15:45 +01:00
Peter Steinberger
0cf51b77fb refactor(memory): collapse legacy memory registration state 2026-05-02 16:15:07 +01:00
zhang-guiping
2c272e271a fix(agents): preserve session model after heartbeat runs
Fixes #75452.

Heartbeat runs can use a per-turn model override via agents.defaults.heartbeat.model. Before this change, the run metadata was written back to the shared session store, so the next normal turn could inherit the heartbeat provider/model and a smaller context window.

This lands the contributor fix plus maintainer polish:
- preserve existing session runtime model/provider/context metadata when persisting heartbeat turns
- avoid creating invalid provider/model pairs for legacy model-only session entries
- leave empty prior runtime state unset for heartbeat-only turns
- keep normal non-heartbeat runtime persistence unchanged
- add focused regression coverage for the session-store edge cases
- refresh heartbeat docs and changelog attribution

Validation:
- pnpm test src/agents/command/session-store.test.ts src/agents/openclaw-tools.session-status.test.ts
- pnpm exec oxfmt --check --threads=1 src/agents/agent-command.ts src/agents/command/session-store.ts src/agents/command/session-store.test.ts CHANGELOG.md docs/gateway/heartbeat.md
- git diff --check
- GitHub checks on 42a00dcf38: clean; no active checks and no relevant failures

Duplicate PR #75567 was already closed; #75557 is the canonical fix.
2026-05-02 10:14:30 -05:00
Peter Steinberger
ad0d87d881 perf: cache startup package metadata 2026-05-02 16:11:05 +01:00
Peter Steinberger
5b063c2d83 fix: keep legacy config repair in doctor 2026-05-02 16:10:45 +01:00
Peter Steinberger
3f2c3a69d7 fix(release): stabilize slow live release gates 2026-05-02 16:04:39 +01:00
Vincent Koc
c7b5302acf fix(plugins): repair missing clawhub installs 2026-05-02 08:01:37 -07:00
Peter Steinberger
2244ba87b3 docs: add generated plugin reference pages 2026-05-02 15:55:47 +01:00
Peter Steinberger
da2a8bd6bb fix: scope runtime plugin preload to effective plugins 2026-05-02 15:55:06 +01:00
Peter Steinberger
5980040894 fix: avoid duplicate gateway config loads 2026-05-02 15:49:16 +01:00
Federico Kamelhar
10ebcbdb99 fix(docker): replace curl|bash Bun install with pinned multi-stage COPY (#74359)
Merged via squash.

Prepared head SHA: 3b4a889467
Co-authored-by: fede-kamel <209537060+fede-kamel@users.noreply.github.com>
Co-authored-by: sallyom <11166065+sallyom@users.noreply.github.com>
Reviewed-by: @sallyom
2026-05-02 10:46:51 -04:00
Peter Steinberger
2b37b383ed fix(sessions): keep list polling lightweight (#76090)
Co-authored-by: rolandrscheel <20336324+rolandrscheel@users.noreply.github.com>
2026-05-02 15:45:38 +01:00
Vincent Koc
d228b0dc58 fix(plugins): narrow channel install defaults 2026-05-02 07:41:24 -07:00
Vincent Koc
16e3316beb fix(plugins): type channel clawhub install metadata 2026-05-02 07:41:24 -07:00
Vincent Koc
9281eee702 feat(plugins): prefer clawhub for channel setup installs 2026-05-02 07:41:23 -07:00
Peter Steinberger
27318663ef docs: compact plugin inventory tables 2026-05-02 15:40:02 +01:00
Peter Steinberger
9d5a0d4094 test: support legacy plugin cleanup package layout 2026-05-02 15:36:01 +01:00
Peter Steinberger
57e4a12165 fix(release): stage codex plugin source for live docker harness 2026-05-02 15:34:59 +01:00
Vincent Koc
dda2db97d4 fix(plugins): accept clawhub provider index installs 2026-05-02 07:27:20 -07:00
Vincent Koc
11daaad3d0 feat(plugins): prefer clawhub in onboarding installs 2026-05-02 07:27:20 -07:00
Peter Steinberger
75dd28e083 fix(doctor): preserve built-in channel plugin allow entries 2026-05-02 15:26:57 +01:00
Peter Steinberger
bf2711b40e fix(gateway): cap channel startup fanout 2026-05-02 15:26:45 +01:00
Peter Steinberger
829364f85e test: dedupe session write-lock mock export (#76051) 2026-05-02 15:20:24 +01:00
Peter Steinberger
95b65054d4 test: repair session write-lock generated coverage (#76051) 2026-05-02 15:20:24 +01:00
Peter Steinberger
17d3513211 docs: add sessions defaults changelog (#76051) 2026-05-02 15:20:24 +01:00
Cedric
98bd987a0a fix(control-ui): bound default sessions query 2026-05-02 15:20:24 +01:00
Peter Steinberger
1d5c77c443 fix(gateway): include active plugin tools in catalog 2026-05-02 15:15:52 +01:00
Peter Steinberger
bd6035d977 fix: prefer built plugin artifacts at gateway startup 2026-05-02 15:12:52 +01:00
Peter Steinberger
2dd3e40a13 fix: lazy-load memory-core runtime surfaces 2026-05-02 15:12:30 +01:00
Peter Steinberger
91bb76d8b9 perf(file-transfer): lazy-load runtime handlers 2026-05-02 15:12:14 +01:00
Peter Steinberger
3a52e95473 test(core): refresh write lock config fixtures 2026-05-02 15:07:48 +01:00
Peter Steinberger
eddc589ca5 fix: lazy load bonjour advertiser 2026-05-02 15:05:33 +01:00
Peter Steinberger
408642dc34 test: skip legacy doctor in upgrade survivor prep 2026-05-02 15:04:06 +01:00
Peter Steinberger
3240cccb8a fix(plugins): expose startup tool registry in catalog 2026-05-02 15:01:01 +01:00
JIRBOY
68ac9a48b7 perf(gateway): skip auth overlays during startup secrets preflight
Use persisted-only auth profile loading for gateway startup and restart-check secrets preflight, keeping reload/OAuth/runtime paths overlay-capable.

Validation:
- pnpm test src/gateway/server-startup-config.secrets.test.ts src/secrets/runtime.fast-path.test.ts
- Testbox: OPENCLAW_TESTBOX=1 pnpm check:changed

Thanks @JIRBOY.
2026-05-02 15:00:21 +01:00
Ayaan Zaidi
a55b2af7a5 fix: keep Gemini thinking streams active (#76080) (thanks @zhangguiping-xydt) 2026-05-02 19:26:54 +05:30
zhang-guiping
ea3416d8b5 fix(google): handle thoughtSignature-only parts to prevent Gemini stream hang
Gemini 3.1 Pro Preview may emit parts with only thoughtSignature
and no text content, causing the stream to stall. Emit a
thinking_signature event to keep the stream active, and start
a thinking block when these parts arrive before any text.

Fixes #76071
2026-05-02 19:26:54 +05:30
Peter Steinberger
f7ed29e118 fix: thread session write-lock timeout config 2026-05-02 14:54:54 +01:00
Ayaan Zaidi
731f640bca style(agents): trim tool-timeout comments 2026-05-02 19:23:17 +05:30
Simon
fbad17bf4f fix(plugin-sdk): keep harness timeout flag optional
Keep the new attempt-result field optional for third-party harness compatibility while defaulting absent values at the runner boundary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:23:17 +05:30
Simon
8996161e99 fix(agents): skip retry paths for tool timeouts
Thread tool-timeout state through timeout-triggered compaction, generic timeout payload synthesis, and the changelog.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:23:17 +05:30
Simon
2605490dbd fix(agents): classify tool-execution timeouts
Detect run-level timeouts that fire while a tool call is still active and keep them out of assistant model fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 19:23:17 +05:30
Peter Steinberger
afbc395dda fix(gateway): load plugin tools for catalog 2026-05-02 14:52:27 +01:00
Peter Steinberger
1466878c36 refactor: cache plugin tool descriptors (#76079)
Co-authored-by: Shakker <shakkernerd@users.noreply.github.com>
2026-05-02 14:52:21 +01:00
Peter Steinberger
c6817d8d7a fix: preserve heartbeat wake compatibility (#76086) 2026-05-02 14:52:18 +01:00
Peter Steinberger
c06739d773 fix(heartbeat): type wake scheduling intent
Co-authored-by: Jordan Baker <jbb@scryent.com>
2026-05-02 14:52:18 +01:00
Mason Huang
0b09cfb8cd fix(cli): block package updates from inside running gateway service (#75729)
Merged via squash.

Prepared head SHA: 8f301c5632
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Co-authored-by: hxy91819 <8814856+hxy91819@users.noreply.github.com>
Reviewed-by: @hxy91819
2026-05-02 21:48:38 +08:00
Ayaan Zaidi
473fc0aad8 fix: retry busy cron wake-now jobs (#76083) (thanks @xuruiray) 2026-05-02 19:15:23 +05:30
Ayaan Zaidi
9797ae35ca fix(cron): polish wake-now retry PR 2026-05-02 19:15:23 +05:30
Rui Xu
8db83f241e fix(cron): retry busy recurring wake-now jobs 2026-05-02 19:15:23 +05:30
Peter Steinberger
91055b9a37 fix(release): keep provider registry fallback behind loader 2026-05-02 14:44:17 +01:00
Peter Steinberger
6a54aac489 build(protocol): refresh generated Swift models 2026-05-02 14:37:42 +01:00
Peter Steinberger
efa15001d6 fix(release): handle missing plugin registry fallback 2026-05-02 14:34:13 +01:00
Peter Steinberger
0ea28ddb16 fix: speed up exact session lookups 2026-05-02 14:29:36 +01:00
Peter Steinberger
81e1deade2 fix(release): restore plugin runtime loading 2026-05-02 14:28:55 +01:00
Peter Steinberger
61fc62ade7 fix(auth): avoid structuredClone for auth profile stores 2026-05-02 14:23:51 +01:00
Peter Steinberger
d678bcfcc7 fix: hot reload plugin management changes (#75976)
Summary:
- The PR changes Gateway reload planning, CLI plugin install-index writes, plugin runtime/cache cleanup, docs, changelog, and tests so plugin enable/disable hot reloads while install/update/uninstall stay restart-backed.
- Reproducibility: yes. The earlier blocker has a source-level reproduction: run an external plugin install/up ...  watches config and only the managed plugin index changes; the PR now tests that path and queues a restart.

ClawSweeper fixups:
- Included follow-up commit: fix: hot reload plugin management changes
- Included follow-up commit: fix(clawsweeper): address review for automerge-openclaw-openclaw-7597…
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head 860594f722.
- Required merge gates passed before the squash merge.

Prepared head SHA: 860594f722
Review: https://github.com/openclaw/openclaw/pull/75976#issuecomment-4363168379

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 13:19:24 +00:00
Peter Steinberger
c9fa7b61f1 test(xai): tolerate live provider drift 2026-05-02 14:16:07 +01:00
Peter Steinberger
7a100021d3 test(release): stabilize live codex gates 2026-05-02 14:08:47 +01:00
Val Alexander
d919281fa8 fix(control-ui): improve text selection contrast
Use dedicated high-contrast selection tokens for Control UI/WebChat text selection and add the user-facing changelog entry.\n\nFixes #60850.\nSupersedes #60854.
2026-05-02 07:56:08 -05:00
Peter Steinberger
f523620abe ci: use gpt-5.4 for cross-os release smoke 2026-05-02 13:47:51 +01:00
Peter Steinberger
0f16edf329 fix: cache stable system prompt prep 2026-05-02 13:47:40 +01:00
Kevin
d22da87126 fix: contain iOS standalone viewport (#76072)
Contain the Control UI document in iOS Add-to-Home-Screen standalone mode by enabling viewport-fit=cover, applying safe-area-aware body locking, and constraining the app root so inner panes own scrolling.

Thanks @kvncrw.
2026-05-02 13:46:41 +01:00
DmitryPogodaev
8283c5d6cc perf(plugins): reuse startup runtime registry
Reuse the startup runtime plugin registry across provider/tool helper paths while preserving standalone CLI/MCP fallback loading.

Includes follow-up fixes for migration/provider/tool registry bootstrap and regression coverage for compatible registry reuse.

Co-authored-by: DmitryPogodaev <pogodaev.dm@gmail.com>
2026-05-02 13:44:49 +01:00
Peter Steinberger
695960975a test(release): relax reduced kitchen sink diagnostics 2026-05-02 13:40:45 +01:00
Peter Steinberger
b151694e00 refactor(sessions): route cleanup through controlled writers 2026-05-02 13:40:33 +01:00
Peter Steinberger
2165d1687e test(release): allow kitchen sink channel probe diagnostic 2026-05-02 13:37:17 +01:00
JC
228e5a238c fix: recover topic-suffixed restart locks (#76052)
Fix restart recovery for main sessions that use topic-suffixed transcript files by matching cleaned transcript lock paths directly while preserving the canonical session-id fallback for stale metadata.

Thanks @anyech.
2026-05-02 13:30:10 +01:00
Peter Steinberger
237d0869dc ci: fix release-path docker rerun commands 2026-05-02 13:27:03 +01:00
Peter Steinberger
f4a69c4620 test(google-meet): mock session store updates 2026-05-02 13:24:02 +01:00
Peter Steinberger
9fff2b7791 fix(gateway): detect SecretRef auth rotations 2026-05-02 13:16:28 +01:00
Peter Steinberger
8a2207f8a1 fix(security): ignore plugin install debris in audits 2026-05-02 13:12:28 +01:00
Peter Steinberger
be2768433c fix: mark task fallback events untrusted 2026-05-02 13:11:19 +01:00
Peter Steinberger
638fbc75a0 test: remove stale reset hook import 2026-05-02 13:11:19 +01:00
Peter Steinberger
35685540e2 test: stabilize session reset writer coverage 2026-05-02 13:11:19 +01:00
Peter Steinberger
4967bcb16b fix: route session cleanup through gateway writer 2026-05-02 13:11:19 +01:00
Peter Steinberger
b4437047f4 perf: route session store writes through writer queue 2026-05-02 13:11:19 +01:00
Peter Steinberger
ffc79532b8 test(release): stabilize live release gates 2026-05-02 13:06:37 +01:00
Peter Steinberger
f46c699887 fix(tasks): speed up registry maintenance
Co-authored-by: Lightningxxl <yuanhangxurobin@gmail.com>
Co-authored-by: Gorin Lee <glfruit80@gmail.com>
2026-05-02 13:02:13 +01:00
Peter Steinberger
a254fdaf42 refactor: isolate plugin tool factory execution 2026-05-02 13:01:51 +01:00
Peter Steinberger
7ed58a3efb fix: preserve discord setup channel allowlists (#47788) (thanks @Eldersonar) 2026-05-02 13:01:30 +01:00
Matthew Schleder
084c4beb2e fix(telegram): pass session files to native plugin commands
Pass persisted session file context into Telegram native plugin commands so topic-scoped /codex bind can attach to the active OpenClaw session.

Thanks @MatthewSchleder.

Validation:
- pnpm plugin-sdk:api:check
- pnpm test extensions/telegram/src/bot-native-commands.session-meta.test.ts extensions/telegram/src/bot-native-commands.test.ts -- --reporter=verbose
- OPENCLAW_TESTBOX=1 pnpm check:changed (tbx_01kqm8kzwkdxs2ntgck6vmyrgr)
2026-05-02 13:01:07 +01:00
Peter Steinberger
3980eaa1c2 fix(discord): harden Carbon parity (#75363)
Summary:
- The PR updates the Discord plugin with REST priority lanes and stale background drops, gateway send/member v ... normalization, explicit component forwarding, one-off component wait helpers, tests, and a changelog entry.
- Reproducibility: yes. The prior scheduler failure has a high-confidence source-level reproduction using one  ... ne pending same-bucket request under fake timers, and the latest head adds a regression test for that path.

ClawSweeper fixups:
- Included follow-up commit: fix(discord): preserve option localizations
- Included follow-up commit: fix(discord): harden component sends
- Included follow-up commit: docs(changelog): note Discord Carbon parity hardening
- Included follow-up commit: fix(discord): harden Carbon parity
- Ran the ClawSweeper repair loop before final review.

Validation:
- ClawSweeper review passed for head 4fa634ef1a.
- Required merge gates passed before the squash merge.

Prepared head SHA: 4fa634ef1a
Review: https://github.com/openclaw/openclaw/pull/75363#issuecomment-4357438917

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
2026-05-02 11:57:07 +00:00
Peter Steinberger
cd84e9bfb0 fix: preserve discord announce account routing 2026-05-02 12:50:26 +01:00
Peter Steinberger
3ee41deba9 test(agents): preserve session lock pid mock 2026-05-02 12:48:43 +01:00
Peter Steinberger
70ef234753 refactor(skills): centralize snapshot hydration 2026-05-02 12:47:19 +01:00
Peter Steinberger
e607ad4ab0 fix(telegram): route bound group native commands 2026-05-02 12:47:06 +01:00
Peter Steinberger
05a5fa81a0 fix(sessions): hydrate agent-command skill snapshots 2026-05-02 12:44:39 +01:00
Amogh Asgekar
479ed596bd fix(sessions): hydrate skillsSnapshot.resolvedSkills on resume
Codex review on PR #75960 flagged that prepareClaudeCliSkillsPlugin and
the claude-live-session fingerprint read skillsSnapshot.resolvedSkills
directly without a disk fallback. After the persistence-layer strip,
those consumers would see an empty Skill[] on cold session resume,
breaking the documented Claude Code skills integration.

Add a hydration helper in ensureSkillSnapshot that rebuilds
resolvedSkills from a fresh workspace scan when the loaded snapshot
lacks it, while keeping the persisted prompt/skills/skillFilter/version
fields untouched so the model's prompt-cache key stays stable across
resume. The embedded runner's existing consumer-level fallback in
src/agents/pi-embedded-runner/skills-runtime.ts is now a redundant
safety net rather than the only fallback path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 12:44:39 +01:00
Amogh Asgekar
643ff4d778 docs(changelog): note sessions skillsSnapshot.resolvedSkills strip
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 12:44:39 +01:00
Amogh Asgekar
a3cacf3b67 perf(sessions): stop persisting skillsSnapshot.resolvedSkills
Each SessionEntry carried the fully parsed Skill[] (including each
SKILL.md body) inside skillsSnapshot.resolvedSkills, multiplied across
every active session. Strip the field at the persistence chokepoint —
normalizeSessionStore in store-load.ts — so every load and every save
naturally drops it. The runtime already falls back to a workspace skill
scan when resolvedSkills is absent (see
src/agents/pi-embedded-runner/skills-runtime.ts:14), so prompts and
session resume behavior are unchanged.

Legacy sessions.json files self-heal on first load: normalize strips
the in-memory store, the next write rewrites the file in stripped form.

Test fixture (100 sessions × 50 skills × ~3KB body) goes from ~32MB to
under 2MB on disk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 12:44:39 +01:00
Peter Steinberger
03df3539e9 fix: suppress discord reconnect exhaustion during shutdown 2026-05-02 12:43:24 +01:00
Peter Steinberger
d90a08a447 refactor: extract plugin tool factory cache 2026-05-02 12:41:54 +01:00
Peter Steinberger
e62608beaa fix(release): keep discord core package files 2026-05-02 12:36:07 +01:00
Peter Steinberger
15f2cebc3e test(gateway): tolerate loaded auth rotation close 2026-05-02 12:23:42 +01:00
Peter Steinberger
40f2bf3950 fix: cache plugin tool factories by context 2026-05-02 12:19:29 +01:00
Peter Steinberger
335f870cd2 test: keep live release smokes tool-minimal 2026-05-02 12:18:25 +01:00
Peter Steinberger
460a5c131f fix: warn on empty discord native command replies 2026-05-02 12:14:37 +01:00
Peter Steinberger
5d0925fbb2 test(release): align package docker expectations 2026-05-02 12:10:04 +01:00
Peter Steinberger
85ce75c005 fix(daemon): canonicalize macOS service PATH 2026-05-02 12:02:47 +01:00
Peter Steinberger
29dc18d33d test(plugin-state): seed limit fixtures in one transaction 2026-05-02 12:02:10 +01:00
Peter Steinberger
c136bb0eaf test(release): exclude Discord plugin dist from core package 2026-05-02 12:00:05 +01:00
dae-sun
a147540b5f fix(telegram): register commands for group scope + preserve topic thread params 2026-05-02 12:00:05 +01:00
Ayaan Zaidi
d3e5292551 docs(changelog): move session status note to unreleased 2026-05-02 16:28:59 +05:30
Ayaan Zaidi
f3b4cb53b5 docs(changelog): note channel session status fix 2026-05-02 16:28:59 +05:30
bittoby
d5ad90f7ec fix: solve current-session resolution and valid session creation for sparse channel-plugin requesters 2026-05-02 16:28:59 +05:30
bittoby
8ace33be67 fix(agents/tools): resolve sessionKey=current for channel-plugin agents 2026-05-02 16:28:59 +05:30
Peter Steinberger
80da0a0213 chore: bump version to 2026.5.2 2026-05-02 11:58:45 +01:00
Ayaan Zaidi
7edac014e5 fix: drop stale service PATH entries (#75440) (thanks @leonaIee) 2026-05-02 16:20:50 +05:30
Ayaan Zaidi
626a22decb refactor(daemon): reuse shared path normalizer 2026-05-02 16:20:50 +05:30
leonaIee
0d747536de docs: add service path changelog 2026-05-02 16:20:50 +05:30
leonaIee
49b1b08444 fix: drop stale service PATH entries 2026-05-02 16:20:50 +05:30
Peter Steinberger
ad264a9f5a fix(release): keep core runtime plugins installed 2026-05-02 11:48:34 +01:00
Peter Steinberger
5dff0397cf fix: keep discord typing alive during long runs 2026-05-02 11:47:42 +01:00
Peter Steinberger
17d02a6a73 test(wizard): mock migration detection in setup tests 2026-05-02 11:45:17 +01:00
Peter Steinberger
2b88dc0714 fix(slack): preserve hook alert content (#76036) (thanks @amsminn) 2026-05-02 11:43:46 +01:00
amsminn
177fb7e84d fix: preserve slack hook alert content 2026-05-02 11:43:46 +01:00
Peter Steinberger
d7ab2c4c41 fix(agents): narrow transcript policy cache config 2026-05-02 11:42:31 +01:00
Peter Steinberger
68bfdb4d29 fix(agents): repair codex responses tool args (#75281) 2026-05-02 11:42:31 +01:00
Eric Huang
edca8c721a fix(google): narrow Gemini 2.5 minimal budget floor (#70629) (thanks @ericberic)
* fix: raise Gemini 2.5 minimal thinking budget from 128 to 512

Google raised the minimum thinkingBudget for Gemini 2.5 Pro and Flash
models to 512. The hardcoded minimal: 128 now causes a 400 INVALID_ARGUMENT
("The thinking budget 128 is invalid. Please choose a value between 512
and 24576.") on every heartbeat using gemini-2.5-flash-lite with minimal
thinking.

* test(google): assert thinkingBudget minimum of 512 for Gemini 2.5 models

Add parametrized tests covering minimal/low/medium budget tiers for
gemini-2.5-flash-lite, gemini-2.5-flash, and gemini-2.5-pro — ensures
the 128→512 floor change is regression-tested.

Pre-existing typecheck failure in src/agents/model-auth.ts (TS2322) is
unrelated; confirmed present on upstream main without our changes.
Tests validated: pnpm test extensions/google/transport-stream.test.ts (21 pass).

* test(google): fix it.each format string placeholder order

* fix(google): narrow Gemini 2.5 minimal budget floor to flash-lite only
2026-05-02 16:11:22 +05:30
Peter Steinberger
56c4f9761c fix(models): restore provider catalog listing 2026-05-02 11:37:05 +01:00
Peter Steinberger
eb3e4f20a0 fix: relax gateway service path audit 2026-05-02 11:36:23 +01:00
Peter Steinberger
8f94bd9984 fix: preserve discord multipart content type 2026-05-02 11:35:36 +01:00
Peter Steinberger
053b7900bb perf(status): lazy-load harness selection 2026-05-02 11:34:39 +01:00
Peter Steinberger
e5dc3f712e fix: retry codex app-server startup closes 2026-05-02 11:32:43 +01:00
Peter Steinberger
8631cadf5b fix: normalize discord thread channel metadata 2026-05-02 11:32:18 +01:00
Peter Steinberger
f8cbd356e1 perf(agents): memoize transcript policy safely 2026-05-02 11:30:47 +01:00
Peter Steinberger
ae339872a1 test: retry empty moonshot live smoke 2026-05-02 11:28:58 +01:00
Peter Steinberger
c247820bd1 fix(memory): dedupe managed markdown blocks 2026-05-02 11:28:01 +01:00
Peter Steinberger
f738263604 test(release): allow packaged discord runtime 2026-05-02 11:23:56 +01:00
Ayaan Zaidi
4e11daa521 chore: remove checked-in pi workspace files 2026-05-02 15:49:21 +05:30
Peter Steinberger
051171ba8f fix(release): restore package acceptance checks 2026-05-02 11:18:15 +01:00
scoootscooob
ccb847e46f fix(gateway): make startup control-plane retries explicit
* fix(gateway): make startup control-plane retries explicit

* docs(changelog): note startup control-plane retry fix
2026-05-02 03:16:04 -07:00
Peter Steinberger
ebc26a0bef test(auto-reply): speed up bound ACP dispatch test 2026-05-02 11:15:38 +01:00
Peter Steinberger
aebac43d97 fix: stop orphaned QA gateway children 2026-05-02 11:15:16 +01:00
jarvisdoes
7686136419 docs: add parallel specialist lane guidance
Adds a generic docs page for parallel specialist lanes and links it from the Multi-agent docs navigation.

Verification:
- PR CI green for docs path, including `check-docs`
- ClawSweeper reviewed as docs-only and cleared security surface

Co-authored-by: Jarvis <jarvisisago@gmail.com>
2026-05-02 11:14:06 +01:00
Val Alexander
2bade2703e fix(ui): surface slash command dispatch failures
## Summary
- surface inline Control UI feedback when local slash-command dispatch is unavailable or throws
- cover missing-client and unexpected-error paths for local slash commands
- note the user-facing fix in the changelog

Fixes #52105.
2026-05-02 05:08:05 -05:00
Peter Steinberger
0e8bd8e75c fix(gateway): defer pricing refresh until ready 2026-05-02 11:07:54 +01:00
kunpeng-ai-lab
f3fd0eedff fix(memory): retry transient index swaps on Windows
Fixes #64187.

Adds bounded retry handling for transient Windows rename failures (`EBUSY`, `EPERM`, `EACCES`) during memory-core SQLite atomic reindex swaps. Keeps missing optional SQLite sidecars ignored and non-transient rename failures fail-fast.

Verification:
- PR CI green, including `check`, `check-additional`, `checks-node-core`, `build-smoke`, and security fast checks
- Contributor local proof: `pnpm exec vitest run extensions/memory-core/src/memory/manager.atomic-reindex.test.ts`
- Contributor local proof: `pnpm lint:extensions -- extensions/memory-core/src/memory/manager-atomic-reindex.ts extensions/memory-core/src/memory/manager.atomic-reindex.test.ts`
- Contributor local proof: `pnpm check:changed`

Co-authored-by: 鲲鹏AI探索局 <kunpeng-ai@outlook.com>
2026-05-02 11:07:48 +01:00
Peter Steinberger
b1cfba2fc2 fix(agents): return tool loop stops as blocks 2026-05-02 11:06:46 +01:00
Peter Steinberger
546f81de04 fix(model): clarify session-scoped model switches 2026-05-02 11:03:47 +01:00
Peter Steinberger
738cf18a0f fix(plugins): align loader cache scope typing 2026-05-02 11:01:31 +01:00
Peter Steinberger
e497681dea fix(telegram): keep outbound timeout guard authoritative 2026-05-02 11:01:11 +01:00
Peter Steinberger
e0a267afc6 fix: avoid repeated discord thread starter context 2026-05-02 11:00:57 +01:00
Illia Pavelko
d25019b416 fix(openai): show codex device code in ssh (#74258)
Fixes #74212.

Thanks @da22le123.
2026-05-02 11:00:25 +01:00
Peter Steinberger
7020cfddbf fix: remove duplicate Telegram thread config fields 2026-05-02 10:59:46 +01:00
Peter Steinberger
a7d2953956 fix: remove duplicate Telegram DM thread helper 2026-05-02 10:59:46 +01:00
Peter Steinberger
7db255150c fix: keep Telegram DM thread IDs on flat sessions 2026-05-02 10:59:46 +01:00
Peter Steinberger
f727fbc775 fix(agents): skip model normalization in context warmup 2026-05-02 10:59:34 +01:00
Peter Steinberger
1634f91a35 fix: improve google meet twilio join sequencing 2026-05-02 10:56:14 +01:00
Peter Steinberger
59fb9e5ca7 refactor: unify lazy import loaders 2026-05-02 10:55:59 +01:00
Peter Steinberger
2dcc13d685 fix(memory-wiki): accept relative markdown link targets 2026-05-02 10:55:37 +01:00
Peter Steinberger
f7b24a697d perf(infra): fast path posix containment checks 2026-05-02 10:50:28 +01:00
Peter Steinberger
6cc7b759e9 fix(plugins): accept unscoped registry cache reuse 2026-05-02 10:48:29 +01:00
Peter Steinberger
e0221d37e5 fix(openrouter): preserve deepseek v4 reasoning replay 2026-05-02 10:48:28 +01:00
Peter Steinberger
f2df789ca5 test: accept codex models shell fallback 2026-05-02 10:47:16 +01:00
Peter Steinberger
701811e013 test: align runtime fixture expectations 2026-05-02 10:41:42 +01:00
Ayaan Zaidi
47de32ac21 chore(security): remove stale secret baseline 2026-05-02 15:10:45 +05:30
Peter Steinberger
3b3def0354 fix(plugins): cache cli registration entries 2026-05-02 10:40:07 +01:00
Peter Steinberger
70dcd81f03 fix: canonicalize discord pluralkit inbound ids 2026-05-02 10:36:20 +01:00
Peter Steinberger
9e983ef8e1 test: stabilize full test suite 2026-05-02 10:35:59 +01:00
Gabriel
3ea2d2a928 fix(failover): improve internal server error classification (#73844)
* fix(failover): improve internal server error classification

* fix: cover bare internal server status

---------

Co-authored-by: Altay <altay@uinaf.dev>
2026-05-02 12:35:55 +03:00
Ayaan Zaidi
6de92d0bd4 chore: remove prettier ignore 2026-05-02 15:05:09 +05:30
Peter Steinberger
9b11248c5f fix(anthropic): recover orphan text deltas 2026-05-02 10:34:24 +01:00
Val Alexander
64fcc8a1aa fix(control-ui): measure and decouple slow refreshes
Add Control UI timing attribution for tab visibility, refresh phases, secondary refresh groups, and gateway RPCs. Decouple slow Overview, Cron, and Nodes secondary refreshes from primary tab feedback, and report Cron runs timing from the controller's real ok/error/skipped load outcome.

Also keeps telemetry secret-safe by excluding request params and response bodies, adds focused regression coverage for RPC attribution and stale/failed background refreshes, and carries the latest-main Discord test fixture correction needed for check:test-types.

Fixes #64004.
2026-05-02 04:33:36 -05:00
Peter Steinberger
0a6584a231 fix(plugins): reuse gateway-bindable loader cache 2026-05-02 10:33:27 +01:00
Ayaan Zaidi
f458a9f17f chore: remove mailmap 2026-05-02 15:01:50 +05:30
Peter Steinberger
28c852fee5 fix(gateway): log secrets handler error details 2026-05-02 10:31:37 +01:00
Peter Steinberger
a0c3cd6878 test: cover npm pack override reference 2026-05-02 10:25:44 +01:00
Peter Steinberger
e550e83c0e docs: clarify changelog attribution 2026-05-02 10:24:39 +01:00
Peter Steinberger
4f6a4317de fix: clarify google meet twilio dial plan 2026-05-02 10:24:39 +01:00
Peter Steinberger
800a33bbfe test: harden release live probes 2026-05-02 10:22:54 +01:00
Peter Steinberger
5b2a0fbac1 fix: keep npm pack override compatible 2026-05-02 10:16:27 +01:00
Peter Steinberger
db06fcd990 refactor: unify lazy module loaders 2026-05-02 10:15:25 +01:00
Peter Steinberger
4407c317f3 fix: honor openai sse transport for agent turns 2026-05-02 10:10:09 +01:00
Peter Steinberger
d419bcf5c9 fix: preserve discord unicode channel labels 2026-05-02 10:09:48 +01:00
Ayaan Zaidi
d50cd0f6cf chore: remove stale preview artifacts 2026-05-02 14:37:38 +05:30
Peter Steinberger
bb93254473 ci: upload ts-unused deadcode report 2026-05-02 10:02:37 +01:00
Val Alexander
37aebf612b fix(control-ui): create sessions for typed /new
Route typed Control UI `/new` through the dashboard session create-and-switch flow used by the New Chat button.

Keep typed `/reset` as the explicit in-place gateway reset path, and document the Control UI slash-command boundary.

Fixes #69599.
2026-05-02 04:02:34 -05:00
Ayaan Zaidi
6669827135 chore: remove accidental fix script 2026-05-02 14:31:58 +05:30
clawsweeper[bot]
26e6860a64 fix(discord): document mention formatting guidance (#75173)
Summary:
- This PR adds Discord outbound mention-format guidance to the Discord plugin prompt hints, Discord channel docs, a focused channel test, and the changelog.
- Reproducibility: not applicable. as a runtime bug reproduction. There is a high-confidence inspection path:  ... lacks the guidance, while the existing formatter/tests and Discord reference establish the expected syntax.

ClawSweeper fixups:
- Included follow-up commit: fix(discord): document mention formatting guidance

Validation:
- ClawSweeper review passed for head bf2734a002.
- Required merge gates passed before the squash merge.

Prepared head SHA: bf2734a002
Review: https://github.com/openclaw/openclaw/pull/75173#issuecomment-4354537199

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: clawsweeper-repair <clawsweeper-repair@users.noreply.github.com>
Co-authored-by: Peter Steinberger <58493+steipete@users.noreply.github.com>
2026-05-02 09:00:58 +00:00
Peter Steinberger
b8c0a1e9ff fix(telegram): keep dm reply threads on main session 2026-05-02 09:58:08 +01:00
Peter Steinberger
2b92de604c test: align bonjour package metadata contract 2026-05-02 09:56:50 +01:00
Peter Steinberger
254b2ed104 chore: ignore bundled plugin runtime deps in knip 2026-05-02 09:55:35 +01:00
Peter Steinberger
2baa07f62b refactor: streamline plugin cache helpers 2026-05-02 09:54:54 +01:00
Peter Steinberger
127da4c3ca fix: preserve discord inbound media filenames 2026-05-02 09:54:09 +01:00
Peter Steinberger
803b7ab808 fix: warn on invalid hook transform directories 2026-05-02 09:51:03 +01:00
Peter Steinberger
a3628310e4 refactor: trim unused acp exports 2026-05-02 09:49:06 +01:00
Peter Steinberger
ae31aa6f84 fix: allow discord ack reactions in tool-only guilds 2026-05-02 09:49:00 +01:00
Peter Steinberger
e9cd362cd8 ci: preserve artifact package source metadata 2026-05-02 09:48:50 +01:00
Peter Steinberger
54d82b3055 fix(mcp): normalize invalid object tool properties 2026-05-02 09:48:32 +01:00
Peter Steinberger
ea26bdf07d test: align package metadata contracts 2026-05-02 09:48:06 +01:00
Pavan Kumar Gondhi
42dfc36da5 fix(infra): block workspace state-directory env override [AI] (#75940)
* fix: block workspace state directory env override

* docs: add changelog entry for PR merge
2026-05-02 14:17:42 +05:30
Peter Steinberger
089a3063ee fix: make codex app-server cleanup ownership-aware 2026-05-02 09:45:59 +01:00
Peter Steinberger
39a931f1bf feat(voice-call): route inbound calls per number 2026-05-02 09:44:52 +01:00
Peter Steinberger
de67311b96 refactor: hide acp secret file limit 2026-05-02 09:43:04 +01:00
1961 changed files with 77366 additions and 30929 deletions

0
.codex
View File

View File

@@ -1,45 +0,0 @@
# detect-secrets exclusion patterns (regex)
#
# Note: detect-secrets does not read this file by default. If you want these
# applied, wire them into your scan command (e.g. translate to --exclude-files
# / --exclude-lines) or into a baseline's filters_used.
[exclude-files]
# pnpm lockfiles contain lots of high-entropy package integrity blobs.
pattern = (^|/)pnpm-lock\.yaml$
[exclude-lines]
# Fastlane checks for private key marker; not a real key.
pattern = key_content\.include\?\("BEGIN PRIVATE KEY"\)
# UI label string for Anthropic auth mode.
pattern = case \.apiKeyEnv: "API key \(env var\)"
# CodingKeys mapping uses apiKey literal.
pattern = case apikey = "apiKey"
# Schema labels referencing password fields (not actual secrets).
pattern = "gateway\.remote\.password"
pattern = "gateway\.auth\.password"
# Schema label for talk API key (label text only).
pattern = "talk\.apiKey"
# checking for typeof is not something we care about.
pattern = === "string"
# specific optional-chaining password check that didn't match the line above.
pattern = typeof remote\?\.password === "string"
# Docker apt signing key fingerprint constant; not a secret.
pattern = OPENCLAW_DOCKER_GPG_FINGERPRINT=
# Credential matrix metadata field in docs JSON; not a secret value.
pattern = "secretShape": "(secret_input|sibling_ref)"
# Docs line describing API key rotation knobs; not a credential.
pattern = API key rotation \(provider-specific\): set `\*_API_KEYS`
# Docs line describing remote password precedence; not a credential.
pattern = passw[o]rd: `OPENCLAW_GATEWAY_PASSW[O]RD` -> `gateway\.auth\.passw[o]rd` -> `gateway\.remote\.passw[o]rd`
pattern = passw[o]rd: `OPENCLAW_GATEWAY_PASSW[O]RD` -> `gateway\.remote\.passw[o]rd` -> `gateway\.auth\.passw[o]rd`
# Test fixture starts a multiline fake private key; detector should ignore the header line.
pattern = const key = `-----BEGIN PRIVATE KEY-----
# Docs examples: literal placeholder API key snippets and shell heredoc helper.
pattern = export CUSTOM_API_K[E]Y="your-key"
pattern = grep -q 'N[O]DE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache' ~/.bashrc \|\| cat >> ~/.bashrc <<'EOF'
pattern = env: \{ MISTRAL_API_K[E]Y: "sk-\.\.\." \},
pattern = "ap[i]Key": "xxxxx",
pattern = ap[i]Key: "A[I]za\.\.\.",
# Sparkle appcast signatures are release metadata, not credentials.
pattern = sparkle:edSignature="[A-Za-z0-9+/=]+"

View File

@@ -59,11 +59,6 @@ apps/ios/build
# large app trees not needed for CLI build
apps/
assets/
Peekaboo/
Swabble/
Core/
Users/
vendor/
# Needed for building the Canvas A2UI bundle during Docker image builds.

View File

@@ -94,6 +94,9 @@ runs:
echo "lanes input is required for Docker E2E targeted planning." >&2
exit 1
fi
if [[ "$INCLUDE_RELEASE_PATH_SUITES" == "true" ]]; then
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
fi
export OPENCLAW_DOCKER_ALL_LANES="$LANES"
plan_path=".artifacts/docker-tests/targeted-plan.json"
;;

View File

@@ -29,7 +29,7 @@ updates:
update-types:
- minor
- patch
open-pull-requests-limit: 10
open-pull-requests-limit: 20
registries:
- npm-npmjs
@@ -83,7 +83,7 @@ updates:
# Swift Package Manager - Swabble
- package-ecosystem: swift
directory: /Swabble
directory: /apps/swabble
schedule:
interval: daily
cooldown:

2
.github/labeler.yml vendored
View File

@@ -195,7 +195,6 @@
- changed-files:
- any-glob-to-any-file:
- "docs/**"
- "docs.acp.md"
"cli":
- changed-files:
@@ -222,6 +221,7 @@
- "setup-podman.sh"
- ".dockerignore"
- "scripts/docker/setup.sh"
- "scripts/docker/sandbox/Dockerfile*"
- "scripts/podman/setup.sh"
- "scripts/**/*docker*"
- "scripts/**/Dockerfile*"

View File

@@ -1405,6 +1405,7 @@ jobs:
if pnpm run --silent 2>/dev/null | grep -q '^ deadcode:dependencies$'; then
pnpm deadcode:dependencies
pnpm deadcode:unused-files
pnpm deadcode:report:ci:ts-unused
else
pnpm deadcode:ci
fi
@@ -1428,6 +1429,14 @@ jobs:
;;
esac
- name: Upload deadcode reports
if: ${{ always() && matrix.task == 'dependencies' }}
uses: actions/upload-artifact@v7
with:
name: deadcode-reports
path: .artifacts/deadcode
if-no-files-found: ignore
check:
permissions:
contents: read
@@ -1952,7 +1961,7 @@ jobs:
uses: actions/cache@v5
with:
path: apps/macos/.build
key: ${{ runner.os }}-swift-build-v2-${{ steps.swift-toolchain.outputs.key }}-${{ hashFiles('apps/macos/Package.swift', 'apps/macos/Package.resolved', 'apps/macos/Sources/**', 'apps/macos/Tests/**', 'apps/shared/OpenClawKit/Package.swift', 'apps/shared/OpenClawKit/Sources/**', 'Swabble/Package.swift', 'Swabble/Sources/**') }}
key: ${{ runner.os }}-swift-build-v2-${{ steps.swift-toolchain.outputs.key }}-${{ hashFiles('apps/macos/Package.swift', 'apps/macos/Package.resolved', 'apps/macos/Sources/**', 'apps/macos/Tests/**', 'apps/shared/OpenClawKit/Package.swift', 'apps/shared/OpenClawKit/Sources/**', 'apps/swabble/Package.swift', 'apps/swabble/Sources/**') }}
restore-keys: |
${{ runner.os }}-swift-build-v2-${{ steps.swift-toolchain.outputs.key }}-
@@ -1962,13 +1971,13 @@ jobs:
set -euo pipefail
# Exact source-hash cache hits already match these inputs; checkout
# mtimes are the only reason SwiftPM rebuilds cached products.
find apps/macos/Sources apps/macos/Tests apps/shared/OpenClawKit/Sources Swabble/Sources apps/macos/.build/checkouts \
find apps/macos/Sources apps/macos/Tests apps/shared/OpenClawKit/Sources apps/swabble/Sources apps/macos/.build/checkouts \
-type f -exec touch -t 200001010000 {} +
touch -t 200001010000 \
apps/macos/Package.swift \
apps/macos/Package.resolved \
apps/shared/OpenClawKit/Package.swift \
Swabble/Package.swift
apps/swabble/Package.swift
- name: Show toolchain
run: |

View File

@@ -62,6 +62,26 @@ jobs:
sudo ln -sf "$node_bin/corepack" /usr/local/bin/corepack
sudo ln -sf "$pnpm_bin" /usr/local/bin/pnpm
- name: Ensure Docker is available
shell: bash
run: |
set -euo pipefail
if ! command -v docker >/dev/null 2>&1; then
curl -fsSL https://get.docker.com | sudo sh
fi
if command -v systemctl >/dev/null 2>&1; then
sudo systemctl start docker
fi
if [ -S /var/run/docker.sock ]; then
sudo usermod -aG docker "$USER" || true
# The runner process keeps its original groups; grant this
# ephemeral runner session access without requiring a relogin.
sudo chmod 666 /var/run/docker.sock
fi
- name: Hydrate provider env helper
shell: bash
env:
@@ -90,14 +110,23 @@ jobs:
- name: Mark Crabbox ready
shell: bash
env:
CRABBOX_ID: ${{ inputs.crabbox_id }}
CRABBOX_JOB: ${{ inputs.crabbox_job }}
run: |
set -euo pipefail
job="${{ inputs.crabbox_job }}"
job="${CRABBOX_JOB}"
if [ -z "$job" ]; then job=hydrate; fi
case "$CRABBOX_ID" in
''|*[!A-Za-z0-9._-]*)
echo "Invalid crabbox_id" >&2
exit 2
;;
esac
mkdir -p "$HOME/.crabbox/actions"
state="$HOME/.crabbox/actions/${{ inputs.crabbox_id }}.env"
env_file="$HOME/.crabbox/actions/${{ inputs.crabbox_id }}.env.sh"
services_file="$HOME/.crabbox/actions/${{ inputs.crabbox_id }}.services"
state="$HOME/.crabbox/actions/${CRABBOX_ID}.env"
env_file="$HOME/.crabbox/actions/${CRABBOX_ID}.env.sh"
services_file="$HOME/.crabbox/actions/${CRABBOX_ID}.services"
write_export() {
key="$1"
value="${!key-}"
@@ -129,13 +158,22 @@ jobs:
- name: Keep Crabbox job alive
shell: bash
env:
CRABBOX_ID: ${{ inputs.crabbox_id }}
CRABBOX_KEEP_ALIVE_MINUTES: ${{ inputs.crabbox_keep_alive_minutes }}
run: |
set -euo pipefail
minutes="${{ inputs.crabbox_keep_alive_minutes }}"
case "$CRABBOX_ID" in
''|*[!A-Za-z0-9._-]*)
echo "Invalid crabbox_id" >&2
exit 2
;;
esac
minutes="${CRABBOX_KEEP_ALIVE_MINUTES}"
case "$minutes" in
''|*[!0-9]*) minutes=90 ;;
esac
stop="$HOME/.crabbox/actions/${{ inputs.crabbox_id }}.stop"
stop="$HOME/.crabbox/actions/${CRABBOX_ID}.stop"
deadline=$(( $(date +%s) + minutes * 60 ))
while [ "$(date +%s)" -lt "$deadline" ]; do
if [ -f "$stop" ]; then

View File

@@ -38,7 +38,7 @@ jobs:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-beta\.[1-9][0-9]*)?$ ]]; then
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-(alpha|beta)\.[1-9][0-9]*)?$ ]]; then
echo "Invalid release tag: ${RELEASE_TAG}"
exit 1
fi

View File

@@ -68,6 +68,11 @@ on:
required: false
default: ""
type: string
package_acceptance_package_spec:
description: Optional published package spec for Package Acceptance; blank uses the SHA-built release artifact
required: false
default: ""
type: string
npm_telegram_provider_mode:
description: Provider mode for the package Telegram E2E lane
required: false
@@ -93,6 +98,8 @@ concurrency:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
GH_REPO: ${{ github.repository }}
NODE_VERSION: "24.x"
PNPM_VERSION: "10.32.1"
jobs:
resolve_target:
@@ -127,6 +134,7 @@ jobs:
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
NPM_TELEGRAM_PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
EVIDENCE_PACKAGE_SPEC: ${{ inputs.evidence_package_spec }}
PACKAGE_ACCEPTANCE_PACKAGE_SPEC: ${{ inputs.package_acceptance_package_spec }}
RELEASE_PROFILE: ${{ inputs.release_profile }}
RERUN_GROUP: ${{ inputs.rerun_group }}
LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
@@ -159,13 +167,18 @@ jobs:
if [[ -n "${NPM_TELEGRAM_PACKAGE_SPEC// }" ]]; then
echo "- Published-package Telegram E2E: \`${NPM_TELEGRAM_PACKAGE_SPEC}\`"
elif [[ "$RERUN_GROUP" == "all" && "$RELEASE_PROFILE" == "full" ]]; then
echo "- Package Telegram E2E: release package artifact from \`OpenClaw Release Checks\`"
echo "- Package Telegram E2E: parent \`release-package-under-test\` artifact"
else
echo "- Package Telegram E2E: skipped unless \`release_profile=full\` or \`npm_telegram_package_spec\` is provided"
fi
if [[ -n "${EVIDENCE_PACKAGE_SPEC// }" ]]; then
echo "- Private evidence package proof: \`${EVIDENCE_PACKAGE_SPEC}\`"
fi
if [[ -n "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
echo "- Package Acceptance package spec: \`${PACKAGE_ACCEPTANCE_PACKAGE_SPEC}\`"
else
echo "- Package Acceptance package spec: SHA-built release artifact"
fi
} >> "$GITHUB_STEP_SUMMARY"
normal_ci:
@@ -377,6 +390,7 @@ jobs:
RELEASE_PROFILE: ${{ inputs.release_profile }}
RERUN_GROUP: ${{ inputs.rerun_group }}
LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
PACKAGE_ACCEPTANCE_PACKAGE_SPEC: ${{ inputs.package_acceptance_package_spec }}
run: |
set -euo pipefail
@@ -455,6 +469,9 @@ jobs:
if [[ -n "${LIVE_SUITE_FILTER// }" ]]; then
echo "- Live suite filter: \`${LIVE_SUITE_FILTER}\`"
fi
if [[ -n "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
echo "- Package Acceptance package spec: \`${PACKAGE_ACCEPTANCE_PACKAGE_SPEC}\`"
fi
} >> "$GITHUB_STEP_SUMMARY"
child_rerun_group="$RERUN_GROUP"
@@ -473,12 +490,86 @@ jobs:
if [[ -n "${LIVE_SUITE_FILTER// }" ]]; then
args+=(-f live_suite_filter="$LIVE_SUITE_FILTER")
fi
if [[ -n "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
args+=(-f package_acceptance_package_spec="$PACKAGE_ACCEPTANCE_PACKAGE_SPEC")
fi
dispatch_and_wait openclaw-release-checks.yml "${args[@]}"
prepare_release_package:
name: Prepare release package artifact
needs: [resolve_target]
if: ${{ inputs.npm_telegram_package_spec == '' && inputs.rerun_group == 'all' && inputs.release_profile == 'full' }}
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
contents: read
packages: write
outputs:
artifact_name: ${{ steps.artifact.outputs.name }}
package_sha256: ${{ steps.package.outputs.sha256 }}
package_version: ${{ steps.package.outputs.package_version }}
source_sha: ${{ steps.package.outputs.source_sha }}
steps:
- name: Checkout trusted workflow ref
uses: actions/checkout@v6
with:
persist-credentials: false
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Set artifact metadata
id: artifact
run: echo "name=release-package-under-test" >> "$GITHUB_OUTPUT"
- name: Setup Node environment
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
install-bun: "true"
install-deps: "false"
- name: Resolve release package artifact
id: package
shell: bash
env:
PACKAGE_REF: ${{ needs.resolve_target.outputs.sha }}
run: |
set -euo pipefail
node scripts/resolve-openclaw-package-candidate.mjs \
--source ref \
--package-ref "$PACKAGE_REF" \
--output-dir .artifacts/docker-e2e-package \
--output-name openclaw-current.tgz \
--metadata .artifacts/docker-e2e-package/package-candidate.json \
--github-output "$GITHUB_OUTPUT"
digest="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).sha256")"
version="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).version")"
source_sha="$(node -p "JSON.parse(require('fs').readFileSync('.artifacts/docker-e2e-package/package-candidate.json', 'utf8')).packageSourceSha")"
echo "source_sha=$source_sha" >> "$GITHUB_OUTPUT"
{
echo "## Release package artifact"
echo
echo "- Artifact: \`release-package-under-test\`"
echo "- Package ref: \`$PACKAGE_REF\`"
echo "- SHA-256: \`$digest\`"
echo "- Version: \`$version\`"
echo "- Source SHA: \`$source_sha\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload release package artifact
uses: actions/upload-artifact@v7
with:
name: release-package-under-test
path: |
.artifacts/docker-e2e-package/openclaw-current.tgz
.artifacts/docker-e2e-package/package-candidate.json
if-no-files-found: error
npm_telegram:
name: Run package Telegram E2E
needs: [resolve_target, release_checks]
needs: [resolve_target, prepare_release_package]
if: ${{ always() && contains(fromJSON('["all","npm-telegram"]'), inputs.rerun_group) && (inputs.npm_telegram_package_spec != '' || (inputs.rerun_group == 'all' && inputs.release_profile == 'full')) }}
runs-on: ubuntu-24.04
timeout-minutes: 120
@@ -494,7 +585,8 @@ jobs:
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
TARGET_SHA: ${{ needs.resolve_target.outputs.sha }}
PACKAGE_SPEC: ${{ inputs.npm_telegram_package_spec }}
RELEASE_CHECKS_RUN_ID: ${{ needs.release_checks.outputs.run_id }}
PACKAGE_ARTIFACT_NAME: ${{ needs.prepare_release_package.outputs.artifact_name }}
PREPARE_PACKAGE_RESULT: ${{ needs.prepare_release_package.result }}
PROVIDER_MODE: ${{ inputs.npm_telegram_provider_mode }}
SCENARIO: ${{ inputs.npm_telegram_scenario }}
run: |
@@ -504,13 +596,13 @@ jobs:
args=(-f package_spec="${PACKAGE_SPEC:-openclaw@beta}" -f harness_ref="$TARGET_SHA" -f provider_mode="$PROVIDER_MODE")
if [[ -z "${PACKAGE_SPEC// }" ]]; then
if [[ -z "${RELEASE_CHECKS_RUN_ID// }" ]]; then
echo "Full release Telegram requires either npm_telegram_package_spec or a release_checks child run with the release-package-under-test artifact." >&2
if [[ "$PREPARE_PACKAGE_RESULT" != "success" || -z "${PACKAGE_ARTIFACT_NAME// }" ]]; then
echo "Full release Telegram requires either npm_telegram_package_spec or a prepared release-package-under-test artifact." >&2
exit 1
fi
args+=(
-f package_artifact_name=release-package-under-test
-f package_artifact_run_id="$RELEASE_CHECKS_RUN_ID"
-f package_artifact_name="$PACKAGE_ARTIFACT_NAME"
-f package_artifact_run_id="${GITHUB_RUN_ID}"
-f package_label="full-release-${TARGET_SHA:0:12}"
)
fi

View File

@@ -92,7 +92,7 @@ jobs:
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
const totalChangedLines = files.reduce((total, file) => {
const path = file.filename ?? "";
if (path === "docs.acp.md" || path.startsWith("docs/") || excludedLockfiles.has(path)) {
if (path.startsWith("docs/") || excludedLockfiles.has(path)) {
return total;
}
return total + (file.additions ?? 0) + (file.deletions ?? 0);
@@ -606,7 +606,7 @@ jobs:
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
const totalChangedLines = files.reduce((total, file) => {
const path = file.filename ?? "";
if (path === "docs.acp.md" || path.startsWith("docs/") || excludedLockfiles.has(path)) {
if (path.startsWith("docs/") || excludedLockfiles.has(path)) {
return total;
}
return total + (file.additions ?? 0) + (file.deletions ?? 0);

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Existing release tag to validate for macOS release handoff (for example v2026.3.22 or v2026.3.22-beta.1)
description: Existing release tag to validate for macOS release handoff (for example v2026.3.22, v2026.3.22-alpha.1, or v2026.3.22-beta.1)
required: true
type: string
preflight_only:
@@ -38,7 +38,7 @@ jobs:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-(alpha|beta)\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
echo "Invalid release tag format: ${RELEASE_TAG}"
exit 1
fi

View File

@@ -152,8 +152,8 @@ jobs:
set -euo pipefail
if [[ -z "${PACKAGE_ARTIFACT_NAME// }" ]]; then
if [[ ! "${PACKAGE_SPEC}" =~ ^openclaw@(beta|latest|[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-[1-9][0-9]*|-beta\.[1-9][0-9]*)?)$ ]]; then
echo "package_spec must be openclaw@beta, openclaw@latest, or an exact OpenClaw release version; got: ${PACKAGE_SPEC}" >&2
if [[ ! "${PACKAGE_SPEC}" =~ ^openclaw@(alpha|beta|latest|[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*(-[1-9][0-9]*|-(alpha|beta)\.[1-9][0-9]*)?)$ ]]; then
echo "package_spec must be openclaw@alpha, openclaw@beta, openclaw@latest, or an exact OpenClaw release version; got: ${PACKAGE_SPEC}" >&2
exit 1
fi
fi

View File

@@ -176,7 +176,7 @@ env:
PNPM_VERSION: "10.32.1"
OPENCLAW_REPOSITORY: openclaw/openclaw
TSX_VERSION: "4.21.0"
OPENCLAW_CROSS_OS_OPENAI_MODEL: ${{ inputs.openai_model || vars.OPENCLAW_CROSS_OS_OPENAI_MODEL || 'openai/gpt-5.5' }}
OPENCLAW_CROSS_OS_OPENAI_MODEL: ${{ inputs.openai_model || vars.OPENCLAW_CROSS_OS_OPENAI_MODEL || 'openai/gpt-5.4' }}
jobs:
prepare:

View File

@@ -395,6 +395,9 @@ jobs:
add_profile_suite native-live-src-agents "stable full"
add_profile_suite native-live-src-gateway-core "minimum stable full"
add_profile_suite native-live-src-gateway-profiles-anthropic "stable full"
add_profile_suite native-live-src-gateway-profiles-anthropic-smoke "stable"
add_profile_suite native-live-src-gateway-profiles-anthropic-opus "full"
add_profile_suite native-live-src-gateway-profiles-anthropic-sonnet-haiku "full"
add_profile_suite native-live-src-gateway-profiles-google "stable full"
add_profile_suite native-live-src-gateway-profiles-minimax "stable full"
add_profile_suite native-live-src-gateway-profiles-openai "minimum stable full"
@@ -418,6 +421,9 @@ jobs:
add_profile_suite live-gateway-google-docker "stable full"
add_profile_suite live-gateway-minimax-docker "stable full"
add_profile_suite live-gateway-advisory-docker "full"
add_profile_suite live-gateway-advisory-docker-deepseek-fireworks "full"
add_profile_suite live-gateway-advisory-docker-opencode-openrouter "full"
add_profile_suite live-gateway-advisory-docker-xai-zai "full"
add_profile_suite live-cli-backend-docker "stable full"
add_profile_suite live-acp-bind-docker "stable full"
add_profile_suite live-codex-harness-docker "stable full"
@@ -978,6 +984,7 @@ jobs:
env:
LANES: ${{ matrix.group.docker_lanes }}
INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }}
INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include_release_path_suites }}
run: |
set -euo pipefail
if [[ -z "$LANES" ]]; then
@@ -988,6 +995,9 @@ jobs:
mkdir -p .artifacts/docker-tests
export OPENCLAW_DOCKER_ALL_LANES="$LANES"
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="$INCLUDE_OPENWEBUI"
if [[ "$INCLUDE_RELEASE_PATH_SUITES" == "true" ]]; then
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
fi
plan_path=".artifacts/docker-tests/targeted-plan.json"
node .release-harness/scripts/test-docker-all.mjs --plan-json > "$plan_path"
@@ -1043,6 +1053,9 @@ jobs:
export OPENCLAW_DOCKER_ALL_PREFLIGHT=0
export OPENCLAW_DOCKER_ALL_FAIL_FAST=0
export OPENCLAW_DOCKER_ALL_INCLUDE_OPENWEBUI="${INCLUDE_OPENWEBUI}"
if [[ "${{ inputs.include_release_path_suites }}" == "true" ]]; then
export OPENCLAW_DOCKER_ALL_PROFILE=release-path
fi
export OPENCLAW_DOCKER_ALL_LOG_DIR=".artifacts/docker-tests/targeted-${{ steps.plan.outputs.artifact_suffix }}"
export OPENCLAW_DOCKER_ALL_TIMINGS_FILE=".artifacts/docker-tests/targeted-${{ steps.plan.outputs.artifact_suffix }}-timings.json"
export OPENCLAW_DOCKER_ALL_PNPM_COMMAND="$(command -v pnpm)"
@@ -1241,6 +1254,9 @@ jobs:
LANES: ${{ inputs.docker_lanes }}
INCLUDE_RELEASE_PATH_SUITES: ${{ inputs.include_release_path_suites }}
INCLUDE_OPENWEBUI: ${{ inputs.include_openwebui }}
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC: ${{ inputs.published_upgrade_survivor_baseline }}
OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPECS: ${{ inputs.published_upgrade_survivor_baselines }}
OPENCLAW_UPGRADE_SURVIVOR_SCENARIOS: ${{ inputs.published_upgrade_survivor_scenarios }}
run: |
set -euo pipefail
mkdir -p .artifacts/docker-tests
@@ -1858,12 +1874,27 @@ jobs:
timeout_minutes: 90
profile_env_only: false
profiles: minimum stable full
- suite_id: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
- suite_id: native-live-src-gateway-profiles-anthropic-smoke
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic smoke
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_SMOKE=1 OPENCLAW_LIVE_GATEWAY_MAX_MODELS=1 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 45
profile_env_only: false
profiles: stable
- suite_id: native-live-src-gateway-profiles-anthropic-opus
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic Opus
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-opus-4-7,anthropic/claude-opus-4-6 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
profile_env_only: false
profiles: stable full
profiles: full
- suite_id: native-live-src-gateway-profiles-anthropic-sonnet-haiku
suite_group: native-live-src-gateway-profiles-anthropic
label: Native live gateway profiles Anthropic Sonnet/Haiku
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=anthropic OPENCLAW_LIVE_GATEWAY_MODELS=anthropic/claude-sonnet-4-6,anthropic/claude-haiku-4-5 node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
timeout_minutes: 90
profile_env_only: false
profiles: full
- suite_id: native-live-src-gateway-profiles-google
label: Native live gateway profiles Google
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=google OPENCLAW_LIVE_GATEWAY_MODELS=google/gemini-3.1-pro-preview,google/gemini-3-flash-preview node .release-harness/scripts/test-live-shard.mjs native-live-src-gateway-profiles
@@ -2040,14 +2071,14 @@ jobs:
OPENCLAW_VITEST_MAX_WORKERS: "2"
steps:
- name: Checkout selected ref
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
uses: actions/checkout@v6
with:
ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
fetch-depth: 1
- name: Checkout trusted live shard harness
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
uses: actions/checkout@v6
with:
ref: ${{ github.sha }}
@@ -2055,7 +2086,7 @@ jobs:
path: .release-harness
- name: Setup Node environment
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
@@ -2063,11 +2094,11 @@ jobs:
install-bun: "true"
- name: Hydrate live auth/profile inputs
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
run: bash scripts/ci-hydrate-live-auth.sh
- name: Configure suite-specific env
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
shell: bash
run: |
set -euo pipefail
@@ -2076,7 +2107,7 @@ jobs:
fi
case "${{ matrix.suite_id }}" in
live-cli-backend-docker)
echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.5" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.4" >> "$GITHUB_ENV"
# Keep the release-blocking CI lane on Codex API-key auth. The
# staged auth-file path remains supported for local maintainer
# reruns, but it can hang on stale subscription/session state in
@@ -2120,7 +2151,7 @@ jobs:
esac
- name: Run ${{ matrix.label }}
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-anthropic' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-anthropic-')) || (inputs.live_suite_filter == 'native-live-src-gateway-profiles-opencode-go' && startsWith(matrix.suite_id, 'native-live-src-gateway-profiles-opencode-go-')))
env:
OPENCLAW_LIVE_COMMAND: ${{ matrix.command }}
OPENCLAW_LIVE_SUITE_ADVISORY: ${{ matrix.advisory }}
@@ -2172,10 +2203,25 @@ jobs:
timeout_minutes: 30
profile_env_only: false
profiles: stable full
- suite_id: live-gateway-advisory-docker
label: Docker live gateway advisory providers
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,fireworks,opencode-go,openrouter,xai,zai OPENCLAW_LIVE_GATEWAY_MAX_MODELS=6 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 35m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 40
- suite_id: live-gateway-advisory-docker-deepseek-fireworks
suite_group: live-gateway-advisory-docker
label: Docker live gateway advisory DeepSeek/Fireworks
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=deepseek,fireworks OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 25m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 30
profile_env_only: false
profiles: full
- suite_id: live-gateway-advisory-docker-opencode-openrouter
suite_group: live-gateway-advisory-docker
label: Docker live gateway advisory OpenCode/OpenRouter
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=opencode-go,openrouter OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 25m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 30
profile_env_only: false
profiles: full
- suite_id: live-gateway-advisory-docker-xai-zai
suite_group: live-gateway-advisory-docker
label: Docker live gateway advisory xAI/Z.ai
command: OPENCLAW_LIVE_GATEWAY_PROVIDERS=xai,zai OPENCLAW_LIVE_GATEWAY_MAX_MODELS=2 OPENCLAW_LIVE_GATEWAY_STEP_TIMEOUT_MS=30000 OPENCLAW_LIVE_GATEWAY_MODEL_TIMEOUT_MS=60000 OPENCLAW_LIVE_DOCKER_REPO_ROOT="$GITHUB_WORKSPACE" timeout --foreground --kill-after=30s 25m bash .release-harness/scripts/test-live-gateway-models-docker.sh
timeout_minutes: 30
profile_env_only: false
profiles: full
- suite_id: live-cli-backend-docker
@@ -2249,14 +2295,14 @@ jobs:
OPENCLAW_VITEST_MAX_WORKERS: "2"
steps:
- name: Checkout selected ref
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
uses: actions/checkout@v6
with:
ref: ${{ needs.validate_selected_ref.outputs.selected_sha }}
fetch-depth: 1
- name: Checkout trusted live shard harness
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
uses: actions/checkout@v6
with:
ref: ${{ github.sha }}
@@ -2264,7 +2310,7 @@ jobs:
path: .release-harness
- name: Setup Node environment
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
uses: ./.github/actions/setup-node-env
with:
node-version: ${{ env.NODE_VERSION }}
@@ -2272,11 +2318,11 @@ jobs:
install-bun: "true"
- name: Hydrate live auth/profile inputs
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
run: bash scripts/ci-hydrate-live-auth.sh
- name: Log in to GHCR
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
with:
registry: ghcr.io
@@ -2284,7 +2330,7 @@ jobs:
password: ${{ github.token }}
- name: Configure suite-specific env
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
shell: bash
run: |
set -euo pipefail
@@ -2293,7 +2339,7 @@ jobs:
fi
case "${{ matrix.suite_id }}" in
live-cli-backend-docker)
echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.5" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.4" >> "$GITHUB_ENV"
echo "OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key" >> "$GITHUB_ENV"
echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV"
@@ -2318,7 +2364,7 @@ jobs:
esac
- name: Run ${{ matrix.label }}
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id)
if: contains(matrix.profiles, inputs.release_test_profile) && (inputs.live_suite_filter == '' || inputs.live_suite_filter == matrix.suite_id || (inputs.live_suite_filter == 'live-gateway-advisory-docker' && startsWith(matrix.suite_id, 'live-gateway-advisory-docker-')))
env:
OPENCLAW_LIVE_COMMAND: ${{ matrix.command }}
run: bash .release-harness/scripts/ci-live-command-retry.sh

View File

@@ -17,11 +17,12 @@ on:
required: false
type: string
npm_dist_tag:
description: npm dist-tag to publish to for stable releases
description: npm dist-tag to publish to
required: true
default: beta
type: choice
options:
- alpha
- beta
- latest
@@ -54,7 +55,7 @@ jobs:
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_REF}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]] && [[ ! "${RELEASE_REF}" =~ ^[0-9a-fA-F]{40}$ ]]; then
if [[ ! "${RELEASE_REF}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-(alpha|beta)\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]] && [[ ! "${RELEASE_REF}" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "Invalid release ref format: ${RELEASE_REF}"
exit 1
fi
@@ -62,6 +63,10 @@ jobs:
echo "Full commit SHA input is only supported for validation-only preflight runs."
exit 1
fi
if [[ "${RELEASE_REF}" == *"-alpha."* && "${RELEASE_NPM_DIST_TAG}" != "alpha" ]]; then
echo "Alpha prerelease tags must publish to npm dist-tag alpha."
exit 1
fi
if [[ "${RELEASE_REF}" == *"-beta."* && "${RELEASE_NPM_DIST_TAG}" != "beta" ]]; then
echo "Beta prerelease tags must publish to npm dist-tag beta."
exit 1
@@ -294,10 +299,14 @@ jobs:
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-(alpha|beta)\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
echo "Invalid release tag format: ${RELEASE_TAG}"
exit 1
fi
if [[ "${RELEASE_TAG}" == *"-alpha."* && "${RELEASE_NPM_DIST_TAG}" != "alpha" ]]; then
echo "Alpha prerelease tags must publish to npm dist-tag alpha."
exit 1
fi
if [[ "${RELEASE_TAG}" == *"-beta."* && "${RELEASE_NPM_DIST_TAG}" != "beta" ]]; then
echo "Beta prerelease tags must publish to npm dist-tag beta."
exit 1

View File

@@ -0,0 +1,530 @@
name: OpenClaw Performance
on:
schedule:
- cron: "11 5 * * *"
workflow_dispatch:
inputs:
target_ref:
description: OpenClaw ref to benchmark; defaults to the workflow ref
required: false
default: ""
type: string
profile:
description: Kova profile to run
required: false
default: diagnostic
type: choice
options:
- smoke
- diagnostic
- soak
- release
repeat:
description: Repeat count for non-profiled Kova runs
required: false
default: "3"
type: string
deep_profile:
description: Run the deep-profile lane with CPU/heap/trace artifacts
required: false
default: false
type: boolean
live_gpt54:
description: Run the live OpenAI GPT 5.4 agent-turn lane
required: false
default: false
type: boolean
fail_on_regression:
description: Fail the workflow when Kova exits non-zero
required: false
default: false
type: boolean
kova_ref:
description: openclaw/Kova Git ref to install
required: false
default: b63b6f9e20efb23641df00487e982230d81a90ac
type: string
permissions:
contents: read
concurrency:
group: ${{ github.event_name == 'workflow_dispatch' && format('{0}-{1}', github.workflow, github.run_id) || format('{0}-{1}', github.workflow, github.ref) }}
cancel-in-progress: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
OCM_VERSION: v0.2.15
KOVA_REPOSITORY: openclaw/Kova
PERFORMANCE_MODEL_ID: gpt-5.4
jobs:
kova:
name: ${{ matrix.title }}
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 240
strategy:
fail-fast: false
matrix:
include:
- lane: mock-provider
title: Kova mock provider performance
auth: mock
repeat: input
deep_profile: "false"
live: "false"
include_filters: "scenario:fresh-install scenario:gateway-performance scenario:bundled-plugin-startup scenario:bundled-runtime-deps scenario:agent-cold-warm-message"
- lane: mock-deep-profile
title: Kova mock provider deep profile
auth: mock
repeat: "1"
deep_profile: "true"
live: "false"
include_filters: "scenario:fresh-install scenario:gateway-performance scenario:agent-cold-warm-message"
- lane: live-gpt54
title: Kova live OpenAI GPT 5.4 agent turn
auth: live
repeat: "1"
deep_profile: "false"
live: "true"
include_filters: "scenario:agent-cold-warm-message"
env:
KOVA_REF: ${{ inputs.kova_ref || 'b63b6f9e20efb23641df00487e982230d81a90ac' }}
KOVA_HOME: ${{ github.workspace }}/.artifacts/kova/home/${{ matrix.lane }}
REPORT_DIR: ${{ github.workspace }}/.artifacts/kova/reports/${{ matrix.lane }}
BUNDLE_DIR: ${{ github.workspace }}/.artifacts/kova/bundles/${{ matrix.lane }}
SUMMARY_DIR: ${{ github.workspace }}/.artifacts/kova/summaries
SOURCE_PERF_DIR: ${{ github.workspace }}/.artifacts/openclaw-performance/source/${{ matrix.lane }}
LANE_ID: ${{ matrix.lane }}
TARGET_REF: ${{ inputs.target_ref || github.ref_name }}
PROFILE: ${{ inputs.profile || 'diagnostic' }}
REQUESTED_REPEAT: ${{ inputs.repeat || '3' }}
FAIL_ON_REGRESSION: ${{ inputs.fail_on_regression || 'false' }}
INCLUDE_FILTERS: ${{ matrix.include_filters }}
AUTH_MODE: ${{ matrix.auth }}
MATRIX_REPEAT: ${{ matrix.repeat }}
MATRIX_DEEP_PROFILE: ${{ matrix.deep_profile }}
MATRIX_LIVE: ${{ matrix.live }}
steps:
- name: Decide lane
id: lane
shell: bash
run: |
set -euo pipefail
run_lane=true
reason=""
if [[ "$LANE_ID" == "mock-deep-profile" && "${{ github.event_name }}" != "schedule" && "${{ inputs.deep_profile || 'false' }}" != "true" ]]; then
run_lane=false
reason="deep_profile input is false"
fi
if [[ "$LANE_ID" == "live-gpt54" && "${{ github.event_name }}" != "schedule" && "${{ inputs.live_gpt54 || 'false' }}" != "true" ]]; then
run_lane=false
reason="live_gpt54 input is false"
fi
echo "run=$run_lane" >> "$GITHUB_OUTPUT"
if [[ "$run_lane" != "true" ]]; then
echo "Skipping ${LANE_ID}: ${reason}" >> "$GITHUB_STEP_SUMMARY"
fi
- name: Detect clawgrit report token
id: clawgrit
if: steps.lane.outputs.run == 'true'
env:
CLAWGRIT_REPORTS_TOKEN: ${{ secrets.CLAWGRIT_REPORTS_TOKEN }}
shell: bash
run: |
set -euo pipefail
if [[ -n "${CLAWGRIT_REPORTS_TOKEN:-}" ]]; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout OpenClaw
if: steps.lane.outputs.run == 'true'
uses: actions/checkout@v6
with:
ref: ${{ inputs.target_ref || github.ref }}
fetch-depth: 1
persist-credentials: false
- name: Record tested revision
if: steps.lane.outputs.run == 'true'
shell: bash
run: |
set -euo pipefail
tested_sha="$(git rev-parse HEAD)"
echo "TESTED_REF=${TARGET_REF}" >> "$GITHUB_ENV"
echo "TESTED_SHA=${tested_sha}" >> "$GITHUB_ENV"
{
echo "Tested ref: ${TARGET_REF}"
echo "Tested SHA: ${tested_sha}"
echo "Workflow ref: ${GITHUB_REF_NAME}"
echo "Workflow SHA: ${GITHUB_SHA}"
} >> "$GITHUB_STEP_SUMMARY"
- name: Set up Node environment
if: steps.lane.outputs.run == 'true'
uses: ./.github/actions/setup-node-env
with:
install-bun: "false"
- name: Install OCM and Kova
if: steps.lane.outputs.run == 'true'
shell: bash
run: |
set -euo pipefail
KOVA_SRC="${RUNNER_TEMP}/kova-src"
echo "KOVA_SRC=$KOVA_SRC" >> "$GITHUB_ENV"
mkdir -p "$HOME/.local/bin" "$(dirname "$KOVA_SRC")"
curl -fsSL https://raw.githubusercontent.com/shakkernerd/ocm/main/install.sh \
| bash -s -- --version "$OCM_VERSION" --prefix "$HOME/.local" --force
git clone --filter=blob:none "https://github.com/${KOVA_REPOSITORY}.git" "$KOVA_SRC"
git -C "$KOVA_SRC" checkout "$KOVA_REF"
cat > "$HOME/.local/bin/kova" <<EOF
#!/usr/bin/env bash
export KOVA_HOME="${KOVA_HOME}"
exec node "${KOVA_SRC}/bin/kova.mjs" "\$@"
EOF
chmod 0755 "$HOME/.local/bin/kova"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Pin Kova OpenAI model to GPT 5.4
if: steps.lane.outputs.run == 'true'
shell: bash
run: |
set -euo pipefail
node - <<'NODE'
const fs = require("node:fs");
const path = require("node:path");
const root = process.env.KOVA_SRC;
const files = [
"support/configure-openclaw-mock-auth.mjs",
"support/configure-openclaw-live-auth.mjs",
"support/mock-openai-server.mjs",
"states/mock-openai-provider.json"
];
for (const rel of files) {
const file = path.join(root, rel);
const before = fs.readFileSync(file, "utf8");
const after = before.replaceAll("gpt-5.5", process.env.PERFORMANCE_MODEL_ID);
fs.writeFileSync(file, after, "utf8");
}
NODE
- name: Kova version and plan sanity
if: steps.lane.outputs.run == 'true'
shell: bash
run: |
set -euo pipefail
kova version --json
kova matrix plan \
--profile "$PROFILE" \
--target "local-build:${GITHUB_WORKSPACE}" \
--include scenario:fresh-install \
--json >/tmp/kova-plan.json
- name: Configure live OpenAI auth
if: ${{ steps.lane.outputs.run == 'true' && matrix.live == 'true' }}
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
shell: bash
run: |
set -euo pipefail
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
echo "OPENAI_API_KEY is not configured; live GPT 5.4 lane will be skipped." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
kova setup --ci --json
kova setup --non-interactive --auth env-only --provider openai --env-var OPENAI_API_KEY --json
- name: Run Kova
id: kova
if: steps.lane.outputs.run == 'true'
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_BASE_URL: ${{ secrets.OPENAI_BASE_URL }}
CLAWGRIT_REPORTS_TOKEN_PRESENT: ${{ steps.clawgrit.outputs.present || 'false' }}
shell: bash
run: |
set -euo pipefail
mkdir -p "$REPORT_DIR" "$BUNDLE_DIR" "$SUMMARY_DIR"
if [[ "$MATRIX_LIVE" == "true" && -z "${OPENAI_API_KEY:-}" ]]; then
echo "skipped=true" >> "$GITHUB_OUTPUT"
exit 0
fi
repeat="$REQUESTED_REPEAT"
if [[ "$MATRIX_REPEAT" != "input" ]]; then
repeat="$MATRIX_REPEAT"
fi
args=(
matrix run
--profile "$PROFILE"
--target "local-build:${GITHUB_WORKSPACE}"
--auth "$AUTH_MODE"
--parallel 1
--repeat "$repeat"
--report-dir "$REPORT_DIR"
--execute
--json
)
for filter in $INCLUDE_FILTERS; do
args+=(--include "$filter")
done
if [[ "$MATRIX_DEEP_PROFILE" == "true" ]]; then
args+=(--deep-profile)
fi
if [[ "$FAIL_ON_REGRESSION" == "true" ]]; then
args+=(--gate)
fi
log_path="$REPORT_DIR/${LANE_ID}.log"
set +e
kova "${args[@]}" 2>&1 | tee "$log_path"
status=${PIPESTATUS[0]}
set -e
report_json="$(find "$REPORT_DIR" -maxdepth 1 -type f -name '*.json' -print | sort | tail -n 1)"
if [[ -z "$report_json" ]]; then
echo "Kova did not write a JSON report." >&2
exit 1
fi
report_md="${report_json%.json}.md"
echo "status=$status" >> "$GITHUB_OUTPUT"
echo "report_json=$report_json" >> "$GITHUB_OUTPUT"
echo "report_md=$report_md" >> "$GITHUB_OUTPUT"
kova report bundle "$report_json" --output-dir "$BUNDLE_DIR" --json | tee "$BUNDLE_DIR/bundle.json"
ref_slug="$(printf '%s' "${TESTED_REF}" | tr -c 'A-Za-z0-9._-' '-')"
run_slug="${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
report_url=""
if [[ "${CLAWGRIT_REPORTS_TOKEN_PRESENT:-false}" == "true" ]]; then
report_url="https://github.com/openclaw/clawgrit-reports/tree/main/openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
fi
summary_path="$SUMMARY_DIR/${LANE_ID}.md"
summary_args=(node scripts/kova-ci-summary.mjs --report "$report_json" --output "$summary_path" --lane "$LANE_ID")
if [[ -n "$report_url" ]]; then
summary_args+=(--report-url "$report_url")
fi
"${summary_args[@]}"
cat >> "$summary_path" <<EOF
## Test scope
- Repository: ${GITHUB_REPOSITORY}
- Tested ref: ${TESTED_REF}
- Tested SHA: ${TESTED_SHA}
- Workflow ref: ${GITHUB_REF_NAME}
- Workflow SHA: ${GITHUB_SHA}
- Kova repository: ${KOVA_REPOSITORY}
- Kova ref: ${KOVA_REF}
- Kova profile: ${PROFILE}
- Lane auth: ${AUTH_MODE}
- Lane model: ${PERFORMANCE_MODEL_ID}
- Lane repeat: ${repeat}
- Include filters: ${INCLUDE_FILTERS}
EOF
cat "$summary_path" >> "$GITHUB_STEP_SUMMARY"
if [[ "$FAIL_ON_REGRESSION" == "true" && "$status" != "0" ]]; then
exit "$status"
fi
- name: Run OpenClaw source performance probes
if: ${{ steps.lane.outputs.run == 'true' && matrix.lane == 'mock-provider' }}
shell: bash
run: |
set -euo pipefail
source_runs="$REQUESTED_REPEAT"
if ! [[ "$source_runs" =~ ^[0-9]+$ ]] || [[ "$source_runs" -lt 1 ]]; then
source_runs=3
fi
mkdir -p "$SOURCE_PERF_DIR/mock-hello"
pnpm build
pnpm test:gateway:cpu-scenarios \
--output-dir "$SOURCE_PERF_DIR/gateway-cpu" \
--runs "$source_runs" \
--warmup 1 \
--skip-qa \
--startup-case default \
--startup-case skipChannels \
--startup-case oneInternalHook \
--startup-case allInternalHooks \
--startup-case fiftyPlugins \
--startup-case fiftyStartupLazyPlugins
for run_index in $(seq 1 "$source_runs"); do
run_dir="$SOURCE_PERF_DIR/mock-hello/run-$(printf '%03d' "$run_index")"
pnpm openclaw qa suite \
--provider-mode mock-openai \
--model "mock-openai/${PERFORMANCE_MODEL_ID}" \
--concurrency 1 \
--output-dir "$(realpath --relative-to="$GITHUB_WORKSPACE" "$run_dir")" \
--scenario channel-chat-baseline
done
gateway_home="$(mktemp -d)"
gateway_port="$(node -e "const net=require('node:net'); const s=net.createServer(); s.listen(0,'127.0.0.1',()=>{ console.log(s.address().port); s.close(); });")"
gateway_state="$gateway_home/.openclaw"
gateway_config="$gateway_state/openclaw.json"
gateway_log="$SOURCE_PERF_DIR/cli-gateway.log"
gateway_pid=""
mkdir -p "$gateway_state"
cat > "$gateway_config" <<EOF
{
"browser": { "enabled": false },
"gateway": {
"mode": "local",
"port": ${gateway_port},
"bind": "loopback",
"auth": { "mode": "none" },
"controlUi": { "enabled": false },
"tailscale": { "mode": "off" }
},
"plugins": {
"enabled": true,
"entries": { "browser": { "enabled": false } }
}
}
EOF
cleanup_gateway() {
if [[ -n "${gateway_pid:-}" ]] && kill -0 "$gateway_pid" 2>/dev/null; then
kill "$gateway_pid" 2>/dev/null || true
wait "$gateway_pid" 2>/dev/null || true
fi
rm -rf "$gateway_home"
}
trap cleanup_gateway EXIT
OPENCLAW_HOME="$gateway_home" OPENCLAW_STATE_DIR="$gateway_state" OPENCLAW_CONFIG_PATH="$gateway_config" OPENCLAW_GATEWAY_PORT="$gateway_port" OPENCLAW_SKIP_CHANNELS=1 \
node dist/entry.js gateway run --bind loopback --port "$gateway_port" --auth none --allow-unconfigured --force \
>"$gateway_log" 2>&1 &
gateway_pid="$!"
for _ in $(seq 1 120); do
if curl -fsS "http://127.0.0.1:${gateway_port}/healthz" >/dev/null; then
break
fi
if ! kill -0 "$gateway_pid" 2>/dev/null; then
cat "$gateway_log" >&2
exit 1
fi
sleep 1
done
curl -fsS "http://127.0.0.1:${gateway_port}/healthz" >/dev/null
OPENCLAW_HOME="$gateway_home" OPENCLAW_STATE_DIR="$gateway_state" OPENCLAW_CONFIG_PATH="$gateway_config" OPENCLAW_GATEWAY_PORT="$gateway_port" \
node --import tsx scripts/bench-cli-startup.ts \
--case gatewayHealthJson \
--case configGetGatewayPort \
--runs "$source_runs" \
--warmup 1 \
--output "$SOURCE_PERF_DIR/cli-startup.json"
cleanup_gateway
trap - EXIT
pnpm perf:source:summary \
--source-dir "$SOURCE_PERF_DIR" \
--output "$SOURCE_PERF_DIR/index.md"
cat "$SOURCE_PERF_DIR/index.md" >> "$GITHUB_STEP_SUMMARY"
- name: Upload Kova artifacts
if: ${{ always() && steps.lane.outputs.run == 'true' }}
uses: actions/upload-artifact@v5
with:
name: openclaw-performance-${{ matrix.lane }}-${{ github.run_id }}-${{ github.run_attempt }}
path: |
.artifacts/kova/reports/${{ matrix.lane }}
.artifacts/kova/bundles/${{ matrix.lane }}
.artifacts/kova/summaries/${{ matrix.lane }}.md
.artifacts/openclaw-performance/source/${{ matrix.lane }}
if-no-files-found: ignore
retention-days: ${{ matrix.deep_profile == 'true' && 14 || 30 }}
- name: Prepare clawgrit reports checkout
if: ${{ steps.kova.outputs.report_json != '' && steps.clawgrit.outputs.present == 'true' }}
env:
CLAWGRIT_REPORTS_TOKEN: ${{ secrets.CLAWGRIT_REPORTS_TOKEN }}
shell: bash
run: |
set -euo pipefail
reports_root=".artifacts/clawgrit-reports"
mkdir -p "$reports_root"
git -C "$reports_root" init -b main
git -C "$reports_root" remote add origin https://github.com/openclaw/clawgrit-reports.git
auth_header="$(printf 'x-access-token:%s' "$CLAWGRIT_REPORTS_TOKEN" | base64 -w0)"
git -C "$reports_root" config http.https://github.com/.extraheader "AUTHORIZATION: basic ${auth_header}"
if git -C "$reports_root" ls-remote --exit-code --heads origin main >/dev/null 2>&1; then
git -C "$reports_root" fetch --depth=1 origin main
git -C "$reports_root" checkout -B main FETCH_HEAD
else
git -C "$reports_root" checkout -B main
fi
- name: Publish to clawgrit reports
if: ${{ steps.kova.outputs.report_json != '' && steps.clawgrit.outputs.present == 'true' }}
shell: bash
run: |
set -euo pipefail
reports_root=".artifacts/clawgrit-reports"
ref_slug="$(printf '%s' "${TESTED_REF}" | tr -c 'A-Za-z0-9._-' '-')"
run_slug="${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
dest="${reports_root}/openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
mkdir -p "$dest"
cp "${{ steps.kova.outputs.report_json }}" "$dest/report.json"
if [[ -f "${{ steps.kova.outputs.report_md }}" ]]; then
cp "${{ steps.kova.outputs.report_md }}" "$dest/report.md"
fi
cp "$SUMMARY_DIR/${LANE_ID}.md" "$dest/index.md"
if [[ -d "$BUNDLE_DIR" ]]; then
mkdir -p "$dest/bundles"
cp -R "$BUNDLE_DIR"/. "$dest/bundles/"
fi
if [[ -d "$SOURCE_PERF_DIR" ]]; then
mkdir -p "$dest/source"
cp -R "$SOURCE_PERF_DIR"/. "$dest/source/"
if [[ -f "$SOURCE_PERF_DIR/index.md" ]]; then
cat >> "$dest/index.md" <<'EOF'
## Source probes
Additional gateway boot, memory, plugin pressure, mock hello-loop, and CLI startup numbers are in [source/index.md](source/index.md).
EOF
fi
fi
cat > "${reports_root}/openclaw-performance/${ref_slug}/latest-${LANE_ID}.json" <<EOF
{
"repository": "${GITHUB_REPOSITORY}",
"ref": "${TESTED_REF}",
"sha": "${TESTED_SHA}",
"tested_ref": "${TESTED_REF}",
"tested_sha": "${TESTED_SHA}",
"workflow_ref": "${GITHUB_REF_NAME}",
"workflow_sha": "${GITHUB_SHA}",
"workflow": "${GITHUB_WORKFLOW}",
"run_id": "${GITHUB_RUN_ID}",
"run_attempt": "${GITHUB_RUN_ATTEMPT}",
"lane": "${LANE_ID}",
"path": "openclaw-performance/${ref_slug}/${run_slug}/${LANE_ID}"
}
EOF
git -C "$reports_root" config user.name "openclaw-performance[bot]"
git -C "$reports_root" config user.email "openclaw-performance[bot]@users.noreply.github.com"
git -C "$reports_root" add openclaw-performance
if git -C "$reports_root" diff --cached --quiet; then
echo "No clawgrit report changes to publish."
exit 0
fi
git -C "$reports_root" commit -m "perf: add OpenClaw ${LANE_ID} report ${TESTED_SHA::12}"
git -C "$reports_root" push origin HEAD:main

View File

@@ -58,6 +58,11 @@ on:
required: false
default: ""
type: string
package_acceptance_package_spec:
description: Optional published package spec for Package Acceptance; blank uses the prepared release artifact
required: false
default: ""
type: string
concurrency:
group: openclaw-release-checks-${{ inputs.expected_sha || inputs.ref }}-${{ inputs.rerun_group }}
@@ -83,6 +88,7 @@ jobs:
release_profile: ${{ steps.inputs.outputs.release_profile }}
rerun_group: ${{ steps.inputs.outputs.rerun_group }}
live_suite_filter: ${{ steps.inputs.outputs.live_suite_filter }}
package_acceptance_package_spec: ${{ steps.inputs.outputs.package_acceptance_package_spec }}
steps:
- name: Require main or release workflow ref for release checks
env:
@@ -199,6 +205,7 @@ jobs:
RELEASE_PROFILE_INPUT: ${{ inputs.release_profile }}
RELEASE_RERUN_GROUP_INPUT: ${{ inputs.rerun_group }}
RELEASE_LIVE_SUITE_FILTER_INPUT: ${{ inputs.live_suite_filter }}
RELEASE_PACKAGE_ACCEPTANCE_PACKAGE_SPEC_INPUT: ${{ inputs.package_acceptance_package_spec }}
run: |
set -euo pipefail
{
@@ -208,6 +215,7 @@ jobs:
printf 'release_profile=%s\n' "$RELEASE_PROFILE_INPUT"
printf 'rerun_group=%s\n' "$RELEASE_RERUN_GROUP_INPUT"
printf 'live_suite_filter=%s\n' "$RELEASE_LIVE_SUITE_FILTER_INPUT"
printf 'package_acceptance_package_spec=%s\n' "$RELEASE_PACKAGE_ACCEPTANCE_PACKAGE_SPEC_INPUT"
} >> "$GITHUB_OUTPUT"
- name: Summarize validated ref
@@ -220,6 +228,7 @@ jobs:
RELEASE_PROFILE: ${{ inputs.release_profile }}
RELEASE_RERUN_GROUP: ${{ inputs.rerun_group }}
RELEASE_LIVE_SUITE_FILTER: ${{ inputs.live_suite_filter }}
PACKAGE_ACCEPTANCE_PACKAGE_SPEC: ${{ inputs.package_acceptance_package_spec }}
run: |
{
echo "## Release checks"
@@ -234,6 +243,11 @@ jobs:
if [[ -n "${RELEASE_LIVE_SUITE_FILTER// }" ]]; then
echo "- Live suite filter: \`${RELEASE_LIVE_SUITE_FILTER}\`"
fi
if [[ -n "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
echo "- Package Acceptance package spec: \`${PACKAGE_ACCEPTANCE_PACKAGE_SPEC}\`"
else
echo "- Package Acceptance package spec: prepared release artifact"
fi
echo "- This run will execute cross-OS release validation, install smoke, QA Lab parity, Matrix, and Telegram lanes, and the non-Parallels Docker/live/openwebui coverage from the CI migration plan."
} >> "$GITHUB_STEP_SUMMARY"
@@ -333,7 +347,7 @@ jobs:
candidate_file_name: openclaw-current.tgz
candidate_version: ${{ needs.prepare_release_package.outputs.package_version }}
candidate_source_sha: ${{ needs.prepare_release_package.outputs.source_sha }}
openai_model: openai/gpt-5.5
openai_model: openai/gpt-5.4
secrets:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -439,12 +453,13 @@ jobs:
uses: ./.github/workflows/package-acceptance.yml
with:
workflow_ref: ${{ github.ref_name }}
source: artifact
source: ${{ needs.resolve_target.outputs.package_acceptance_package_spec != '' && 'npm' || 'artifact' }}
package_spec: ${{ needs.resolve_target.outputs.package_acceptance_package_spec || 'openclaw@beta' }}
artifact_name: ${{ needs.prepare_release_package.outputs.artifact_name }}
package_sha256: ${{ needs.prepare_release_package.outputs.package_sha256 }}
suite_profile: custom
docker_lanes: doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update
published_upgrade_survivor_baselines: release-history
published_upgrade_survivor_baselines: all-since-2026.4.23
published_upgrade_survivor_scenarios: reported-issues
telegram_mode: mock-openai
telegram_scenarios: telegram-help-command,telegram-commands-command,telegram-tools-compact-command,telegram-whoami-command,telegram-context-command,telegram-mention-gating

View File

@@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Release tag to publish, for example v2026.5.1-beta.1
description: Release tag to publish, for example v2026.5.1-alpha.1 or v2026.5.1-beta.1
required: true
type: string
preflight_run_id:
@@ -17,6 +17,7 @@ on:
default: beta
type: choice
options:
- alpha
- beta
- latest
plugin_publish_scope:
@@ -69,10 +70,14 @@ jobs:
WORKFLOW_REF: ${{ github.ref }}
run: |
set -euo pipefail
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-(alpha|beta)\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
echo "Invalid release tag: ${RELEASE_TAG}" >&2
exit 1
fi
if [[ "${RELEASE_TAG}" == *"-alpha."* && "${RELEASE_NPM_DIST_TAG}" != "alpha" ]]; then
echo "Alpha prerelease tags must publish OpenClaw to npm dist-tag alpha." >&2
exit 1
fi
if [[ "${RELEASE_TAG}" == *"-beta."* && "${RELEASE_NPM_DIST_TAG}" != "beta" ]]; then
echo "Beta prerelease tags must publish OpenClaw to npm dist-tag beta." >&2
exit 1

View File

@@ -70,7 +70,7 @@ on:
default: openclaw@latest
type: string
published_upgrade_survivor_baselines:
description: Optional baseline list for published-upgrade-survivor/update-migration; use release-history or all-since-2026.4.23
description: Optional baseline list for published-upgrade-survivor/update-migration; use all-since-2026.4.23, release-history, or exact versions
required: false
default: ""
type: string
@@ -150,7 +150,7 @@ on:
default: openclaw@latest
type: string
published_upgrade_survivor_baselines:
description: Optional baseline list for published-upgrade-survivor/update-migration; use release-history or all-since-2026.4.23
description: Optional baseline list for published-upgrade-survivor/update-migration; use all-since-2026.4.23, release-history, or exact versions
required: false
default: ""
type: string

View File

@@ -1,109 +0,0 @@
name: Parity gate
on:
schedule:
- cron: "17 3 * * *"
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: parity-gate-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
jobs:
parity-gate:
name: Run the OpenAI / Opus 4.6 parity gate against the qa-lab mock
runs-on: blacksmith-32vcpu-ubuntu-2404
timeout-minutes: 30
env:
# Fence the gate off from any real provider credentials. The qa-lab
# mock server + auth staging (PR N) should be enough to produce a
# meaningful verdict without touching a real API. If any of these
# leak into the job env, fail hard instead of silently running
# against a live provider and burning real budget.
#
# The parity pack has 11 isolated scenario workers. It exercises a real
# gateway child plus mock model turns and subagents, so keep it serial in
# CI even on the larger runner. Concurrent isolated gateway workers make
# the short strict-agentic scenarios flaky, especially the approval-turn
# followthrough gate that expects a fast post-approval read within a 30s
# agent.wait timeout.
QA_PARITY_CONCURRENCY: "1"
OPENCLAW_CI_OPENAI_MODEL: ${{ vars.OPENCLAW_CI_OPENAI_MODEL || 'openai/gpt-5.5' }}
OPENCLAW_QA_TRANSPORT_READY_TIMEOUT_MS: "180000"
OPENAI_API_KEY: ""
ANTHROPIC_API_KEY: ""
OPENCLAW_LIVE_OPENAI_KEY: ""
OPENCLAW_LIVE_ANTHROPIC_KEY: ""
OPENCLAW_LIVE_GEMINI_KEY: ""
OPENCLAW_LIVE_SETUP_TOKEN_VALUE: ""
# The parity suite is a private QA command. Build that exact runtime up
# front so CI never tests a public dist plus a later no-clean QA overlay.
OPENCLAW_BUILD_PRIVATE_QA: "1"
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
steps:
- name: Checkout PR
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Install pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: "22.18.0"
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build private QA runtime
run: pnpm build
# The approval-turn sentinel still runs inside the full parity pack below.
# Keep the exact mock read-plan contract in deterministic unit tests instead
# of paying for a separate full-runtime preflight that has been flaky in CI.
- name: Run OpenAI candidate lane
run: |
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model "${OPENCLAW_CI_OPENAI_MODEL}" \
--alt-model openai/gpt-5.4-alt \
--output-dir .artifacts/qa-e2e/gpt54
- name: Run Opus 4.6 lane
run: |
pnpm openclaw qa suite \
--provider-mode mock-openai \
--parity-pack agentic \
--concurrency "${QA_PARITY_CONCURRENCY}" \
--model anthropic/claude-opus-4-6 \
--alt-model anthropic/claude-sonnet-4-6 \
--output-dir .artifacts/qa-e2e/opus46
- name: Generate parity report
run: |
pnpm openclaw qa parity-report \
--repo-root . \
--candidate-summary .artifacts/qa-e2e/gpt54/qa-suite-summary.json \
--baseline-summary .artifacts/qa-e2e/opus46/qa-suite-summary.json \
--candidate-label "${OPENCLAW_CI_OPENAI_MODEL}" \
--baseline-label anthropic/claude-opus-4-6 \
--output-dir .artifacts/qa-e2e/parity
- name: Upload parity artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: parity-gate-${{ github.event.pull_request.number || github.sha }}
path: .artifacts/qa-e2e/
retention-days: 14
if-no-files-found: warn

View File

@@ -223,5 +223,4 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
OPENCLAW_NPM_PUBLISH_AUTH_MODE: trusted-publisher
run: bash scripts/plugin-npm-publish.sh --publish "${{ matrix.plugin.packageDir }}"

View File

@@ -141,7 +141,7 @@ jobs:
} >> "$GITHUB_STEP_SUMMARY"
run_mock_parity:
name: Run QA Lab parity gate
name: Run QA Lab mock parity lane
needs: [validate_selected_ref]
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 30

View File

@@ -4,14 +4,14 @@ on:
push:
branches: [main]
paths:
- Dockerfile.sandbox
- Dockerfile.sandbox-common
- scripts/docker/sandbox/Dockerfile
- scripts/docker/sandbox/Dockerfile.common
- scripts/sandbox-common-setup.sh
pull_request:
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
paths:
- Dockerfile.sandbox
- Dockerfile.sandbox-common
- scripts/docker/sandbox/Dockerfile
- scripts/docker/sandbox/Dockerfile.common
- scripts/sandbox-common-setup.sh
permissions:

View File

@@ -162,7 +162,7 @@ jobs:
bad_paths="$(
git diff --name-only | while IFS= read -r path; do
case "$path" in
apps/*|extensions/*|packages/*|scripts/*|src/*|Swabble/*|test/*|ui/*) ;;
apps/*|extensions/*|packages/*|scripts/*|src/*|test/*|ui/*) ;;
*) printf '%s\n' "$path" ;;
esac
done
@@ -240,7 +240,7 @@ jobs:
git config user.name "openclaw-test-performance-agent[bot]"
git config user.email "openclaw-test-performance-agent[bot]@users.noreply.github.com"
git add apps extensions packages scripts src Swabble test ui
git add apps extensions packages scripts src test ui
git commit --no-verify -m "test: optimize slow tests"
for attempt in 1 2 3 4 5; do

25
.gitignore vendored
View File

@@ -14,7 +14,7 @@ coverage
__openclaw_vitest__/
__pycache__/
*.pyc
.tsbuildinfo
*.tsbuildinfo
.pnpm-store
.worktrees/
.DS_Store
@@ -93,8 +93,11 @@ docs/internal/
tmp/
IDENTITY.md
USER.md
.tgz
*.tgz
*.tar.gz
*.zip
.idea
.vscode/
# local tooling
.serena/
@@ -152,7 +155,10 @@ apps/ios/LocalSigning.xcconfig
# Xcode build directories (xcodebuild output)
apps/ios/build/
apps/shared/OpenClawKit/build/
Swabble/build/
apps/swabble/build/
*.xcresult
*.trace
*.profraw
# Generated protocol schema (produced via pnpm protocol:gen)
dist/protocol.schema.json
@@ -185,8 +191,21 @@ changelog/fragments/
# Local scratch workspace
.tmp/
.cache/
.pytest_cache/
.ruff_cache/
.mypy_cache/
.vmux*
.artifacts/
.openclaw-config-doc-cache/
openclaw-path-alias-*/
/.pi/
/C:\\openclaw/
*.log
*.tmp
*.heapsnapshot
*.cpuprofile
*.prof
test/fixtures/openclaw-vitest-unit-report.json
analysis/
.artifacts/qa-e2e/

View File

@@ -1,16 +0,0 @@
{
"gitignore": true,
"noSymlinks": true,
"ignore": [
"**/node_modules/**",
"**/dist/**",
"dist/**",
"**/.git/**",
"**/coverage/**",
"**/build/**",
"**/.build/**",
"**/.artifacts/**",
"docs/zh-CN/**",
"**/CHANGELOG.md"
]
}

View File

@@ -1,13 +0,0 @@
# Canonical contributor identity mappings for cherry-picked commits.
bmendonca3 <208517100+bmendonca3@users.noreply.github.com> <brianmendonca@Brians-MacBook-Air.local>
hcl <7755017+hclsys@users.noreply.github.com> <chenglunhu@gmail.com>
Glucksberg <80581902+Glucksberg@users.noreply.github.com> <markuscontasul@gmail.com>
JackyWay <53031570+JackyWay@users.noreply.github.com> <jackybbc@gmail.com>
Marcus Castro <7562095+mcaxtr@users.noreply.github.com> <mcaxtr@gmail.com>
Marc Gratch <2238658+mgratch@users.noreply.github.com> <me@marcgratch.com>
Peter Machona <7957943+chilu18@users.noreply.github.com> <chilu.machona@icloud.com>
Ben Marvell <92585+easternbloc@users.noreply.github.com> <ben@marvell.consulting>
zerone0x <39543393+zerone0x@users.noreply.github.com> <hi@trine.dev>
Marco Di Dionisio <3519682+marcodd23@users.noreply.github.com> <m.didionisio23@gmail.com>
mujiannan <46643837+mujiannan@users.noreply.github.com> <shennan@mujiannan.com>
Santhanakrishnan <239082898+bitfoundry-ai@users.noreply.github.com> <noreply@anthropic.com>

View File

@@ -1,3 +0,0 @@
**/node_modules/
**/.runtime-deps-*/
docs/.generated/

View File

@@ -10,7 +10,6 @@
"useTabs": false,
"ignorePatterns": [
"apps/",
"assets/",
"CLAUDE.md",
"docker-compose.yml",
"dist/",
@@ -21,7 +20,8 @@
"src/gateway/server-methods/CLAUDE.md",
"src/auto-reply/reply/export-html/",
"src/canvas-host/a2ui/a2ui.bundle.js",
"Swabble/",
"test/fixtures/agents/prompt-snapshots/codex-model-catalog/*.instructions.md",
"test/fixtures/agents/prompt-snapshots/happy-path/*.md",
"vendor/",
],
}

View File

@@ -113,19 +113,19 @@
"vitest/prefer-expect-type-of": "error"
},
"ignorePatterns": [
"assets/",
"dist/",
"dist-runtime/",
"docs/_layouts/",
"extensions/diffs/assets/viewer-runtime.js",
"node_modules/",
"patches/",
"pnpm-lock.yaml",
"skills/",
"src/auto-reply/reply/export-html/template.js",
"src/canvas-host/a2ui/a2ui.bundle.js",
"Swabble/",
"vendor/",
"**/.cache/**",
"**/.openclaw-runtime-deps-copy-*/**",
"**/build/**",
"**/coverage/**",
"**/dist/**",

View File

@@ -1,117 +0,0 @@
/**
* Diff Extension
*
* /diff command shows modified/deleted/new files from git status and opens
* the selected file in VS Code's diff view.
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { showPagedSelectList } from "./ui/paged-select";
interface FileInfo {
status: string;
statusLabel: string;
file: string;
}
export default function (pi: ExtensionAPI) {
pi.registerCommand("diff", {
description: "Show git changes and open in VS Code diff view",
handler: async (_args, ctx) => {
if (!ctx.hasUI) {
ctx.ui.notify("No UI available", "error");
return;
}
// Get changed files from git status
const result = await pi.exec("git", ["status", "--porcelain"], { cwd: ctx.cwd });
if (result.code !== 0) {
ctx.ui.notify(`git status failed: ${result.stderr}`, "error");
return;
}
if (!result.stdout || !result.stdout.trim()) {
ctx.ui.notify("No changes in working tree", "info");
return;
}
// Parse git status output
// Format: XY filename (where XY is two-letter status, then space, then filename)
const lines = result.stdout.split("\n");
const files: FileInfo[] = [];
for (const line of lines) {
if (line.length < 4) {
continue;
} // Need at least "XY f"
const status = line.slice(0, 2);
const file = line.slice(2).trimStart();
// Translate status codes to short labels
let statusLabel: string;
if (status.includes("M")) {
statusLabel = "M";
} else if (status.includes("A")) {
statusLabel = "A";
} else if (status.includes("D")) {
statusLabel = "D";
} else if (status.includes("?")) {
statusLabel = "?";
} else if (status.includes("R")) {
statusLabel = "R";
} else if (status.includes("C")) {
statusLabel = "C";
} else {
statusLabel = status.trim() || "~";
}
files.push({ status: statusLabel, statusLabel, file });
}
if (files.length === 0) {
ctx.ui.notify("No changes found", "info");
return;
}
const openSelected = async (fileInfo: FileInfo): Promise<void> => {
try {
// Open in VS Code diff view.
// For untracked files, git difftool won't work, so fall back to just opening the file.
if (fileInfo.status === "?") {
await pi.exec("code", ["-g", fileInfo.file], { cwd: ctx.cwd });
return;
}
const diffResult = await pi.exec(
"git",
["difftool", "-y", "--tool=vscode", fileInfo.file],
{
cwd: ctx.cwd,
},
);
if (diffResult.code !== 0) {
await pi.exec("code", ["-g", fileInfo.file], { cwd: ctx.cwd });
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
ctx.ui.notify(`Failed to open ${fileInfo.file}: ${message}`, "error");
}
};
const items = files.map((file) => ({
value: file,
label: `${file.status} ${file.file}`,
}));
await showPagedSelectList({
ctx,
title: " Select file to diff",
items,
onSelect: (item) => {
void openSelected(item.value as FileInfo);
},
});
},
});
}

View File

@@ -1,134 +0,0 @@
/**
* Files Extension
*
* /files command lists all files the model has read/written/edited in the active session branch,
* coalesced by path and sorted newest first. Selecting a file opens it in VS Code.
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { showPagedSelectList } from "./ui/paged-select";
interface FileEntry {
path: string;
operations: Set<"read" | "write" | "edit">;
lastTimestamp: number;
}
type FileToolName = "read" | "write" | "edit";
export default function (pi: ExtensionAPI) {
pi.registerCommand("files", {
description: "Show files read/written/edited in this session",
handler: async (_args, ctx) => {
if (!ctx.hasUI) {
ctx.ui.notify("No UI available", "error");
return;
}
// Get the current branch (path from leaf to root)
const branch = ctx.sessionManager.getBranch();
// First pass: collect tool calls (id -> {path, name}) from assistant messages
const toolCalls = new Map<string, { path: string; name: FileToolName; timestamp: number }>();
for (const entry of branch) {
if (entry.type !== "message") {
continue;
}
const msg = entry.message;
if (msg.role === "assistant" && Array.isArray(msg.content)) {
for (const block of msg.content) {
if (block.type === "toolCall") {
const name = block.name;
if (name === "read" || name === "write" || name === "edit") {
const path = block.arguments?.path;
if (path && typeof path === "string") {
toolCalls.set(block.id, { path, name, timestamp: msg.timestamp });
}
}
}
}
}
}
// Second pass: match tool results to get the actual execution timestamp
const fileMap = new Map<string, FileEntry>();
for (const entry of branch) {
if (entry.type !== "message") {
continue;
}
const msg = entry.message;
if (msg.role === "toolResult") {
const toolCall = toolCalls.get(msg.toolCallId);
if (!toolCall) {
continue;
}
const { path, name } = toolCall;
const timestamp = msg.timestamp;
const existing = fileMap.get(path);
if (existing) {
existing.operations.add(name);
if (timestamp > existing.lastTimestamp) {
existing.lastTimestamp = timestamp;
}
} else {
fileMap.set(path, {
path,
operations: new Set([name]),
lastTimestamp: timestamp,
});
}
}
}
if (fileMap.size === 0) {
ctx.ui.notify("No files read/written/edited in this session", "info");
return;
}
// Sort by most recent first
const files = Array.from(fileMap.values()).toSorted(
(a, b) => b.lastTimestamp - a.lastTimestamp,
);
const openSelected = async (file: FileEntry): Promise<void> => {
try {
await pi.exec("code", ["-g", file.path], { cwd: ctx.cwd });
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
ctx.ui.notify(`Failed to open ${file.path}: ${message}`, "error");
}
};
const items = files.map((file) => {
const ops: string[] = [];
if (file.operations.has("read")) {
ops.push("R");
}
if (file.operations.has("write")) {
ops.push("W");
}
if (file.operations.has("edit")) {
ops.push("E");
}
return {
value: file,
label: `${ops.join("")} ${file.path}`,
};
});
await showPagedSelectList({
ctx,
title: " Select file to open",
items,
onSelect: (item) => {
void openSelected(item.value as FileEntry);
},
});
},
});
}

View File

@@ -1,190 +0,0 @@
import {
DynamicBorder,
type ExtensionAPI,
type ExtensionContext,
} from "@mariozechner/pi-coding-agent";
import { Container, Text } from "@mariozechner/pi-tui";
const PR_PROMPT_PATTERN = /^\s*You are given one or more GitHub PR URLs:\s*(\S+)/im;
const ISSUE_PROMPT_PATTERN = /^\s*Analyze GitHub issue\(s\):\s*(\S+)/im;
type PromptMatch = {
kind: "pr" | "issue";
url: string;
};
type GhMetadata = {
title?: string;
author?: {
login?: string;
name?: string | null;
};
};
function extractPromptMatch(prompt: string): PromptMatch | undefined {
const prMatch = prompt.match(PR_PROMPT_PATTERN);
if (prMatch?.[1]) {
return { kind: "pr", url: prMatch[1].trim() };
}
const issueMatch = prompt.match(ISSUE_PROMPT_PATTERN);
if (issueMatch?.[1]) {
return { kind: "issue", url: issueMatch[1].trim() };
}
return undefined;
}
async function fetchGhMetadata(
pi: ExtensionAPI,
kind: PromptMatch["kind"],
url: string,
): Promise<GhMetadata | undefined> {
const args =
kind === "pr"
? ["pr", "view", url, "--json", "title,author"]
: ["issue", "view", url, "--json", "title,author"];
try {
const result = await pi.exec("gh", args);
if (result.code !== 0 || !result.stdout) {
return undefined;
}
return JSON.parse(result.stdout) as GhMetadata;
} catch {
return undefined;
}
}
function formatAuthor(author?: GhMetadata["author"]): string | undefined {
if (!author) {
return undefined;
}
const name = author.name?.trim();
const login = author.login?.trim();
if (name && login) {
return `${name} (@${login})`;
}
if (login) {
return `@${login}`;
}
if (name) {
return name;
}
return undefined;
}
export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
const setWidget = (
ctx: ExtensionContext,
match: PromptMatch,
title?: string,
authorText?: string,
) => {
ctx.ui.setWidget("prompt-url", (_tui, thm) => {
const titleText = title ? thm.fg("accent", title) : thm.fg("accent", match.url);
const authorLine = authorText ? thm.fg("muted", authorText) : undefined;
const urlLine = thm.fg("dim", match.url);
const lines = [titleText];
if (authorLine) {
lines.push(authorLine);
}
lines.push(urlLine);
const container = new Container();
container.addChild(new DynamicBorder((s: string) => thm.fg("muted", s)));
container.addChild(new Text(lines.join("\n"), 1, 0));
return container;
});
};
const applySessionName = (ctx: ExtensionContext, match: PromptMatch, title?: string) => {
const label = match.kind === "pr" ? "PR" : "Issue";
const trimmedTitle = title?.trim();
const fallbackName = `${label}: ${match.url}`;
const desiredName = trimmedTitle ? `${label}: ${trimmedTitle} (${match.url})` : fallbackName;
const currentName = pi.getSessionName()?.trim();
if (!currentName) {
pi.setSessionName(desiredName);
return;
}
if (currentName === match.url || currentName === fallbackName) {
pi.setSessionName(desiredName);
}
};
const renderPromptMatch = (ctx: ExtensionContext, match: PromptMatch) => {
setWidget(ctx, match);
applySessionName(ctx, match);
void fetchGhMetadata(pi, match.kind, match.url).then((meta) => {
const title = meta?.title?.trim();
const authorText = formatAuthor(meta?.author);
setWidget(ctx, match, title, authorText);
applySessionName(ctx, match, title);
});
};
pi.on("before_agent_start", async (event, ctx) => {
if (!ctx.hasUI) {
return;
}
const match = extractPromptMatch(event.prompt);
if (!match) {
return;
}
renderPromptMatch(ctx, match);
});
pi.on("session_switch", async (_event, ctx) => {
rebuildFromSession(ctx);
});
const getUserText = (content: string | { type: string; text?: string }[] | undefined): string => {
if (!content) {
return "";
}
if (typeof content === "string") {
return content;
}
return (
content
.filter((block): block is { type: "text"; text: string } => block.type === "text")
.map((block) => block.text)
.join("\n") ?? ""
);
};
const rebuildFromSession = (ctx: ExtensionContext) => {
if (!ctx.hasUI) {
return;
}
const entries = ctx.sessionManager.getEntries();
const lastMatch = [...entries].toReversed().find((entry) => {
if (entry.type !== "message" || entry.message.role !== "user") {
return false;
}
const text = getUserText(entry.message.content);
return !!extractPromptMatch(text);
});
const content =
lastMatch?.type === "message" && lastMatch.message.role === "user"
? lastMatch.message.content
: undefined;
const text = getUserText(content);
const match = text ? extractPromptMatch(text) : undefined;
if (!match) {
ctx.ui.setWidget("prompt-url", undefined);
return;
}
renderPromptMatch(ctx, match);
};
pi.on("session_start", async (_event, ctx) => {
rebuildFromSession(ctx);
});
}

View File

@@ -1,26 +0,0 @@
/**
* Redraws Extension
*
* Exposes /tui to show TUI redraw stats.
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { Text } from "@mariozechner/pi-tui";
export default function (pi: ExtensionAPI) {
pi.registerCommand("tui", {
description: "Show TUI stats",
handler: async (_args, ctx) => {
if (!ctx.hasUI) {
return;
}
let redraws = 0;
await ctx.ui.custom<void>((tui, _theme, _keybindings, done) => {
redraws = tui.fullRedraws;
done(undefined);
return new Text("", 0, 0);
});
ctx.ui.notify(`TUI full redraws: ${redraws}`, "info");
},
});
}

View File

@@ -1,82 +0,0 @@
import { DynamicBorder } from "@mariozechner/pi-coding-agent";
import {
Container,
Key,
matchesKey,
type SelectItem,
SelectList,
Text,
} from "@mariozechner/pi-tui";
type CustomUiContext = {
ui: {
custom: <T>(
render: (
tui: { requestRender: () => void },
theme: {
fg: (tone: string, text: string) => string;
bold: (text: string) => string;
},
kb: unknown,
done: () => void,
) => {
render: (width: number) => string;
invalidate: () => void;
handleInput: (data: string) => void;
},
) => Promise<T>;
};
};
export async function showPagedSelectList(params: {
ctx: CustomUiContext;
title: string;
items: SelectItem[];
onSelect: (item: SelectItem) => void;
}): Promise<void> {
await params.ctx.ui.custom<void>((tui, theme, _kb, done) => {
const container = new Container();
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
container.addChild(new Text(theme.fg("accent", theme.bold(params.title)), 0, 0));
const visibleRows = Math.min(params.items.length, 15);
let currentIndex = 0;
const selectList = new SelectList(params.items, visibleRows, {
selectedPrefix: (text) => theme.fg("accent", text),
selectedText: (text) => text,
description: (text) => theme.fg("muted", text),
scrollInfo: (text) => theme.fg("dim", text),
noMatch: (text) => theme.fg("warning", text),
});
selectList.onSelect = (item) => params.onSelect(item);
selectList.onCancel = () => done();
selectList.onSelectionChange = (item) => {
currentIndex = params.items.indexOf(item);
};
container.addChild(selectList);
container.addChild(
new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0),
);
container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s)));
return {
render: (width) => container.render(width),
invalidate: () => container.invalidate(),
handleInput: (data) => {
if (matchesKey(data, Key.left)) {
currentIndex = Math.max(0, currentIndex - visibleRows);
selectList.setSelectedIndex(currentIndex);
} else if (matchesKey(data, Key.right)) {
currentIndex = Math.min(params.items.length - 1, currentIndex + visibleRows);
selectList.setSelectedIndex(currentIndex);
} else {
selectList.handleInput(data);
}
tui.requestRender();
},
};
});
}

2
.pi/git/.gitignore vendored
View File

@@ -1,2 +0,0 @@
*
!.gitignore

View File

@@ -1,58 +0,0 @@
---
description: Audit changelog entries before release
---
Audit changelog entries for all commits since the last release.
## Process
1. **Find the last release tag:**
```bash
git tag --sort=-version:refname | head -1
```
2. **List all commits since that tag:**
```bash
git log <tag>..HEAD --oneline
```
3. **Read each package's [Unreleased] section:**
- packages/ai/CHANGELOG.md
- packages/tui/CHANGELOG.md
- packages/coding-agent/CHANGELOG.md
4. **For each commit, check:**
- Skip: changelog updates, doc-only changes, release housekeeping
- Determine which package(s) the commit affects (use `git show <hash> --stat`)
- Verify a changelog entry exists in the affected package(s)
- For external contributions (PRs), verify format: `Description ([#N](url) by [@user](url))`
5. **Cross-package duplication rule:**
Changes in `ai`, `agent` or `tui` that affect end users should be duplicated to `coding-agent` changelog, since coding-agent is the user-facing package that depends on them.
6. **Add New Features section after changelog fixes:**
- Insert a `### New Features` section at the start of `## [Unreleased]` in `packages/coding-agent/CHANGELOG.md`.
- Propose the top new features to the user for confirmation before writing them.
- Link to relevant docs and sections whenever possible.
7. **Report:**
- List commits with missing entries
- List entries that need cross-package duplication
- Add any missing entries directly
## Changelog Format Reference
Sections (in order):
- `### Breaking Changes` - API changes requiring migration
- `### Added` - New features
- `### Changed` - Changes to existing functionality
- `### Fixed` - Bug fixes
- `### Removed` - Removed features
Attribution:
- Internal: `Fixed foo ([#123](https://github.com/badlogic/pi-mono/issues/123))`
- External: `Added bar ([#456](https://github.com/badlogic/pi-mono/pull/456) by [@user](https://github.com/user))`

View File

@@ -1,22 +0,0 @@
---
description: Analyze GitHub issues (bugs or feature requests)
---
Analyze GitHub issue(s): $ARGUMENTS
For each issue:
1. Read the issue in full, including all comments and linked issues/PRs.
2. **For bugs**:
- Ignore any root cause analysis in the issue (likely wrong)
- Read all related code files in full (no truncation)
- Trace the code path and identify the actual root cause
- Propose a fix
3. **For feature requests**:
- Read all related code files in full (no truncation)
- Propose the most concise implementation approach
- List affected files and changes needed
Do NOT implement unless explicitly asked. Analyze and propose only.

View File

@@ -19,60 +19,7 @@ repos:
args: [--maxkb=500]
- id: check-merge-conflict
- id: detect-private-key
exclude: '(^|/)(\.secrets\.baseline$|\.detect-secrets\.cfg$|\.pre-commit-config\.yaml$|apps/ios/fastlane/Fastfile$|.*\.test\.ts$)'
# Secret detection (same as CI)
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args:
- --baseline
- .secrets.baseline
- --exclude-files
- '(^|/)pnpm-lock\.yaml$'
- --exclude-lines
- 'key_content\.include\?\("BEGIN PRIVATE KEY"\)'
- --exclude-lines
- 'case \.apiKeyEnv: "API key \(env var\)"'
- --exclude-lines
- 'case apikey = "apiKey"'
- --exclude-lines
- '"gateway\.remote\.password"'
- --exclude-lines
- '"gateway\.auth\.password"'
- --exclude-lines
- '"talk\.apiKey"'
- --exclude-lines
- '=== "string"'
- --exclude-lines
- 'typeof remote\?\.password === "string"'
- --exclude-lines
- "OPENCLAW_DOCKER_GPG_FINGERPRINT="
- --exclude-lines
- '"secretShape": "(secret_input|sibling_ref)"'
- --exclude-lines
- 'API key rotation \(provider-specific\): set `\*_API_KEYS`'
- --exclude-lines
- 'password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway\.auth\.password` -> `gateway\.remote\.password`'
- --exclude-lines
- 'password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway\.remote\.password` -> `gateway\.auth\.password`'
- --exclude-files
- '^src/gateway/client\.watchdog\.test\.ts$'
- --exclude-lines
- 'export CUSTOM_API_K[E]Y="your-key"'
- --exclude-lines
- 'grep -q ''N[O]DE_COMPILE_CACHE=/var/tmp/openclaw-compile-cache'' ~/.bashrc \|\| cat >> ~/.bashrc <<''EOF'''
- --exclude-lines
- 'env: \{ MISTRAL_API_K[E]Y: "sk-\.\.\." \},'
- --exclude-lines
- '"ap[i]Key": "xxxxx"(,)?'
- --exclude-lines
- 'ap[i]Key: "A[I]za\.\.\.",'
- --exclude-lines
- '"ap[i]Key": "(resolved|normalized|legacy)-key"(,)?'
- --exclude-lines
- 'sparkle:edSignature="[A-Za-z0-9+/=]+"'
exclude: '(^|/)(\.pre-commit-config\.yaml$|apps/ios/fastlane/Fastfile$|.*\.test\.ts$)'
# Shell script linting
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.11.0
@@ -94,7 +41,7 @@ repos:
hooks:
- id: zizmor
args: [--persona=regular, --min-severity=medium, --min-confidence=medium]
exclude: "^(vendor/|Swabble/)"
exclude: "^(vendor/|apps/swabble/)"
# Python checks for skills scripts
- repo: https://github.com/astral-sh/ruff-pre-commit

View File

@@ -1 +0,0 @@
docs/.generated/

File diff suppressed because it is too large Load Diff

View File

@@ -48,4 +48,4 @@
--allman false
# Exclusions
--exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,Swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/OpenClawProtocol,apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift
--exclude .build,.swiftpm,DerivedData,node_modules,dist,coverage,xcuserdata,Peekaboo,apps/swabble,apps/android,apps/ios,apps/shared,apps/macos/Sources/OpenClawProtocol,apps/macos/Sources/OpenClaw/HostEnvSecurityPolicy.generated.swift

View File

@@ -1,3 +0,0 @@
{
"recommendations": ["oxc.oxc-vscode"]
}

22
.vscode/settings.json vendored
View File

@@ -1,22 +0,0 @@
{
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"[javascript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"[json]": {
"editor.defaultFormatter": "oxc.oxc-vscode"
},
"typescript.preferences.importModuleSpecifierEnding": "js",
"typescript.reportStyleChecksAsWarnings": false,
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.tsdk": "node_modules/typescript/lib",
"makefile.configureOnOpen": false
}

View File

@@ -18,7 +18,7 @@ Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
## Map
- Core TS: `src/`, `ui/`, `packages/`; plugins: `extensions/`; SDK: `src/plugin-sdk/*`; channels: `src/channels/*`; loader: `src/plugins/*`; protocol: `src/gateway/protocol/*`; docs/apps: `docs/`, `apps/`, `Swabble/`.
- Core TS: `src/`, `ui/`, `packages/`; plugins: `extensions/`; SDK: `src/plugin-sdk/*`; channels: `src/channels/*`; loader: `src/plugins/*`; protocol: `src/gateway/protocol/*`; docs/apps: `docs/`, `apps/`.
- Installers: sibling `../openclaw.ai`.
- Scoped guides exist in: `extensions/`, `src/{plugin-sdk,channels,plugins,gateway,gateway/protocol,agents}/`, `test/helpers*/`, `docs/`, `ui/`, `scripts/`.
@@ -126,7 +126,7 @@ Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
## Tests
- Vitest. Colocated `*.test.ts`; e2e `*.e2e.test.ts`; example models `sonnet-4.6`, `gpt-5.5`; test GPT with 5.5 preferred, 5.4 ok, no GPT-4.x agent-smoke defaults.
- Vitest. Colocated `*.test.ts`; e2e `*.e2e.test.ts`; example models `sonnet-4.6`, `gpt-5.5`; test GPT with 5.5 preferred, 5.4 ok; no GPT-4.x agent-smoke defaults.
- Avoid brittle tests that grep workflow/docs strings for operator policy. Prefer executable behavior, parsed config/schema checks, or live run proof; put release/CI policy reminders in AGENTS/docs instead.
- Clean timers/env/globals/mocks/sockets/temp dirs/module state; `--isolate=false` safe.
- Hot tests: avoid per-test `vi.resetModules()` + heavy imports. Measure with `pnpm test:perf:imports <file>` / `pnpm test:perf:hotspots --limit N`.
@@ -141,13 +141,14 @@ Telegraph style. Root rules only. Read scoped `AGENTS.md` before subtree work.
- Test workers max 16. Memory pressure: `OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test`.
- Live: `OPENCLAW_LIVE_TEST=1 pnpm test:live`; verbose `OPENCLAW_LIVE_TEST_QUIET=0`.
- Guide: `docs/help/testing.md`.
- Package manifest plugin-local assertions must agree with `pnpm deps:root-ownership:check`; intentionally internalized bundled plugin runtime deps are root-owned while the package acceptance path needs them.
## Docs / Changelog
- Docs change with behavior/API. Use docs list/read_when hints; docs links per `docs/AGENTS.md`.
- Docs final answers: when doc files changed, end with the relevant full `https://docs.openclaw.ai/...` URL(s).
- Changelog user-facing only; fixing an issue or landing/merging a PR needs one unless pure test/internal.
- Changelog placement: active version `### Changes`/`### Fixes`; contributor-facing added entries should include at least one `Thanks @author` attribution, using credited human GitHub username(s). Never add `Thanks @codex`, `Thanks @openclaw`, `Thanks @clawsweeper`, or `Thanks @steipete`; for maintainer-owned or automation-only changes, omit the thanks instead of inventing credit.
- Changelog placement: active version `### Changes`/`### Fixes`; contributor-facing added entries should include at least one `Thanks @author` attribution, using credited human GitHub username(s). Never add `Thanks @codex`, `Thanks @openclaw`, `Thanks @clawsweeper`, or `Thanks @steipete`; if the real credited human is unknown, leave attribution blank instead of guessing or adding a random person.
- Changelog bullets are always single-line. No wrapping/continuation across multiple lines. Long entries stay on one long line so dedupe, PR-ref, and credit-audit tooling work and so the visual style stays uniform.
## Git

View File

@@ -4,9 +4,183 @@ Docs: https://docs.openclaw.ai
## Unreleased
### Highlights
- Plugins/file-transfer: add bundled file-transfer plugin with `file_fetch`, `dir_list`, `dir_fetch`, and `file_write` agent tools for binary file ops on paired nodes; default-deny per-node path policy under `plugins.entries.file-transfer.config.nodes` with operator approval, symlink traversal refused by default (opt-in `followSymlinks`), and a 16 MB byte ceiling per round-trip. (#74742) Thanks @omarshahine.
### Changes
- Gateway/performance: lazy-load early runtime discovery and shutdown-hook helpers, defer maintenance timers until after readiness, and trim duplicate plugin auto-enable work during Gateway startup.
- Gateway/performance: lazy-load the heavy cron runtime after the rest of Gateway startup, defer restart-sentinel refresh after readiness, and let the Gateway startup benchmark write per-run V8 CPU profiles with `--cpu-prof-dir`.
- Gateway/performance: keep raw channel-config schema parsing from discovering bundled plugin runtime metadata, and add `pnpm gateway:watch --benchmark-no-force` for profiling startup without the default port cleanup.
- Plugins/onboarding: let Manual setup install optional official plugins, including ClawHub-backed diagnostics with npm fallback, and expose the external Codex plugin as a selectable provider setup choice. Thanks @vincentkoc.
- Plugins/CLI: include package dependency install state in `openclaw plugins list --json` so scripts can spot missing plugin dependencies without runtime-loading plugins.
- Discord/status: add degraded Discord transport and gateway event-loop starvation signals to `openclaw channels status`, `openclaw status --deep`, and fetch-timeout logs so intermittent socket resets do not look like a healthy running channel. (#76327) Thanks @joshavant.
- Plugins/update: on the beta OpenClaw update channel, default-line npm and ClawHub plugin updates try `@beta` first and fall back to default/latest when no plugin beta release exists.
- Channels/WhatsApp: support explicit WhatsApp Channel/Newsletter `@newsletter` outbound message targets with channel session metadata instead of DM routing. Fixes #13417; carries forward the narrow outbound target idea from #13424. Thanks @vincentkoc and @agentz-manfred.
- Exec approvals: add a tree-sitter-backed shell command explainer for future approval and command-review surfaces. (#75004) Thanks @jesse-merhi.
- Agents/sandbox: store sandbox container and browser registry entries as per-runtime shard files, reducing unrelated session lock contention while `openclaw doctor --fix` migrates legacy monolithic registry files. (#74831) Thanks @luckylhb90.
### Fixes
- Gateway/update: run `doctor --non-interactive --fix` after Control UI global package updates before reporting success, so legacy config is migrated before the gateway restart. Thanks @stevenchouai.
- Gateway/cron: stop a lazy cron startup that loses a hot-reload race, preventing the old cron service from starting after reload has already replaced cron state.
- Active Memory: apply `setupGraceTimeoutMs` to the embedded recall runner as well as the outer prompt-build watchdog, so very-cold first recalls keep the configured setup grace end-to-end. (#74480) Thanks @volcano303.
- Agents/infer: let intentional no-tool `modelRun` and `llm-task` turns ignore inherited config allowlists while preserving explicit runtime `toolsAllow` failures, so gateway model probes and JSON LLM tasks no longer fail before reaching the provider. Fixes #74810. Thanks @amknight.
- CLI/config: keep JSON dry-run patches validating touched channel configuration against bundled channel schemas even when the patch only contains SecretRef objects.
- Plugins/tools: keep disabled bundled tool plugins out of explicit runtime allowlist ownership and fall back from loaded-but-empty channel registries to tool-bearing plugin registries, so Active Memory can use bundled `memory-core` search/get tools even when `memory-lancedb` is disabled. Fixes #76603. Thanks @jwong-art.
- Plugins/install: run `npm install` from the managed npm-root manifest so installing one `@openclaw/*` plugin preserves already installed sibling plugins instead of pruning them. Fixes #76571. (#76602) Thanks @byungskers and @crpol.
- Plugins/context-engine: include the selected `plugins.slots.contextEngine` plugin in the gateway startup load plan so external context-engine plugins without `activation.onStartup` in their manifest are loaded before any agent turn resolves the active engine; prevents the "Context engine X is not registered; falling back to default engine legacy" warning after gateway startup. Fixes #76576. Thanks @hclsys.
- Plugins/tools: restore on-demand registry load for path-based plugins (origin "config") so tool factories registered via `plugins.load.paths` are resolved at agent request time when no pre-warmed channel registry is present; prevents "unknown method" errors after gateway startup. Fixes #76598. Thanks @hclsys.
- Channels/QQ Bot: resolve structured `clientSecret` SecretRefs before QQ token exchange, expose the QQ Bot secret contract to secrets tooling, and reject legacy `secretref:/...` marker strings. (#74772) Thanks @xialonglee.
- Agents: keep active streamed provider replies alive by refreshing guarded fetch timeouts on raw body chunks and surface true prompt stream timeouts as explicit errors instead of partial assistant fragments. Fixes #76307. (#76633) Thanks @MkDev11.
- Plugins/externalization: keep official ACPX, Google Chat, and LINE install specs on production package names, leaving beta-tag probing to the explicit OpenClaw beta update channel. Thanks @vincentkoc.
- CLI/doctor: keep missing-plugin repair from overriding official catalog metadata with runtime fallbacks, so ACPX repairs preserve the official npm spec during the externalization rollout. Thanks @vincentkoc.
- CLI/doctor: match stale bundled-plugin install records by exact parsed package name so doctor does not remove external npm or ClawHub records that only share an OpenClaw package-name prefix.
- Plugins/catalog: preserve ClawHub install specs when generating the packaged channel catalog so future storepack-first channel plugins keep their remote source instead of becoming npm-only. Thanks @vincentkoc.
- Plugins/catalog: pin bare npm specs from prerelease external channel catalog entries to the catalog entry version, so beta catalogs do not silently install the latest stable package.
- Plugins/update: treat catalog-matched official npm updates and OpenClaw-authored externalized-bundled npm bridges as trusted official installs so launch-code plugins can update or migrate out of the bundled tree without scanner false positives. Thanks @vincentkoc.
- Plugins/onboarding: fall back from ClawHub to npm only for missing package/version errors, keeping integrity and verification failures fail-closed during storepack rollout. Thanks @vincentkoc.
- Control UI/Talk: fix Talk (OpenAI Realtime WebRTC) CORS failure by stripping server-side-only attribution headers (`originator`, `version`, `User-Agent`) from browser offer headers; `api.openai.com/v1/realtime/calls` only allows `authorization` and `content-type` in its CORS preflight, so forwarding these headers caused the browser SDP exchange to fail. Fixes #76435. Thanks @hclsys.
- CLI/logs: auto-reconnect `openclaw logs --follow` on transient gateway disconnects (WebSocket close, timeout, connection drop) with bounded exponential backoff (up to 8 retries, capped at 30 s) and stderr retry warnings, while still exiting immediately on non-recoverable auth or configuration errors. Fixes #74782. (#75059) Thanks @shashank-poola.
- CLI/logs: announce `--follow` recovery with a `[logs] gateway reconnected` notice once a poll succeeds after a transient outage, and emit JSON `notice` records in `--json` mode for both the retry warning and the reconnect transition, so live monitoring scripts can react to the recovery. Carries forward #75059. (#75372) Thanks @romneyda.
- Plugins/onboarding: trust optional official plugin and web-search installs selected from the official catalog so npm security scanning treats them like other source-linked official install paths. Thanks @vincentkoc.
- Tests/plugins: expose the Discord npm onboarding Docker lane as a package script and assert planned Docker lanes point at real scripts, so external-channel onboarding coverage can actually run. Thanks @vincentkoc.
- Plugins/ClawHub: explain unreleased ClawHub plugin artifacts as a rollout-state fallback to `npm:` installs instead of leaking raw archive metadata fields. Thanks @vincentkoc.
- Tests/onboarding: assert packaged channel onboarding leaves `openclaw channels status --json` and plain `openclaw status` showing the configured channel, covering the empty Channels table regression path. Thanks @vincentkoc.
- Microsoft Teams: persist sent-message markers across Gateway restarts so follow-up replies to recent bot messages keep resolving the original conversation instead of dropping out after restart, with marker TTLs preserved on best-effort recovery. (#75585) Thanks @amknight.
- Matrix: persist pending approval reaction targets across Gateway restarts so room approvers can still approve or deny outstanding prompts after OpenClaw comes back online. (#75586) Thanks @amknight.
- Channels/onboarding: map third-party official WeCom and Yuanbao catalog entries to their published plugin ids so npm installs pass expected-plugin validation. Thanks @vincentkoc.
- Plugin SDK: restore the Mattermost and Matrix compatibility subpaths used by the pinned Yuanbao channel package so external installs can module-load after npm install. Thanks @vincentkoc.
- Plugins/install: keep managed npm-root security scans from treating earlier plugin `openclaw` peer links as failures, so one external plugin install cannot poison later official npm installs. Thanks @vincentkoc.
- Memory LanceDB: allow installed-but-unconfigured plugin metadata to load so onboarding and setup flows can prompt for embedding config instead of failing the plugin registry first. Thanks @vincentkoc.
- CLI/plugins: keep `plugins enable` and `plugins disable` from creating unconfigured channel config sections, so channel plugins with required setup fields no longer fail validation during lifecycle probes. Thanks @vincentkoc.
- Doctor/config: set `messages.groupChat.visibleReplies: "message_tool"` during compatibility repair for configured-channel configs that omit a visible-reply policy, so upgrades can persist the intended tool-only group/channel reply default. Thanks @kagura-agent.
- Agents/sessions: keep delayed `sessions_send` A2A replies alive after soft wait-window timeouts, while preserving terminal run timeouts and avoiding stale target replies in requester sessions. Fixes #76443. Thanks @ryswork1993 and @vincentkoc.
- TUI/Control UI: fix `/think` command showing only base thinking levels when the active session uses a different model from the default, so provider-specific levels like DeepSeek V4 Pro's `xhigh` and `max` are now visible and selectable. Fixes #76482. Thanks @amknight.
- CLI/sessions: keep intentional empty agent replies silent after tool-delivered channel output, instead of surfacing a misleading "No reply from agent." fallback. Thanks @vincentkoc.
- Config/doctor: cap `.clobbered.*` forensic snapshots per config path and serialize snapshot writes so repeated `doctor --fix` recovery loops cannot flood the config directory. Fixes #76454; carries forward #65649. Thanks @JUSTICEESSIELP, @rsnow, and @vincentkoc.
- Feishu: suppress duplicate text when replies send native voice media while preserving captions for ordinary audio files and falling back to text plus attachment links when voice uploads fail.
- Feishu: send the skipped reply text when `audioAsVoice` falls back to a generic file attachment after transcode failure, so voice-intent replies do not lose their caption.
- TTS/plugins: activate the configured speech provider plugin during Gateway startup, so Microsoft and Local CLI voice replies work immediately after selecting them instead of staying invisible in the startup plugin set. Fixes #76481. Thanks @amknight.
- TTS/plugins: include speech providers selected through inherited agent, channel, and account TTS personas during Gateway startup, matching the runtime TTS config merge. Carries forward #76481. Thanks @amknight.
- Feishu: keep packaged Feishu startup from bundling the Lark SDK's ESM `__dirname` path by loading the SDK as a plugin-local runtime dependency. Fixes #76291 and #76494. (#76392) Thanks @zqchris.
- Plugins/npm: build package-local runtime dist files for publishable plugins and stop listing root-package-excluded plugin sidecars in the core package metadata, so npm plugin installs such as `@openclaw/diffs` and `@openclaw/discord` no longer publish source-only runtime payloads. Fixes #76426. Thanks @PrinceOfEgypt.
- Channels/secrets: resolve SecretRef-backed channel credentials through external plugin secret contracts after the plugin split, covering runtime startup, target discovery, webhook auth, disabled-account enumeration, and late-bound web_search config. Fixes #76371. (#76449) Thanks @joshavant and @neeravmakwana.
- Docker/Gateway: pass Docker setup `.env` values into gateway and CLI containers and preserve exec SecretRef `passEnv` keys in managed service plans, so 1Password Connect-backed Discord tokens keep resolving after doctor or plugin repair. Thanks @vincentkoc.
- Control UI/WebChat: explain compaction boundaries in chat history and link directly to session checkpoint controls so pre-compaction turns no longer look silently lost after refresh. Fixes #76415. Thanks @BunsDev.
- Agents/incomplete-turn: detect and surface a warning when the agent's final text after a tool-call chain is silently dropped because the post-tool assistant response was never produced, instead of completing the turn with only the pre-tool analysis text. Fixes #76477. Thanks @amknight.
- Channels/WhatsApp: attach native outbound mention metadata for group text and media captions by resolving `@+<digits>` and `@<digits>` tokens against WhatsApp participant data, including LID groups. Fixes #39879; carries forward #56863. Thanks @kengi1437, @joe2643, and @fridayck.
- Channels/WhatsApp: require outbound mention tokens to end at a word boundary so phone-number prefixes inside longer strings no longer trigger hidden native mentions.
- Plugins/uninstall: remove empty managed git install parent directories after deleting cloned plugin repos and cover npm/git uninstall residue in Docker plugin lifecycle tests. Thanks @vincentkoc.
- Plugins/install: resolve bare official external plugin IDs such as `brave` through the official catalog when no bundled source is available, so packaged installs fetch the intended scoped npm package instead of an unrelated unscoped package. Fixes #76373. Thanks @bek91 and @vincentkoc.
- Plugins/install: require OpenClaw-owned install provenance before granting official npm plugin scanner trust, so direct npm package names no longer bypass launch-code scanning while catalog, onboarding, and doctor installs stay trusted. Thanks @fede-kamel and @vincentkoc.
- Network proxy: preserve target TLS hostname validation for Node HTTPS requests routed through the managed HTTP proxy, so Discord-style CONNECT traffic no longer validates certificates against the local proxy host. Fixes #74809. (#76442) Thanks @jesse-merhi and @abnershang.
- Gateway/sessions: keep async `sessions.list` title and preview hydration bounded to transcript head/tail reads so Control UI polling cannot full-scan large session transcripts every refresh. Thanks @vincentkoc.
- Gateway/performance: cache per-run verbose-level session reads, skip a redundant `lsof` scan in `gateway --force` when no listener was killed, and make the Gateway startup benchmark print usage for `--help`.
- Gateway/sessions: keep agent runtime metadata on lightweight `sessions.list` rows so model-only session patches do not make Control UI lose runtime identity. Thanks @vincentkoc.
- Gateway/sessions: keep bulk `sessions.list` rows lightweight by skipping per-row transcript usage fallback, display model inference, and plugin projection, avoiding event-loop stalls in large session stores. Thanks @Marvinthebored and @vincentkoc.
- Gateway/models: keep read-only `models.list` fallbacks on persisted/current metadata and configured rows while using static auth checks, so missing `models.json` files no longer runtime-load provider discovery or stall gateway after restart. Fixes #76382; refs #76360 and #75707. Thanks @trojy13, @RayWoo, @AnathemaOfficial, and @vincentkoc.
- Gateway/models: keep agent image attachment capability checks on the full catalog while preserving the read-only `models.list` path, so image sends are not rejected after static catalog fallback.
- CLI/plugins: reject missing plugin ids before config writes in `plugins enable` and `plugins disable` so a typo no longer persists a stale config entry. (#73554) Thanks @ai-hpc.
- Agents/sessions: preserve delivered trailing assistant replies during session-file repair so Telegram/WebChat history is not rewritten to drop already-delivered responses. Fixes #76329. Thanks @obviyus.
- Gateway/chat history: preserve oversized transcript turns as explicit omitted-message placeholders while avoiding large JSONL parse stalls. Thanks @Marvinthebored and @vincentkoc.
- Gateway/models: keep read-only model-list responses on registry-compatible fallbacks and metadata defaults, so empty or minimal persisted model files do not hide built-ins or custom model capabilities. Thanks @Marvinthebored.
- CLI/doctor: load the configured memory-slot plugin when resolving memory diagnostics so bundled `memory-core` no longer triggers a false “no active memory plugin” warning on standalone `doctor` / `status` runs. Fixes #76367. Thanks @neeravmakwana.
- Gateway: preserve stack diagnostics when `chat.send` or agent attachment parsing/staging fails, improving image-send failure triage. Refs #63432. (#75135) Thanks @keen0206.
- Heartbeats/Codex: stop sending the legacy `HEARTBEAT_OK` prompt instruction when heartbeat turns have the structured `heartbeat_respond` tool, while keeping the text sentinel for legacy automatic heartbeat replies. Thanks @pashpashpash.
- Agent runtimes: fail explicit plugin runtime selections honestly when the requested harness is unavailable instead of silently falling back to the embedded PI runtime. Thanks @pashpashpash.
- Maintainer workflow: push prepared PR heads through GitHub's verified commit API by default and require an explicit override before git-protocol pushes can publish unsigned commits. Thanks @BunsDev.
- Feishu: resolve setup/status probes through the selected/default account so multi-account configs with account-scoped app credentials show as configured and probeable. Fixes #72930. Thanks @brokemac79.
- Gateway/responses: emit every client tool call from `/v1/responses` JSON and SSE responses when the agent invokes multiple client tools in a single turn, so multi-tool plans, graph orchestration calls, and similar batched flows no longer drop every call but the last. Fixes #52288. Thanks @CharZhou and @bonelli.
- Gateway/agent: enforce `session.sendPolicy=deny` on gateway agent requests only when `deliver: true`, so non-delivery smoke checks and internal agent runs are no longer rejected with `send blocked by session policy` while outbound delivery remains gated. Fixes #73381. Thanks @wenxu007.
- Slack/reactions: treat missing no_reaction remove responses as idempotent success and route own-reaction cleanup through the remove helper, so concurrent cleanup no longer surfaces Slack race errors. Fixes #50733. (#76304) Thanks @martingarramon and @Hollychou924.
- Feishu: include media `file_key` and `image_key` values in inbound dedupe so reused message IDs still process distinct media attachments while true retries stay suppressed. Fixes #75057. Thanks @SymbolStar.
- Control UI/Gateway: avoid full session-list reloads for locally applied message-phase session updates, carry known session keys through transcript-file update events, and defer media provider listing when explicit generation model config is present. Refs #76236, #76203, #76188, #76107, and #76166. Thanks @BunsDev.
- Install/update: prune the obsolete `plugin-runtime-deps` state directory during packaged postinstall so upgrades from pre-2026.5.2 releases reclaim old bundled-plugin dependency caches without touching external plugin installs.
- Auto-reply/queue: treat reset-triggered `/new` and `/reset` turns as interrupt runs across active-run queue handling, so steer/followup modes cannot delay a fresh session behind existing work. Fixes #74093. (#74144) Thanks @ruji9527 and @yelog.
- Cron: persist repaired startup runtime state back to `jobs-state.json` so a valid future `nextRunAtMs` with missing `updatedAtMs` no longer triggers repeated external health-check repairs after Gateway restart. Fixes #76461. Thanks @vincentkoc.
- Cron: preserve manual `cron.run` IDs in `cron.runs` history so manual run acknowledgements can be correlated with finished run records. Fixes #76276.
- CLI/devices: request `operator.admin` for `openclaw devices approve <requestId>` only when the exact pending device request would mint or inherit admin-scoped operator access, while keeping lower-scope approvals on the pairing scope.
- Memory/embedding: broaden the embedding reindex retry classifier to include transient socket-layer errors (`fetch failed`, `ECONNRESET`, `socket hang up`, `UND_ERR_*`, `closed`) so memory reindex survives provider network hiccups instead of aborting mid-run. Related #56815, #44166. (#76311) Thanks @buyitsydney.
- Memory/sessions: keep rotated and deleted session transcripts (`.jsonl.reset.<iso>` / `.jsonl.deleted.<iso>`) searchable end-to-end by indexing their real content in `buildSessionEntry` instead of short-circuiting to empty entries, and by mapping archive hit paths back to their live transcript stem during `memory_search` visibility filtering so hits are no longer dropped at the guard. `.jsonl.bak.<iso>` backups and compaction checkpoints remain opaque. Refs #56131. Thanks @buyitsydney.
- Memory/sessions: emit a `sessionTranscriptUpdate` event when `archiveFileOnDisk` rotates a live session transcript into `.jsonl.reset.<iso>` / `.jsonl.deleted.<iso>` / `.jsonl.bak.<iso>`, and bypass the delta-bytes / delta-messages threshold gate in `processSessionDeltaBatch` for usage-counted archive paths (`.jsonl.reset.<iso>` and `.jsonl.deleted.<iso>`). Without the bypass the archive event was forwarded to the listener but dropped at the threshold check, because an archive is a one-shot file-rename mutation rather than an incremental append and would typically land below the default `deltaBytes: 100000` / `deltaMessages: 50` reindex thresholds. Archives now feed the memory sync incremental path the same way `appendMessage` / compaction / tool-result rewrite / chat inject / command execution events already do. Refs #56131. Thanks @buyitsydney.
- Memory/search: keep sqlite-vec optional in packaged installs and point missing-extension recovery at the valid `agents.defaults.memorySearch.store.vector.extensionPath` setting. Thanks @willemsej and @vincentkoc.
- Gateway: keep directly requested plugin tools invokable under restrictive tool profiles while preserving explicit deny lists and the HTTP safety deny list, preventing catalog/invoke mismatches that surface as "Tool not available". Thanks @BunsDev.
- Gateway/update: allow beta binaries to refresh gateway services when the config was last written by the matching stable release version, avoiding false newer-config downgrade blocks during beta channel updates.
- Channels: keep Matrix and Mattermost bundled in the core package instead of advertising external npm installs before those channels are cut over. Thanks @vincentkoc.
- Bonjour: disable LAN mDNS advertising after a repeated stuck-announcing recovery instead of repeatedly restarting ciao and saturating the Gateway event loop.
- Channels/setup: label installable channel picker hints as remote npm installs and hide remote install hints for bundled plugins that already ship with OpenClaw.
- CLI/update: refuse package updates launched from the active gateway process tree before stopping the managed Gateway service, avoiding self-terminated in-lane updates that leave old Gateway code running. Fixes #75691. (#75819) Thanks @ai-hpc.
- CLI/plugins: stop treating the non-plugin `auth` command root as a bundled plugin id, so restrictive `plugins.allow` configs no longer tell users to add stale `auth` plugin entries.
- Doctor/plugins: update configured plugin installs whose stale manifests still declare channels without `channelConfigs`, so beta upgrades repair old Discord-style package payloads during `doctor --fix`.
- Doctor/plugins: repair configured external plugin installs whose persisted install record points at a missing package directory, so upgrades reconcile phantom npm metadata before plugin runtime validation. Thanks @vincentkoc.
- Active Memory: keep non-empty `memory_search` results from being fast-failed as empty when debug telemetry reports zero hits.
- Active Memory: preserve the target agent context when building embedded recall plugin tools so `memory_search` and `memory_get` stay available for explicit recall sessions. Fixes #76343. Thanks @Countermarch.
- Plugins/externalization: repair missing configured plugin installs from npm by default, reserve ClawHub downloads for explicit `clawhubSpec` metadata, and cover agent-runtime/env-selected plugin repair. Thanks @vincentkoc.
- Plugins/install: allow official catalog-matched npm channel plugins such as Feishu to pass the trusted install scanner path while keeping spoofed package names blocked. Thanks @vincentkoc.
- Tools/profiles: make `tools.profile: "full"` grant all tools including optional plugin tools such as browser, so the full profile no longer silently drops plugin-provided tools that require an explicit allowlist entry. Fixes #76507. Thanks @amknight.
- Feishu: keep timeout env parsing separate from the HTTP client wrapper so package security scans no longer report a false env-harvesting hit during install. Thanks @vincentkoc.
- Upgrade/config: validate configured web-search providers and statically suppressed model/provider pairs against the active plugin set at config load, so stale plugin state fails loud before runtime fallback.
- Status/update: resolve beta update-channel checks from the installed version when config still says `stable`, and let `status --deep` reuse live gateway channel credential state instead of warning on command-path-only token misses.
- Doctor/plugins: preserve unmanaged third-party plugin `node_modules` during `doctor --fix`, while still pruning OpenClaw-managed runtime dependency caches.
- Gateway/restart: add `openclaw gateway restart --force` and `--wait <duration>`, log active task run IDs before restart deferral timers, and report timeout restarts as explicit forced restarts.
- Discord: persist slash-command deploy hashes across process restarts so unchanged command sets skip redeploy and avoid restart-loop 429s.
- Providers/LM Studio: normalize binary `off`/`on` reasoning metadata from Gemma 4 and other local models to LM Studio's accepted OpenAI-compatible `reasoning_effort` values.
- Plugins/externalization: keep official external install docs, update examples, and live Codex npm checks on default npm tags instead of `@beta`. Thanks @vincentkoc.
- Plugins/externalization: keep ACPX, Google Chat, and LINE publishable plugin dist trees out of the core npm package file list.
- Plugins/ClawHub: fall back to version metadata when the artifact resolver route is missing and keep the Docker ClawHub fixture aligned with npm-pack artifact resolution, avoiding false version-not-found failures during plugin install validation. Thanks @vincentkoc.
- Providers/openai-codex: honor `providerConfig.baseUrl` in the dynamic-model synthesis fallback so codex providers configured with a custom upstream (for example a forwarding proxy) no longer silently bypass the configured URL when the registry has no template row to clone for the requested model id. (#76428) Thanks @arniesaha.
- Status/channels: show configured channels in `openclaw status` and config-only `openclaw channels status` output even when the Gateway is unreachable, avoiding empty Channels tables on WSL and other no-Gateway paths. Thanks @vincentkoc.
- Plugins/ClawHub: explain unavailable explicit ClawHub ClawPack artifact downloads with a temporary npm install hint while ClawHub artifact routing rolls out. Thanks @vincentkoc.
- Media: accept home-relative `MEDIA:~/...` attachment paths while preserving existing file-read policy, traversal checks, and media type validation. Fixes #73796. Thanks @fabkury.
- Onboarding/search: install official external web-search plugins such as Brave before saving provider config, and make doctor repair reconcile selected external search providers whose npm payload is missing. Thanks @vincentkoc.
- Plugins/externalization: add official npm-first catalogs for externalized channel, provider, and generic plugins, keep unpublished ACPX/Google Chat/LINE bundled, and make missing-plugin repair honor npm-first metadata while ClawHub pack files roll out. Thanks @vincentkoc.
- Plugins/update: detect tracked plugin install records whose package directories disappeared during `openclaw update`, reinstall them before normal plugin updates, and fail the update if any install record still points at missing disk payloads.
- Plugins/registry: hash manifest and package metadata when validating persisted plugin registries so fast same-size rewrites cannot leave stale plugin metadata trusted.
- Plugins/registry: canonicalize install-record provenance paths before trust diagnostics, so npm plugins installed under symlinked temp/state roots no longer warn as untracked local code.
- Plugins/install: let official external Discord reinstall requests pass the invalid-config guard and run stale-channel repair, so upgrades can recover missing external plugin state directly.
- CLI/infer: reject local `codex/*` one-shot model probes before simple-completion dispatch and point operators at the Codex app-server runtime path instead of ending with an empty-output error.
- Agents/sessions: preserve terminal lifecycle state when final run metadata persists from a stale in-memory snapshot, preventing `main` sessions from staying stuck as running after completed or timed-out turns.
- Gateway/CLI: make `openclaw gateway start` repair stale managed service definitions that point at old OpenClaw versions, missing binaries, or temporary installer paths before starting.
- Heartbeat/scheduler: make heartbeat phase scheduling active-hours-aware so the scheduler seeks forward to the first in-window phase slot instead of arming timers for quiet-hours slots and relying solely on the runtime guard. Non-UTC `activeHours.timezone` values (e.g. `Asia/Shanghai`) now correctly influence when the next heartbeat timer fires, avoiding wasted quiet-hours ticks and long dormant gaps after gateway restarts. Fixes #75487. Thanks @amknight.
- Providers/Arcee AI: mark Trinity Large Thinking as tool-incompatible so main-session runs use the same text-only request shape that made subagent runs recover, avoiding the remaining main-session response-shape mismatch after the #62848 transport failover fix. Fixes #62851 and #62847; carries forward #62848. Thanks @Adam-Researchh.
- Status: show the `openai-codex` OAuth profile for `openai/gpt-*` sessions running through the native Codex runtime instead of reporting auth as unknown. (#76197) Thanks @mbelinky.
- Gateway: avoid repeated plugin tool descriptor config hashing so large runtime configs do not block reply startup and trigger reconnect/timeouts. (#75944) Thanks @joshavant.
- Plugins/externalization: keep diagnostics ClawHub packages and persisted bundled-plugin relocation on npm-first install metadata for launch, and omit Discord from the core package now that its external package is published. Thanks @vincentkoc.
- Setup/TUI: bound the Terminal hatch bootstrap run so a stalled provider request times out instead of leaving first-run hatching stuck behind the watchdog. (#76241) Thanks @joshavant.
- Cron/CLI runtimes: route isolated cron jobs through configured per-agent CLI runtimes only when the resolved model provider is compatible, so OpenAI job overrides no longer inherit a mismatched Claude CLI backend. Thanks @vishutdhar.
- Plugins/Codex: allow the official npm Codex plugin to install without the unsafe-install override, keep `/codex` command ownership, and cover the real npm Docker live path through managed `.openclaw/npm` dependencies plus uninstall failure proof.
- Gateway/status: add concrete service, config, listener-owner, and log collection next steps when gateway probes fail and Bonjour finds no local gateway, so frozen or port-conflict reports include the data needed for root-cause triage. Refs #49012. Thanks @vincentkoc.
- Codex harness: forward OpenClaw workspace bootstrap files such as `SOUL.md` through native Codex config instructions while leaving `AGENTS.md` to Codex project-doc discovery. Fixes #76273. Thanks @zknicker.
- Parallels/Windows update smoke: escape the stale post-swap import regex in the generated PowerShell script so expected `ERR_MODULE_NOT_FOUND` update handoffs continue to post-update health checks. (#75315)
- Slack: allow draft preview streaming in top-level DMs when `replyToMode` is `off` while keeping Slack native streaming and assistant thread status gated on reply threads. Fixes #56480. (#56544) Thanks @HangGlidersRule.
- Control UI/chat: remove the delete-confirm popover outside-click listener on every dismiss path, so Cancel, Delete, outside clicks, and same-button toggles no longer leave stale document listeners behind. Refs #75590 and #69982. Thanks @Ricardo-M-L.
- Memory-core: treat exhausted file watcher limits as non-fatal for builtin memory auto-sync while preserving fatal handling for unrelated disk-full errors. (#73357) Thanks @solodmd.
- Providers/Ollama: restore catalog context-window forwarding as `num_ctx` for native `/api/chat` requests; fixes tool selection and context truncation regressions on models with catalog entries (qwen3, llama3, gemma3, …) when no explicit `params.num_ctx` was configured. Fixes #76117. (#76181) Thanks @openperf.
- Plugins/providers: preserve scoped cold-load fallback for enabled external manifest-contract capability providers missing from the startup registry, so providers such as Fish Audio can resolve on request without requiring `activation.onStartup` for correctness. (#76536) Thanks @Conan-Scott.
- Gateway/update: carry `continuationMessage` from `update.run` into successful restart sentinels so session-scoped self-updates can resume one follow-up turn after the Gateway restarts. Refs #71178. (#74362) Thanks @100menotu001, @HeilbronAILabs, and @artnking.
## 2026.5.2
### Highlights
- External plugin installation now covers diagnostics, onboarding, doctor repair, channel setup, install/update records, and artifact metadata while keeping bare package installs on npm for the first cutover. Thanks @vincentkoc.
- Gateway startup, session listing, task maintenance, prompt prep, plugin loading, and filesystem hot paths get targeted cache and fanout reductions for large or plugin-heavy installs.
- Control UI and WebChat reliability improves across Sessions, Cron, long-running Gateway WebSockets, grouped-message width, slash-command feedback, iOS PWA bounds, selection contrast, and Talk diagnostics.
- Channel and provider fixes cover Telegram topic commands and networking, Discord delivery and startup edge cases, OpenAI-compatible TTS/Realtime, OpenRouter/DeepSeek replay, Anthropic-compatible streaming, Brave/SearXNG/Firecrawl web search, and voice-call routing.
### Changes
- Gateway/startup: skip plugin-backed auth-profile overlays during startup secrets preflight, reducing gateway readiness latency while keeping reload and OAuth recovery paths overlay-capable. (#68327) Thanks @JIRBOY.
- Plugins/ClawHub: make diagnostics, onboarding, doctor repair, and channel setup carry ClawPack metadata through install records while keeping explicit `clawhub:` installs on ClawHub and bare package installs on npm for the launch cutover. Thanks @vincentkoc.
- Plugins/runtime: scope broad runtime preloads to the effective plugin ids derived from config, startup planning, configured channels, slots, and auto-enable rules instead of importing every discoverable plugin.
- Agents/runtime: reuse the startup-loaded plugin registry for request-time providers, tools, channel actions, web/capability/memory/migration helpers, and memoized provider extra-params so stable embedded-run inputs no longer repeat plugin registry resolution while model-specific transport hook patches stay isolated. Thanks @DmitryPogodaev.
- Agents/runtime: memoize transcript replay-policy resolution for stable config and process-env runs while preserving custom-env provider hook behavior. Thanks @DmitryPogodaev.
- Infra/path-guards: add a fast path for canonical absolute POSIX containment checks, avoiding repeated `path.resolve` and `path.relative` work in hot filesystem walkers. Refs #75895, #75575, and #68782. Thanks @Enderfga.
- Tools: add a platform-level tool descriptor planner for descriptor-first visibility, generic availability checks, and executor references. Thanks @shakkernerd.
- Plugins/tools: cache plugin tool descriptors captured from `api.registerTool(...)` so repeated prompt-time planning can skip plugin runtime loading while execution still loads the live plugin tool. (#76079) Thanks @shakkernerd.
- Docs/Codex: clarify that ChatGPT/Codex subscription setups should use `openai/gpt-*` with `agentRuntime.id: "codex"` for native Codex runtime, while `openai-codex/*` remains the PI OAuth route. Thanks @pashpashpash.
- Plugins/source checkout: load bundled plugins from the `extensions/*` pnpm workspace tree in source checkouts, so plugin-local dependencies and edits are used directly while packaged installs keep using the built runtime tree. Thanks @vincentkoc.
- Plugins/beta: externalize ACPX behind the official `@openclaw/acpx` package so packaged installs keep ACP harness adapter binaries out of core until the ACP backend is installed. Thanks @vincentkoc.
@@ -20,29 +194,104 @@ Docs: https://docs.openclaw.ai
- Google Meet: add `googlemeet test-listen` and the matching `google_meet` `test_listen` action so transcribe-mode joins wait for real caption or transcript movement before reporting listen-first health. Refs #72478. Thanks @DougButdorf.
- Plugins/ClawHub: prefer versioned ClawPack artifacts when ClawHub publishes digest metadata, verifying the ClawPack response header and downloaded bytes before installing. Thanks @vincentkoc.
- Plugins/ClawHub: persist ClawPack digest metadata on ClawHub plugin install and update records so registry refreshes and download verification can reuse stored artifact facts. Thanks @vincentkoc.
- Plugins/ClawHub: allow official bundled-plugin cutovers to prefer ClawHub installs with npm fallback only when the ClawHub package or version is absent. Thanks @vincentkoc.
- Plugins/ClawHub: allow official bundled-plugin cutovers to record ClawHub artifact metadata while preserving npm as the launch default for bare package specs. Thanks @vincentkoc.
- Plugins/onboarding: allow install-on-demand provider setup entries to persist ClawHub artifact metadata after explicit ClawHub installs while retaining npm/local fallback paths. Thanks @vincentkoc.
- Plugins/Crestodian: add ClawHub plugin search plus Crestodian plugin list/search/install/uninstall operations, with approval and audit coverage for install and uninstall.
- Channels/thread bindings: replace split subagent/ACP thread-spawn toggles with `threadBindings.spawnSessions`, default thread-bound spawns on, and let `openclaw doctor --fix` migrate the legacy keys. (#75943)
- Providers/OpenAI: add `extraBody`/`extra_body` passthrough for OpenAI-compatible TTS endpoints, so custom speech servers can receive fields such as `lang` in `/audio/speech` requests. Fixes #39900. Thanks @R3NK0R.
- Dependencies: refresh workspace dependency pins, including TypeBox 1.1.37, AWS SDK 3.1041.0, Microsoft Teams 2.0.9, and Marked 18.0.3. Thanks @mariozechner, @aws, and @microsoft.
- Discord/channels: add reusable message-channel access groups plus Discord channel-audience DM authorization, so allowlists can reference `accessGroup:<name>` across channel auth paths. (#75813)
- Crabbox/scripts: print the selected Crabbox binary, version, and supported providers before `pnpm crabbox:*` commands, and reject stale binaries that lack `blacksmith-testbox` provider support.
- Agents/Codex: add committed happy-path prompt snapshots for Codex/message-tool Telegram direct, Discord group, and heartbeat turns so prompt drift can be reviewed. Thanks @pashpashpash.
### Fixes
- Plugins/tools: keep plugin tool catalog visibility on manifest metadata, honor global plugin disablement, and reuse explicitly static plugin tool factories during prompt prep.
- CLI/message: skip eager model context warmup and preserve channel-declared gateway execution for Discord and Telegram message actions, avoiding Codex app-server/model discovery during simple send/read commands. Thanks @fuller-stack-dev.
- Codex/app-server: resolve managed binaries from bundled `dist` chunks and from the `@openai/codex` package bin when installs do not provide a nearby `.bin/codex` shim, avoiding false missing-binary startup failures.
- Plugins/ClawHub: use the ClawHub artifact resolver response as the install decision before downloading, keeping legacy ZIP fallback and future ClawPack npm-pack installs on the same explicit resolver path. Thanks @vincentkoc.
- Plugins/ClawHub: keep bare plugin package specs on npm for the launch cutover and reserve ClawHub resolution for explicit `clawhub:` specs until ClawHub pack readiness is deployed. Thanks @vincentkoc.
- Plugins/source checkout: discover source-only plugins such as Codex from the `extensions/*` workspace while using npm package excludes as the packaged-core boundary, removing the stale core-bundle metadata path.
- Plugins/ClawHub: install ClawPack artifacts from the explicit npm-pack `.tgz` resolver path and persist artifact kind, npm integrity, shasum, and tarball metadata for update and diagnostics flows. Thanks @vincentkoc.
- Control UI: allow deployments to configure grouped chat message max-width with a validated `gateway.controlUi.chatMessageMaxWidth` setting instead of patching bundled CSS after upgrades. Fixes #67935. Thanks @xiew4589-lang.
- Control UI/Cron: ignore malformed persisted cron rows without valid payloads before they enter UI state and guard stale cron render paths, preventing blank Control UI sections after a bad cron snapshot. Fixes #55047 and #54439; supersedes #54550 and #54552.
- Control UI/sessions: bound the default Sessions tab query to recent activity and fewer rows, avoiding expensive full-history loads while keeping filters editable. Fixes #76050. (#76051) Thanks @Neomail2.
- Gateway/channels: cap startup fanout at four channel/account handoffs and recover from Bonjour ciao self-probe races, reducing Windows startup stalls with many Telegram accounts. Fixes #75687.
- Gateway/sessions: keep `sessions.list` polling responsive on large session stores by reusing list-safe session cache/indexes and returning a lightweight compaction checkpoint preview instead of heavyweight summaries. Thanks @rolandrscheel.
- Control UI/Gateway: keep long-running dashboard WebSocket sessions alive with protocol pings and keep Stop available after reconnect or reload by recovering session-scoped active-run abort state. Fixes #70991. Thanks @alexandre-leng.
- CLI/update: treat inherited Gateway service markers as origin hints and only block package replacement when the managed Gateway is still live, so self-updates can stop the service and continue safely. (#75729) Thanks @hxy91819.
- Agents/failover: exempt run-level timeouts that fire during tool execution from model fallback, timeout-triggered compaction, and generic timeout payload synthesis, avoiding misleading "LLM request timed out" errors after the primary model has already responded. Fixes #52147. (#75873) Thanks @simonusa.
- Docker: copy Bun 1.3.13 from a digest-pinned image and keep CI on the same version. Fixes #74356. Thanks @fede-kamel and @sallyom.
- Agents/compaction: keep prior context on consecutive turns against z.ai-style providers (z.ai direct, openrouter z-ai/\*, in-house GLM gateways), avoiding accidental Pi state reset after successful turns. (#76056) Thanks @openperf.
- Doctor/plugins: run a one-time 2026.5.2 configured-plugin install repair based on `meta.lastTouchedVersion`, installing actively used downloadable OpenClaw plugins through the configured external source before marking the config touched for the release.
- Sessions/transcripts: use one `session.writeLock.acquireTimeoutMs` policy for session transcript lock acquisitions and raise the default wait to 60 seconds, avoiding user-visible lock timeouts during legitimate slow prep, cleanup, compaction, and mirror work. Fixes #75894. Thanks @shandutta.
- Control UI: contain the standalone iOS PWA viewport with safe-area-aware document locking, so Add-to-Home-Screen launches cannot scroll past the device bounds. Refs #76072. Thanks @kvncrw.
- Agents/restart recovery: match cleaned transcript locks by exact transcript lock paths plus the canonical session fallback, so interrupted main sessions using topic-suffixed transcripts resume after gateway restart. Refs #76052. Thanks @anyech.
- Agents/runtime: cache the stable system-prompt prefix and reuse prompt-report tool schema stats during dispatch prep, reducing repeated CPU work before streaming starts. Fixes #75999; supersedes #76061. Thanks @zackchiutw and @STLI69.
- Control UI/WebChat: use high-contrast text selection colors so highlighted chat text stays visible across themes. Fixes #60850; supersedes #60854. Thanks @Badschaff and @efe-arv.
- Telegram/native commands: pass persisted session files into plugin commands for topic-bound sessions, so `/codex bind` works from Telegram forum topics. Refs #75845 and #76049. Thanks @MatthewSchleder.
- Security audit/plugins: ignore plugin install backup, disabled, and dependency debris directories when enumerating installed plugin roots, avoiding false-positive findings for `.openclaw-install-backups` after plugin updates. Fixes #75456.
- Telegram: honor runtime conversation bindings for native slash commands in bound top-level groups, so commands like `/status@bot` route to the active non-`main` session instead of falling back to the default route. Fixes #75405; supersedes #75558. Thanks @ziptbm and @yfge.
- Gateway/tasks: make task registry maintenance use pass-local backing-session lookups and fresh active child-session indexes, avoiding repeated full task snapshots and session-store clones on large stale registries. Fixes #73517 and #75708; supersedes #74406 and #75709. Thanks @Lightningxxl, @glfruit, and @jared-rebel.
- Auth/sessions: JSON-clone auth-profile cache/runtime snapshots and remaining session cleanup previews instead of using `structuredClone`, preserving mutation isolation while avoiding native-memory growth on large stores. Fixes #45438. Thanks @markus-lassfolk.
- Models CLI: restore `openclaw models list --provider <id>` catalog and registry fallback rows for unconfigured providers, so provider-specific verification commands no longer report "No models found." Fixes #75517; supersedes #75615. Thanks @lotsoftick and @koshaji.
- Gateway/macOS: write LaunchAgent services with a canonical system PATH and stop preserving old plist PATH entries, so Volta, asdf, fnm, and pnpm shell paths no longer affect gateway child-process Node resolution. Fixes #75233; supersedes #75246. Thanks @nphyde2.
- Slack/hooks: preserve bot alert attachment text in message-received hook content when command text is blank. Fixes #76035; refs #76036. Thanks @amsminn.
- Sessions/agents: route Gateway session-store writes, CLI cleanup maintenance, and agent-delete session purges through a dedicated in-process writer and borrow the validated mutable cache during the writer slot, avoiding runtime file locks plus repeated `sessions.json` rereads and JSON clones on hot metadata updates. Refs #68554. Thanks @henkterharmsel.
- Control UI/chat: show inline feedback when local slash-command dispatch is unavailable or fails unexpectedly instead of clearing the composer silently. Fixes #52105. Thanks @MooreQiao.
- Memory/markdown: replace CRLF managed blocks in place and collapse duplicate marker blocks without rewriting unmanaged markdown, so Dreaming and Memory Wiki files self-heal from repeated generated sections. Fixes #75491; supersedes #75495, #75810, and #76008. Thanks @asaenokkostya-coder, @ottodeng, @everettjf, and @lrg913427-dot.
- Agents/tools: return critical tool-loop circuit-breaker stops as blocked tool results instead of thrown tool failures, so models see the guardrail and stop retrying the same call. Thanks @rayraiser.
- Agents/sessions: preserve pre-existing runtime model and context window after heartbeat turns so a per-run heartbeat model override does not bleed into shared-session status. Fixes #75452. Thanks @zhangguiping-xydt.
- Model commands: clarify direct and inline `/model` acknowledgements for non-default selections as session-scoped. Thanks @addu2612.
- Doctor/gateway: stop warning that non-existent, unconfigured user-bin directories are required in the Gateway service PATH. Fixes #76017. Thanks @xiphis.
- TUI/chat: skip full provider model normalization during context-window warmup while preserving provider-owned context metadata, avoiding cold-start stalls with large model registries. Thanks @547895019.
- Agents: enable malformed tool-call argument repair for Codex and Azure OpenAI Responses transports while keeping generic OpenAI Responses paths out of the repair gate. Fixes #75154. Thanks @Nimraakram22.
- Memory Wiki: accept relative Markdown links that include the `.md` suffix during broken-wikilink validation, avoiding false positives for native render-mode links. Thanks @Kenneth8128.
- OpenAI Codex: show the device-pairing code in the interactive SSH/headless prompt while keeping the short-lived code out of persistent runtime logs. Fixes #74212. Thanks @da22le123.
- QA Lab: stop gateway children when the suite parent disappears, so interrupted local QA runs cannot leave hot orphaned gateways behind.
- Codex/app-server: tolerate a second connection close during startup recovery and include retry counts plus stringified errors in the restart warning, so concurrent lanes do not fail after one shared-client race.
- Plugins/CLI: cache plugin CLI registration entries per command program so completion state generation does not repeat the full plugin sweep in one invocation. Thanks @ScientificProgrammer.
- Plugins: reuse gateway-bindable plugin loader cache entries for later default-mode loads without serving default-built registries to gateway-bound requests, reducing repeated plugin registration during dispatch. Refs #61756. Thanks @DmitryPogodaev.
- Gateway/secrets: include the caught error message in `secrets.reload` and `secrets.resolve` warning logs while keeping RPC errors generic, so operators can diagnose reload and permission failures. Thanks @davidangularme.
- Providers/OpenRouter: fill DeepSeek V4 `reasoning_content` replay placeholders for `openrouter/deepseek/deepseek-v4-flash` and `openrouter/deepseek/deepseek-v4-pro`, so thinking/tool follow-up turns do not fail with DeepSeek's replay-shape error. Fixes #76018. Thanks @cloph-dsp.
- Anthropic-compatible streams: recover text deltas that arrive before their matching content block, so Kimi Code and similar providers do not finish as empty `incomplete_result` replies. Fixes #76007. Thanks @vliuyt.
- fix(infra): block workspace state-directory env override [AI]. (#75940) Thanks @pgondhi987.
- MCP/OpenAI: normalize parameter-free tool schemas whose top-level object `properties` is missing, null, or invalid before sending tools to OpenAI, so MCP tools without params stay usable. Fixes #75362. Thanks @tolkonepiu and @SymbolStar.
- Control UI/WebChat: add server-side chat-draft microphone dictation via the existing audio transcription pipeline, avoiding browser Web Speech while keeping provider credentials on the Gateway. Fixes #47311. Thanks @jmomford.
- TTS: honor explicit short `[[tts:text]]...[[/tts:text]]` blocks while keeping untagged short auto-TTS suppressed, so tagged voice replies are synthesized instead of being dropped as empty voice-only payloads. Fixes #73758. Thanks @yfge.
- Hooks/doctor: warn when `hooks.transformsDir` points outside the canonical hooks transform directory, so invalid workspace skill paths get a direct recovery hint before the Gateway crash-loops. Fixes #75853. Thanks @midobk.
- Proxy/audio: convert standard `FormData` bodies before proxy-backed undici fetches, so audio transcription and multipart uploads no longer send `[object FormData]` when `HTTP_PROXY` or `HTTPS_PROXY` is configured. Fixes #48554. Thanks @dco5.
- Discord: allow explicitly configured ack reactions in tool-only guild channels while keeping automatic lifecycle/status reactions suppressed. Fixes #74922. Thanks @samvilian and @BlueBirdBack.
- Discord: enable session-backed A2A announce target lookup so `sessions_send` uses the target session's `deliveryContext.accountId` or `lastAccountId` instead of falling back to the default bot in multi-account setups. Fixes #42652; refs #51626 and #44773; supersedes #73975. Thanks @irchelper, @dpalfox, and @Lanfei.
- Discord/setup: write resolved guild/channel allowlist selections to the selected guild and channel instead of falling back to the wildcard guild during setup. Supersedes #47788. Thanks @Eldersonar.
- Discord: treat abort-time Carbon reconnect-exhausted events as expected shutdown during stale-socket restarts, so health-monitor restarts no longer reject the monitor lifecycle. Carries forward #58216; supersedes #73949. Thanks @Perttulands.
- Discord/native commands: return an explicit warning when slash command dispatch or direct plugin execution produces no visible reply instead of a success-style completion ack. Fixes #58986; supersedes #62057. Thanks @jb510.
- Discord: keep typing indicators alive during long tool runs and auto-compaction while keepalive ticks continue, so active sessions do not appear stalled before the final reply. Thanks @Squirbie.
- Discord: preserve multipart Content-Type headers for attachment uploads across REST fetch paths, so generated images and other media no longer fail delivery with `CONTENT_TYPE_INVALID`. Thanks @FunJim.
- Discord: preserve attachment and sticker filenames when saving inbound media, so agents can see human-readable file names instead of only UUID-based paths. Fixes #59744. Thanks @xela92 and @rockcent.
- Discord: preserve non-ASCII channel names in session display labels while keeping allowlist matching on the existing ASCII slug contract. Thanks @swjeong9.
- Discord/PluralKit: canonicalize proxied webhook turns to the original Discord message id for inbound dedupe, while preserving the proxy message id for reply routing. Thanks @acgh213.
- Discord: only inject thread starter context on the first turn of the effective thread session, so follow-up thread replies do not repeat the starter block. Fixes #41355; supersedes #44447 and #44449. Thanks @p3nchan.
- Discord: resolve thread `ownerId` and `parentId` from Discord API-style snake_case payload fields, so bot-owned autoThreads do not require unnecessary mentions. Thanks @mgh3326.
- Gateway/diagnostics: include a bounded redacted startup error message in stability bundles, so crash-loop reports identify the failing plugin or contract without exposing secrets. Refs #75797. Thanks @ymebosma.
- Gateway/pricing: defer optional model pricing catalog refresh until after sidecars and channels reach the ready path, so slow OpenRouter or LiteLLM pricing fetches cannot block Gateway readiness. Fixes #74128; supersedes #73486. Thanks @ctbritt and @alprclbi.
- Gateway/pricing: abort in-flight model pricing catalog fetches when Gateway shutdown stops the refresh loop, and avoid post-stop cache writes or refresh timers. Fixes #72208. Thanks @rzcq.
- Codex/app-server: make startup retry cleanup ownership-aware so concurrent Codex lanes cannot close another lane's freshly restarted shared app-server client. Thanks @vincentkoc.
- Google Meet/Twilio: report missing dial-in details during setup and explain that Twilio cannot join Meet URLs without a phone dial plan.
- Google Meet/Twilio: start the phone leg before sending Meet PIN DTMF, delay intro speech until after the post-connect dial sequence, and log each stage so operators can tell Twilio-leg audio from Meet-room audio.
- Voice Call: accept provider call IDs for gateway speak/continue requests and report ended-call state from history instead of returning a generic "Call not found" for stale calls.
- Control UI/Talk: allow the OpenAI Realtime WebRTC offer endpoint through the Control UI CSP, configure browser sessions with explicit VAD/transcription input settings, and surface OpenAI realtime error/lifecycle events instead of leaving Talk stuck as live with no diagnostic. Fixes #73427.
- Plugins: clarify config-selected duplicate plugin override diagnostics and document manifest schema updates for bundled-plugin forks. Fixes #8582. Thanks @sachah.
- CLI backends/Claude: make live-session JSONL turn caps bounded and configurable via `reliability.outputLimits`, raising the default guard for tool-heavy Claude CLI turns while preserving memory limits. Fixes #75838. Thanks @hcordoba840.
- Telegram/DMs: keep incidental `message_thread_id` reply-with-quote metadata on the flat DM session by default while preserving opt-in DM topic isolation for configured topics, `dm.threadReplies`, and `direct.<chatId>.threadReplies`. Fixes #75975. Thanks @ProjectEvolutionEVE.
- Telegram/network: raise outbound text and typing Bot API request guards to 60 seconds, keep low grammY client timeouts from preempting those guards, let higher `timeoutSeconds` configs extend safe method guards, and retry timed-out typing indicators through the transport fallback without risking duplicate messages. Fixes #76013. Thanks @iaki1206.
- Telegram/native commands: register and clear command menus in both default and group-chat scopes, so `/status` and plugin commands stay available in forum topics. Fixes #74032; updates #6457. Thanks @dae-sun and @WouldenShyp.
- Providers/OpenAI: resolve `keychain:<service>:<account>` `OPENAI_API_KEY` refs before creating OpenAI Realtime browser sessions or voice bridges, with a bounded cached Keychain lookup. Fixes #72120. Thanks @ctbritt.
- Discord/gateway: reconnect when the gateway socket closes while waiting for the shared IDENTIFY concurrency window, instead of silently skipping IDENTIFY and leaving the bot online but unresponsive. Fixes #74617. Thanks @zeeskdr-ai.
- Voice Call: add `sessionScope: "per-call"` for fresh per-call agent memory while preserving the default per-phone caller history. Fixes #45280. Thanks @pondcountry.
- Music generation: raise too-small tool timeouts to the provider-safe 10-second floor and collapse cascading abort fallback errors into a clearer root-cause summary. Thanks @shakkernerd.
- Memory-core/dreaming: include the primary runtime workspace in multi-agent dreaming sweeps without mixing main-agent session transcripts into configured subagent workspaces. Fixes #70014. Thanks @ttomiczek.
- Control UI: add tab/RPC timing attribution and decouple slow Overview/Cron secondary refreshes so Sessions navigation gets immediate visible feedback. Refs #64004. Thanks @WaMaSeDu.
- Memory: retry transient SQLite index file swaps during atomic reindex on Windows, so brief `EBUSY`, `EPERM`, or `EACCES` locks do not fail memory rebuilds. Fixes #64187. Thanks @kunpeng-ai-lab.
- Telegram/startup: use the existing `getMe` request guard for the gateway bot probe instead of a fixed 2.5-second budget, and honor higher `timeoutSeconds` configs for slow Telegram API paths. Fixes #75783. Thanks @tankotan.
- Telegram/models: make model picker confirmations say selections are session-scoped and do not change the agent's persistent default. Fixes #75965. Thanks @sd1114820.
- Control UI/slash commands: keep fallback command metadata on a browser-safe registry path, so provider thinking runtime imports cannot blank the Web UI with `process is not defined`. Fixes #75987. Thanks @novkien.
@@ -53,6 +302,7 @@ Docs: https://docs.openclaw.ai
- WhatsApp/Cron: keep DM pairing-store approvals out of implicit cron and heartbeat recipient fallback, so scheduled automation only uses explicit targets, active configured recipients, or configured `allowFrom` entries. Fixes #62339. Thanks @kelvinisly-collab.
- Google Meet: keep the agent-facing `google_meet` tool visible on non-macOS hosts but block local Chrome realtime actions with guidance, so Linux agents can still use transcribe, Twilio, chrome-node, and artifact flows without choosing the macOS-only BlackHole path. Refs #75950. Thanks @actual-software-inc.
- macOS/settings: keep opening General from rewriting `openclaw.json` during Tailscale settings hydration, preserving `gateway`, `auth`, `meta`, and `wizard` until the user changes a setting. Fixes #59545. Thanks @Tengdw.
- Discord: prioritize interaction callbacks ahead of stale background REST work without polling active REST buckets, validate oversized gateway payloads and member-intent requests before send, and forward explicit component payloads from message actions. (#75363)
- Active Memory: use the configured recall timeout as the blocking prompt-build hook budget by default and move cold-start setup grace behind explicit `setupGraceTimeoutMs` config, so the plugin no longer silently extends 15000 ms configs to 45000 ms on the main lane. Fixes #75843. Thanks @vishutdhar.
- Plugins/web-provider: reuse the active gateway plugin registry for runtime web provider resolution after deriving the same candidate plugin ids as the loader path, avoiding a redundant `loadOpenClawPlugins` call on every request while preserving origin and scope filters. Fixes #75513. Thanks @jochen.
- Crestodian/CLI: exit non-zero when interactive Crestodian is invoked without a TTY, so scripts and CI no longer treat the setup error as success. Fixes #73646 and supersedes #73928 and #74059. Thanks @bittoby, @luyao618, and @Linux2010.
@@ -65,6 +315,7 @@ Docs: https://docs.openclaw.ai
- CLI/message: skip gateway-stop hooks for read-only `message read` and bound stop-hook shutdown for other message actions, so one-shot Discord reads cannot hang behind plugin lifecycle cleanup.
- Plugins/web-provider: cache repeated bundled web search and web fetch provider registry loads by default while preserving explicit cache opt-outs. Supersedes #75992. Thanks @DmitryPogodaev.
- Agents/sandbox: preserve existing workspace file modes when sandbox edits atomically replace files, so 0644 files do not collapse to 0600 after Write/Edit/apply_patch. Fixes #44077. Thanks @patosullivan.
- Control UI/WebChat: route typed `/new` through the New Chat dashboard-session creation flow instead of `chat.send`, while keeping `/reset` as the explicit current-session reset. Fixes #69599. Thanks @WolvenRA.
- Agents/models: keep legacy CLI runtime model refs such as `claude-cli/*` in the configured allowlist after canonical runtime migration, so cron `payload.model` overrides keep working. Fixes #75753. Thanks @RyanSandoval.
- Codex/app-server: restart the shared Codex app-server client once when it closes during startup thread resume, preserving the existing thread binding instead of retrying `thread/start` on a closed client. Thanks @vincentkoc.
- Gateway/watch: keep colored subsystem log prefixes in the managed tmux pane even when the parent shell exports `NO_COLOR`, while preserving explicit `FORCE_COLOR=0` opt-out. Thanks @vincentkoc.
@@ -81,12 +332,14 @@ Docs: https://docs.openclaw.ai
- Web search/Firecrawl: allow self-hosted private/internal Firecrawl `baseUrl` endpoints, including HTTP for private targets, while keeping hosted Firecrawl on the strict official endpoint. Fixes #63877 and supersedes #59666, #63941, and #74013. Thanks @jhthompson12, @jzakirov, @Mlightsnow, and @shad0wca7.
- CLI/models: report gateway model fallback attempts in `infer model run --json` and avoid double-prefixing provider-qualified defaults such as `openrouter/auto` in `models status`. Partially fixes #69527. Thanks @alexifra.
- Providers/OpenRouter: strip trailing assistant prefill turns from verified OpenRouter Anthropic model requests when reasoning is enabled, so Claude 4.6 routes no longer fail with Anthropic's prefill rejection through the OpenAI-compatible adapter. Fixes #75395. Thanks @sbmilburn.
- Voice Call: add per-number inbound routing for dialed-number greetings, response agents/models/prompts, and TTS voice overrides. Fixes #56604. Thanks @healthstatus.
- Feishu: preserve Feishu/Lark HTTP error bodies for message sends, media sends, and chat member lookups, so HTTP 400 failures include vendor code, message, log id, and troubleshooter details. Fixes #73860. Thanks @desksk.
- Agents/transcripts: avoid reopening large Pi transcript files through the synchronous session manager for maintenance rewrites, persisted tool-result truncation, manual compaction boundary hardening, and queued compaction rotation. Thanks @mariozechner.
- Web search/Exa: accept `plugins.entries.exa.config.webSearch.baseUrl`, normalize it to the Exa `/search` endpoint, and partition cached results by endpoint. Fixes #54928 and supersedes #54939. Thanks @mrpl327 and @lyfuci.
- Web search/MiniMax: include MiniMax Search in the web-search setup flow and let `MINIMAX_API_KEY` participate in MiniMax Search auto-detection. Supersedes #65828. Thanks @Jah-yee.
- Plugins/ClawHub: preserve official source-linked trust through archive installs, so OpenClaw can install trusted ClawHub plugin packages that trigger the built-in dangerous-pattern scanner. Thanks @vincentkoc.
- Plugins/ClawHub: install package runtime dependencies for archive-backed plugin installs, so ClawHub packages such as WhatsApp load declared dependencies after download. Thanks @vincentkoc.
- Plugins/tools: cache repeated plugin tool factory results only for matching request context, reducing per-turn tool prep without leaking sandbox, session, browser, delivery, or runtime config state. Fixes #75956. Thanks @Linux2010.
- Providers/LM Studio: allow `models.providers.lmstudio.params.preload: false` to skip OpenClaw's native model-load call so LM Studio JIT loading, idle TTL, and auto-evict can own model lifecycle. Fixes #75921. Thanks @garyd9.
- Agents/transcripts: keep chat history, restart recovery, fork token checks, and stale-token compaction checks on bounded async transcript reads or cached async indexes instead of reparsing large session files. Thanks @mariozechner.
- Telegram: inherit the process DNS result order for Bot API transport and downgrade recovered sticky IPv4 fallback promotions to debug logs, while keeping pinned-IP escalation warnings visible. Fixes #75904. Thanks @highfly-hi and @neeravmakwana.
@@ -115,6 +368,7 @@ Docs: https://docs.openclaw.ai
- Telegram: split long default markdown sends and media follow-up text into safe HTML chunks, so outbound messages over Telegram's limit no longer fail as one oversized Bot API request. Fixes #75868. Thanks @zhengsx.
- Gateway/chat history: merge Claude CLI transcript imports for Anthropic-routed sessions that still have a Claude CLI binding, so local chat history does not hide CLI JSONL turns. Fixes #75850. Thanks @alfredjbclaw.
- Media: trim serialized JSON suffixes after local `MEDIA:` directive file extensions, so generated-image metadata cannot pollute the parsed media path and cause false `ENOENT` delivery failures. Fixes #75182. Thanks @TnzGit and @hclsys.
- Plugins/runtime: hot-reload Gateway plugin runtime surfaces after plugin enable/disable changes while keeping source-changing plugin install, update, and uninstall operations restart-backed so loaded module code is not reused. Fixes #72097.
- Cron: make scheduler reload schedule comparison tolerate malformed persisted jobs, so one bad cron entry no longer aborts the whole tick. Fixes #75886. Thanks @samfox-ai.
- Doctor/channels: warn after migrations when default Telegram or Discord accounts have no configured token and their env fallback (`TELEGRAM_BOT_TOKEN` or `DISCORD_BOT_TOKEN`) is unavailable, with secret-safe migration docs for checking state-dir `.env`. Fixes #74298. Thanks @lolaopenclaw.
- Gateway/diagnostics: keep idle liveness samples in telemetry instead of visible warning logs unless diagnostic work is active, waiting, or queued. Thanks @vincentkoc.
@@ -169,6 +423,7 @@ Docs: https://docs.openclaw.ai
- macOS/Voice Wake: accept trigger-only phrases in the built-in Voice Wake test, matching the settings UI and runtime trigger-only path instead of requiring extra command text after the wake word. Fixes #64986. Thanks @zoiks65.
- Cron/TTS: run cron announce payloads through the normal TTS directive transform before outbound delivery, so scheduled `[[tts]]` replies generate voice payloads instead of leaking raw tags. Fixes #52125. Thanks @kenchen3000.
- WhatsApp: save downloadable quoted image media from reply context as inbound media, so agents can inspect an image that a user replied to instead of only seeing `<media:image>`. Fixes #59174. Thanks @gaffner.
- Sessions/store: stop persisting the runtime-only `skillsSnapshot.resolvedSkills` array inside each session entry, so `sessions.json` no longer carries a copy of every parsed `SKILL.md` body for every active session; `ensureSkillSnapshot` rehydrates the array from disk on cold resume so the embedded runner, the Claude CLI skills plugin, and the Claude live-session fingerprint all see populated skills, and legacy stores self-heal on the next save. Refs #11950, #6650, #15000. Thanks @amoghasgekar.
- Doctor/WhatsApp: warn when Linux crontabs still run the legacy `ensure-whatsapp.sh` health check, which can misreport `Gateway inactive` when cron lacks the systemd user-bus environment. Fixes #60204. Thanks @mySebbe.
- Slack/setup: print the generated app manifest as plain JSON instead of embedding it inside the framed setup note, so it can be copied into Slack without deleting border characters. Fixes #65751. Thanks @theDanielJLewis.
- Channels/WhatsApp: route CLI logout through the live Gateway and stop runtime-backed listeners before channel removal, so removing a WhatsApp account does not leave the old socket replying until restart. Fixes #67746. Thanks @123Mismail.
@@ -198,8 +453,14 @@ Docs: https://docs.openclaw.ai
- Plugins/hooks: derive hook `ctx.channelId` from the conversation target instead of the provider name, so Discord and other channel plugins can keep per-channel state isolated. Fixes #59881. Thanks @bradfreels.
- Gateway/config: log config health-state write failures instead of silently hiding config observe-recovery write errors. Thanks @sallyom.
- Diagnostics: reset stuck-session timers on reply, tool, status, block, and ACP progress events, and back off repeated `session.stuck` diagnostics while a session remains unchanged. Supersedes #72010. Thanks @rubencu.
- Agents/OpenAI: normalize parameter-free MCP tool schemas whose `properties` value is null or undefined, so OpenAI no longer rejects MCP tools without parameters. Fixes #75362. (#75401) Thanks @SymbolStar.
- Gateway/agents: avoid rebuilding core tools for plugin-only allowlists and keep the full plugin registry cache warm across scoped plugin loads, reducing per-turn latency spikes. Fixes #75882, #75907, #75906, #75887, and #75851. (#75922) Thanks @obviyus.
- Agents/failover: classify bare `status: internal server error` provider messages as retryable server errors so model fallback can rotate instead of stopping. (#73844) Thanks @thesomewhatyou.
- Gateway/startup: return the shared retryable startup-sidecars error for startup-gated control-plane RPCs such as sessions.create, sessions.send, sessions.abort, agent.wait, and tools.effective, so clients can retry early sidecar races. (#76012) Thanks @scoootscooob.
- Providers/Google: fix Gemini 2.5 Flash-Lite `reasoning: "minimal"` rejections by raising its thinking-budget floor to 512 while preserving the existing Gemini 2.5 Pro and Flash minimal presets. (#70629) Thanks @ericberic.
- Agents/status: resolve `session_status(sessionKey="current")` for sparse channel-plugin sessions after literal current lookups miss, so Scope, Slack, Discord, and other plugin-driven agents avoid retrying through `Unknown sessionKey: current`. Fixes #74141. (#72306) Thanks @bittoby.
- Cron: retry recurring wake-now main-session jobs through temporary heartbeat busy skips before recording success, so queued cron events no longer appear as ok ghost runs while the main lane is still busy. Fixes #75964. (#76083) Thanks @kshetrajna12 and @xuruiray.
- Providers/Google: keep Gemini thinking-signature-only stream chunks active during reasoning, so Gemini 3.1 Pro Preview replies no longer hit idle timeouts before visible text. Fixes #76071. (#76080) Thanks @marcoschierhorn and @zhangguiping-xydt.
- CLI/skills: show per-agent model and command visibility in `openclaw skills check --agent`, and let doctor report or disable unavailable skills allowed for the default agent. (#75983) Thanks @mbelinky.
## 2026.4.30
@@ -238,6 +499,8 @@ Docs: https://docs.openclaw.ai
- Agents/tools: let plugins declare media generation auth aliases and base-url guards in manifests, preserving OpenAI Codex OAuth image generation availability without core-owned provider special cases. Thanks @shakkernerd.
- Agents/tools: reuse the auth profile store already loaded for the active run when deciding media and generation tool availability, avoiding repeated provider-auth runtime discovery during reply startup. Thanks @shakkernerd.
- Agents/tools: keep image, video, and music generation tool registration on manifest/auth control-plane checks instead of loading runtime provider registries during reply startup, reducing live-path tool-prep blocking while leaving provider runtime resolution for execution and list actions. Thanks @shakkernerd.
- Discord: document canonical mention formatting in agent prompt hints and channel docs so outbound replies use `<@USER_ID>`, `<#CHANNEL_ID>`, and `<@&ROLE_ID>` instead of legacy nickname mentions. (#75173)
- Heartbeat scheduler: gate exec-event/notification/spawn/retry wakes through a centralized cooldown so backgrounded `process.start` exit notifications can no longer self-feed runaway heartbeat runs (configured `every: "30m"` was firing every ~10s in production, pegging the gateway event loop with `eventLoopDelayMaxMs >6s` spikes that stalled control-UI asset serving and TUI handshakes). Documented wake-now paths (`manual`, `wake`, task completion, blocked-task follow-up, `/hooks/wake mode=now`, and cron `--wake now`) remain immediate; retryable busy skips no longer poison the cooldown for the next retry; per-agent flood guard caps any unexpected feedback loop at 5 runs/60s. (#64016, refs #17797 and #75436) Thanks @hexsprite.
- fix: block workspace CLOUDSDK_PYTHON override and always set trusted interpreter for gcloud. (#74492) Thanks @pgondhi987.
- Providers/Z.AI: move the bundled GLM catalog and auth env metadata into the plugin manifest, so `models list --all --provider zai` shows the full known catalog without duplicated runtime seed data. Thanks @shakkernerd.
- Providers/Qianfan and Providers/Stepfun: declare setup auth metadata (`api-key` method, `QIANFAN_API_KEY`, `STEPFUN_API_KEY`) in the plugin manifest so onboarding and `models setup` surface the expected env var without falling back to legacy `providerAuthEnvVars` runtime seed data. Thanks @shakkernerd.
@@ -319,6 +582,7 @@ Docs: https://docs.openclaw.ai
- Telegram/agents: keep typing indicators and optional generation tools off the reply critical path, so fresh Telegram replies no longer stall while provider catalogs and media models load. (#75360) Thanks @obviyus.
- Agents/commitments: run hidden follow-up extraction on the configured agent/default model instead of falling back to direct OpenAI, so OpenAI Codex OAuth-only gateways no longer spam background API-key failures. Fixes #75334. Thanks @sene1337.
- Agents/media: keep async music generation completions on the requester-session wake path even when direct-send completion is enabled, so finished audio stays agent-mediated while video can still opt into direct channel delivery. (#75335) Thanks @vincentkoc.
- Agents/media: keep image and video provider inventory internal when tool output is hidden, so shared chat surfaces no longer expose provider/model/auth-hint details from list results. Fixes #75166. Thanks @MkDev11.
- Security/config-audit: redact CLI argv and execArgv secrets before persisting config audit records, covering write, observe, and recovery paths. Fixes #60826. Thanks @koshaji.
- Gateway/models: keep default and configured model-list views responsive when provider catalog discovery stalls, without hiding real catalog load failures, while `--all` still waits for the exact full catalog. Fixes #75297; refs #74404. Thanks @lisandromachado and @najef1979-code.
- Plugins/runtime-deps: accept already materialized package-level runtime-deps supersets as converged, so later lazy plugin activation no longer prunes and relaunches `pnpm install` after gateway startup pre-staging, reducing event-loop pressure from repeated runtime-deps repair on packaged installs. Fixes #75283; refs #75297 and #72338. Thanks @brokemac79, @lisandromachado, and @midhunmonachan.
@@ -371,6 +635,7 @@ Docs: https://docs.openclaw.ai
- Context Engine: treat assembled prompt as the default authority for preemptive overflow prechecks so engines that return a windowed, self-contained context no longer trigger false hard-fail compactions on huge raw history. Engines whose assembled view can hide overflow risk can opt back into the legacy behavior with `AssembleResult.promptAuthority: "preassembly_may_overflow"`. (#74255) Thanks @100yenadmin.
- Mattermost: refresh current native slash command registrations before accepting callbacks so stale tokens from deleted or regenerated commands stop being accepted without a gateway restart while failed validations stay briefly cached and lookup starts are rate-limited per command, gate each callback against the resolved command's own startup token so a token leaked for one slash command cannot poison another command's failure cache, redact slash validation lookup errors, and add a body read timeout to the multi-account routing path so slow callback senders cannot tie up the dispatcher. Thanks @feynman-hou and @eleqtrizit.
- Security/dotenv: block `COMSPEC` in workspace `.env` so a malicious repo cannot redirect Windows `cmd.exe` resolution, and lock in case-insensitive workspace-`.env` regression coverage for the full Windows shell trust-root family (`COMSPEC`, `PROGRAMFILES`, `PROGRAMW6432`, `SYSTEMROOT`, `WINDIR`). (#74460) Thanks @mmaps.
- Gateway/install: drop stale version-manager and package-manager PATH entries preserved from old service files during `gateway install --force` and doctor repair, so the repair path no longer recreates `gateway-path-nonminimal` warnings. Fixes #75220. (#75440) Thanks @leonaIee, @renaudcerrato, and @aaajiao.
## 2026.4.29
@@ -429,6 +694,7 @@ Docs: https://docs.openclaw.ai
- Active Memory: clarify the deprecated `modelFallbackPolicy` warning and config help so `modelFallback` is described as a chain-resolution last resort, not runtime failover. (#74602) Thanks @jeffrey701.
- Channels/Discord: keep read-only allowlist/default-target accessors from resolving SecretRef-backed bot tokens, so status and channel summaries no longer fail when tokens are only available in gateway runtime. (#74737) Thanks @eusine.
- Gateway/sessions: align session abort wait semantics across `chat`, `agent`, and `sessions` server methods so abort RPCs return after the targeted sessions actually halt instead of resolving early while runs are still draining. (#74751) Thanks @BunsDev.
- Gateway/sessions: reuse one subagent registry read index for `sessions.list` `spawnedBy` filtering and row enrichment so subagent ownership stays consistent without repeated registry reloads. Carries forward #75013. Thanks @anyech.
- Agents/output: drop copied inbound metadata-only assistant replay turns before provider replay instead of synthesizing a placeholder, so Telegram and other channels cannot receive `[assistant copied inbound metadata omitted]` as model output. Fixes #74745. Thanks @adamwdear and @Marvae.
- Doctor/memory: suppress skipped embedding-readiness warnings for key-optional providers such as Ollama and LM Studio while preserving timeout and not-ready diagnostics. Fixes #74608 and #73882. Thanks @hclsys.
- Channels/groups: preserve observe-only turn suppression for prepared dispatch paths and restore deprecated channel turn runtime aliases, so passive observer/group flows stay silent while older plugins keep compiling. Thanks @vincentkoc.
@@ -648,7 +914,7 @@ Docs: https://docs.openclaw.ai
- Outbound/security: strip known internal runtime scaffolding such as `<system-reminder>` and `<previous_response>` at the final channel delivery boundary and keep Discord output on targeted tag stripping, so degraded harness replies cannot leak those tags to users. Fixes #73595. Thanks @gabrielexito-stack and @martingarramon.
- Security/Telegram: load Telegram security adapters in read-only audit/doctor, audit malformed Telegram DM `allowFrom` entries even when groups are disabled, and keep allowlist DM audits from counting stale pairing-store senders, so public/shared-DM risk checks stay accurate. Refs #73698. Thanks @xace1825.
- Plugins: remove hidden manifest, provider-owner, bootstrap, and channel metadata caches so plugin installs, manifest edits, and bundled-root changes are visible on the next metadata read while keeping runtime/module loader caches for actual plugin code. Thanks @shakkernerd.
- Control UI/WebChat: create a fresh dashboard session from the New Chat button instead of resetting the current transcript with `/new`, while keeping explicit `/new` reset behavior, preserving in-progress composer edits during delayed session creation or when creation cannot safely switch sessions, and showing clear retry feedback when creation is blocked, refreshing, or returns no new session. Carries forward #52042 and #52746. Thanks @bobashopcashier and @vincentkoc.
- Control UI/WebChat: create a fresh dashboard session from the New Chat button instead of resetting the current transcript with `/new`, preserving in-progress composer edits during delayed session creation or when creation cannot safely switch sessions, and showing clear retry feedback when creation is blocked, refreshing, or returns no new session. Carries forward #52042 and #52746. Thanks @bobashopcashier and @vincentkoc.
- CLI/plugins: use plugin metadata snapshots for install slot selection and add opt-in plugin lifecycle timing traces, so plugin install avoids runtime-loading the plugin registry for metadata-only decisions. Thanks @shakkernerd.
- fix(plugins): restrict bundled plugin dir resolution to trusted package roots. (#73275) Thanks @pgondhi987.
- fix(security): prevent workspace PATH injection via service env and trash helpers. (#73264) Thanks @pgondhi987.

View File

@@ -15,6 +15,9 @@ ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
# Keep in sync with .github/actions/setup-node-env/action.yml bun-version.
# To update: docker buildx imagetools inspect oven/bun:<version> and use the manifest-list digest.
ARG OPENCLAW_BUN_IMAGE="oven/bun:1.3.13@sha256:87416c977a612a204eb54ab9f3927023c2a3c971f4f345a01da08ea6262ae30e"
# Base images are pinned to SHA256 digests for reproducible builds.
# Dependabot refreshes these blessed digests; release builds consume the
@@ -37,22 +40,12 @@ RUN --mount=type=bind,source=${OPENCLAW_BUNDLED_PLUGIN_DIR},target=/tmp/${OPENCL
done
# ── Stage 2: Build ──────────────────────────────────────────────
FROM ${OPENCLAW_BUN_IMAGE} AS bun-binary
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
# Install Bun (required for build scripts). Retry the whole bootstrap flow to
# tolerate transient 5xx failures from bun.sh/GitHub during CI image builds.
RUN set -eux; \
for attempt in 1 2 3 4 5; do \
if curl --retry 5 --retry-all-errors --retry-delay 2 -fsSL https://bun.sh/install | bash; then \
break; \
fi; \
if [ "$attempt" -eq 5 ]; then \
exit 1; \
fi; \
sleep $((attempt * 2)); \
done
ENV PATH="/root/.bun/bin:${PATH}"
# Copy pinned Bun binary from the official image instead of fetching via curl.
COPY --from=bun-binary /usr/local/bin/bun /usr/local/bin/bun
RUN corepack enable

View File

@@ -1,4 +0,0 @@
.PHONY: build
build:
pnpm build

View File

@@ -26,6 +26,7 @@ For OpenClaw core issues, submit through a private [GitHub Security Advisory](ht
Maintainers may close, hide, delete, or otherwise take down public issues and PRs that disclose vulnerabilities or active security issues. We will redirect those reports through the private disclosure process so the issue can be triaged and fixed without giving attackers a public playbook.
For full reporting instructions see our [Trust page](https://trust.openclaw.ai).
For maintainer response workflow, see the [incident response plan](docs/security/incident-response.md).
OpenClaw does not currently run a paid bug bounty program. Please still disclose responsibly so we can fix real issues quickly. The best way to help the project right now is to send high-signal reports and, when practical, focused PRs.
@@ -344,13 +345,12 @@ OpenClaw uses several security and release-validation layers. No single scanner
### Secret Detection
OpenClaw uses `detect-secrets` with a checked-in baseline and local exclusion notes (`.secrets.baseline`, `.detect-secrets.cfg`). Secret-resolution behavior is also covered by the dedicated secrets test surface.
OpenClaw runs the pre-commit `detect-private-key` hook in CI and keeps secret-resolution behavior covered by the dedicated secrets test surface.
Run the baseline scan locally:
Run the key scan locally:
```bash
pip install detect-secrets==1.5.0
detect-secrets scan --baseline .secrets.baseline
pre-commit run --all-files detect-private-key
```
### Static Analysis

View File

@@ -2,6 +2,406 @@
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>OpenClaw</title>
<item>
<title>2026.5.2</title>
<pubDate>Sun, 03 May 2026 01:11:51 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026050290</sparkle:version>
<sparkle:shortVersionString>2026.5.2</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.5.2</h2>
<h3>Highlights</h3>
<ul>
<li>External plugin installation, update, doctor repair, dependency reporting, and artifact metadata now cover the npm-first cutover, stale configured installs, missing package payloads, and beta-channel plugin fallback. Thanks @vincentkoc.</li>
<li>Gateway and agent hot paths are leaner across startup, session listing, task maintenance, prompt prep, plugin loading, tool descriptor planning, filesystem guards, and large runtime configs.</li>
<li>Control UI and WebChat are more resilient across Sessions, Cron, long-running Gateway WebSockets, grouped-message width, slash-command feedback, iOS PWA bounds, selection contrast, and Talk diagnostics.</li>
<li>Messaging fixes cover WhatsApp Channel/Newsletter targets, Telegram topic commands and networking, Discord delivery/startup edge cases, Slack threads, Signal groups/media, and visible reply routing.</li>
<li>Provider and media fixes cover OpenAI-compatible TTS/Realtime, OpenRouter/DeepSeek replay, Anthropic-compatible streaming, LM Studio reasoning metadata, Brave/SearXNG/Firecrawl web search, media paths, music, and voice-call routing.</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Gateway/startup and restart: skip plugin-backed auth-profile overlays during startup secrets preflight, reducing gateway readiness latency while keeping reload and OAuth recovery paths overlay-capable; add <code>openclaw gateway restart --force</code> and <code>--wait <duration></code>, log active task run IDs before restart deferral timers, and report timeout restarts as explicit forced restarts. (#68327) Thanks @JIRBOY.</li>
<li>Plugins/ClawHub: make diagnostics, onboarding, doctor repair, and channel setup carry ClawPack metadata through install records while keeping explicit <code>clawhub:</code> installs on ClawHub and bare package installs on npm for the launch cutover. Thanks @vincentkoc.</li>
<li>Plugins/CLI: include package dependency install state in <code>openclaw plugins list --json</code> so scripts can spot missing plugin dependencies without runtime-loading plugins.</li>
<li>Plugins/update: on the beta OpenClaw update channel, default-line npm and ClawHub plugin updates try <code>@beta</code> first and fall back to default/latest when no plugin beta release exists.</li>
<li>Plugins/runtime: scope broad runtime preloads to the effective plugin ids derived from config, startup planning, configured channels, slots, and auto-enable rules instead of importing every discoverable plugin.</li>
<li>Agents/runtime: reuse the startup-loaded plugin registry for request-time providers, tools, channel actions, web/capability/memory/migration helpers, and memoized provider extra-params, and memoize transcript replay-policy resolution for stable config and process-env runs while preserving model-specific transport hook patches and custom-env provider behavior. Thanks @DmitryPogodaev.</li>
<li>Infra/path-guards: add a fast path for canonical absolute POSIX containment checks, avoiding repeated <code>path.resolve</code> and <code>path.relative</code> work in hot filesystem walkers. Refs #75895, #75575, and #68782. Thanks @Enderfga.</li>
<li>Tools/plugins: add a platform-level tool descriptor planner for descriptor-first visibility, generic availability checks, and executor references, and cache plugin tool descriptors captured from <code>api.registerTool(...)</code> so repeated prompt-time planning can skip plugin runtime loading while execution still loads the live plugin tool. (#76079) Thanks @shakkernerd.</li>
<li>Docs/Codex: clarify that ChatGPT/Codex subscription setups should use <code>openai/gpt-*</code> with <code>agentRuntime.id: "codex"</code> for native Codex runtime, while <code>openai-codex/*</code> remains the PI OAuth route. Thanks @pashpashpash.</li>
<li>Plugins/source checkout: load bundled plugins from the <code>extensions/*</code> pnpm workspace tree in source checkouts, so plugin-local dependencies and edits are used directly while packaged installs keep using the built runtime tree. Thanks @vincentkoc.</li>
<li>Plugins/beta: externalize ACPX behind <code>@openclaw/acpx</code> and diagnostics OpenTelemetry behind <code>@openclaw/diagnostics-otel</code>, keeping their heavier runtime stacks out of the core package until installed; prepare Google Chat, LINE, Matrix, Mattermost, BlueBubbles, diagnostics Prometheus, Google Meet, Nextcloud Talk, Nostr, Zalo, Zalo Personal, diagnostics OpenTelemetry, Discord, Diffs, Lobster, Memory LanceDB, Microsoft Teams, QQ Bot, Voice Call, WhatsApp, Brave, Codex, Feishu, Synology Chat, Tlon, and Twitch for <code>2026.5.1-beta.1</code>/<code>2026.5.1-beta.2</code> npm and ClawHub publishing, and keep publishable plugin dist trees out of the core npm package. Thanks @vincentkoc.</li>
<li>Providers/xAI: add Grok 4.3 to the bundled catalog and make it the default xAI chat model.</li>
<li>Google Meet: let API-created rooms set <code>accessType</code> and <code>entryPointAccess</code>, add <code>googlemeet end-active-conference</code> for closing managed spaces after a call, and add <code>googlemeet test-listen</code> plus the matching <code>google_meet</code> <code>test_listen</code> action so transcribe-mode joins wait for real caption or transcript movement before reporting listen-first health. (#74824; refs #72478) Thanks @BsnizND and @DougButdorf.</li>
<li>Plugins/ClawHub/onboarding: prefer versioned ClawPack artifacts when ClawHub publishes digest metadata, verify ClawPack response headers and downloaded bytes, persist ClawPack digest/artifact metadata on install/update records and install-on-demand provider setup entries, and allow official bundled-plugin cutovers to record ClawHub artifact metadata while preserving npm as the launch default for bare package specs and retaining npm/local fallback paths. Thanks @vincentkoc.</li>
<li>Plugins/Crestodian: add ClawHub plugin search plus Crestodian plugin list/search/install/uninstall operations, with approval and audit coverage for install and uninstall.</li>
<li>Channels/thread bindings: replace split subagent/ACP thread-spawn toggles with <code>threadBindings.spawnSessions</code>, default thread-bound spawns on, and let <code>openclaw doctor --fix</code> migrate the legacy keys. (#75943)</li>
<li>Providers/OpenAI: add <code>extraBody</code>/<code>extra_body</code> passthrough for OpenAI-compatible TTS endpoints, so custom speech servers can receive fields such as <code>lang</code> in <code>/audio/speech</code> requests. Fixes #39900. Thanks @R3NK0R.</li>
<li>Channels/WhatsApp: support explicit WhatsApp Channel/Newsletter <code>@newsletter</code> outbound message targets with channel session metadata instead of DM routing. Fixes #13417; carries forward the narrow outbound target idea from #13424. Thanks @vincentkoc and @agentz-manfred.</li>
<li>Dependencies: refresh workspace, bundled runtime, and plugin dependency pins, including TypeBox 1.1.37, AWS SDK 3.1041.0, Microsoft Teams 2.0.9, Marked 18.0.3, Pi 0.71.1, OpenAI 6.35.0, Codex 0.128.0, Zod 4.4.1, and Matrix 41.4.0. Thanks @mariozechner, @aws, and @microsoft.</li>
<li>Discord/channels: add reusable message-channel access groups plus Discord channel-audience DM authorization, so allowlists can reference <code>accessGroup:<name></code> across channel auth paths. (#75813)</li>
<li>Crabbox/scripts: print the selected Crabbox binary, version, and supported providers before <code>pnpm crabbox:*</code> commands, and reject stale binaries that lack <code>blacksmith-testbox</code> provider support.</li>
<li>Agents/Codex: add committed happy-path prompt snapshots for Codex/message-tool Telegram direct, Discord group, and heartbeat turns so prompt drift can be reviewed. Thanks @pashpashpash.</li>
<li>Agents/workspace: add <code>agents.defaults.skipOptionalBootstrapFiles</code> for skipping selected optional workspace files during bootstrap without disabling required workspace setup. (#62110) Thanks @mainstay22.</li>
<li>Plugins/CLI: add first-class <code>git:</code> plugin installs with ref checkout, commit metadata, normal scanner/staging, and <code>plugins update</code> support for recorded git sources. Thanks @badlogic.</li>
<li>Google Meet: add live caption health for Chrome transcribe mode, including caption observer state, transcript counters, last caption text, and recent transcript lines in status and doctor output. Refs #72478. Thanks @DougButdorf.</li>
<li>Voice Call/Google Meet: add Twilio Meet join phase logs around pre-connect DTMF, realtime stream setup, and initial greeting handoff for easier live-call debugging. Thanks @donkeykong91 and @PfanP.</li>
<li>macOS app: move recent session context rows into a Context submenu while keeping usage and cost details root-level, so the menu bar companion stays compact with many active sessions. Thanks @guti.</li>
<li>Gateway/SDK: add SDK-facing tools.invoke RPC with shared HTTP policy, typed approval/refusal results, and SDK helper support. Refs #74705. Thanks @BunsDev and @ai-hpc.</li>
<li>Discord: keep active buttons, selects, and forms working across Gateway restarts until they expire, so multi-step Discord interactions are less likely to break during upgrades or restarts. Thanks @amknight.</li>
<li>Messages/docs: clarify that <code>BodyForAgent</code> is the primary inbound model text while <code>Body</code> is the legacy envelope fallback, and add Signal coverage so channel hardening patches target the real prompt path. Refs #66198. Thanks @defonota3box.</li>
<li>Slack: publish a safe default App Home tab view on <code>app_home_opened</code>, include the Home tab event in setup manifests, and keep track of bot-participated threads across restarts so ongoing threaded conversations can continue auto-replying after the Gateway restarts. Fixes #11655; refs #52020. Thanks @TinyTb and @amknight.</li>
<li>Control UI/Usage: add UTC quarter-hour token buckets for the Usage Mosaic and reuse them for hour filtering, keeping the legacy session-span fallback for older summaries. (#74337) Thanks @konanok.</li>
<li>BlueBubbles: add opt-in <code>channels.bluebubbles.replyContextApiFallback</code> that fetches the original message from the BlueBubbles HTTP API when the in-memory reply-context cache misses (multi-instance deployments sharing one BB account, post-restart, after long-lived TTL/LRU eviction). Off by default; channel-level setting propagates to accounts that omit the flag through <code>mergeAccountConfig</code>; routed through the typed <code>BlueBubblesClient</code> so every fetch is SSRF-guarded by the same three-mode policy as every other BB client request; reply-id shape is validated and part-index prefixes (<code>p:0/<guid></code>) are stripped before the request; concurrent webhooks for the same <code>replyToId</code> coalesce into one fetch and successful responses populate the reply cache for subsequent hits. Also promotes BlueBubbles attachment download failures from verbose to runtime error so silently-dropped inbound images are visible at default log level, and extends <code>sanitizeForLog</code> to redact <code>?password=…</code>/<code>?token=…</code> query params and <code>Authorization:</code> headers before they reach the log sink (CWE-532). (#71820) Thanks @coletebou and @zqchris.</li>
<li>CLI/proxy: add <code>openclaw proxy validate</code> so operators can verify effective proxy configuration, proxy reachability, and expected allow/deny destination behavior before deploying proxy-routed OpenClaw commands. (#73438) Thanks @jesse-merhi.</li>
<li>Agents/Codex: default Codex app-server dynamic tools to native-first, keeping OpenClaw integration tools while leaving file, patch, exec, and process ownership to the Codex harness; default Codex-harness direct source replies to the OpenClaw <code>message</code> tool when visible reply delivery is not explicitly configured, keeping channel-visible output as a deliberate tool call. (#75308, #75765) Thanks @pashpashpash.</li>
<li>Heartbeats/agents: add a structured <code>heartbeat_respond</code> tool for tool-capable heartbeat runs so agents can record quiet outcomes or explicit notification text without relying only on <code>HEARTBEAT_OK</code> parsing. (#75765) Thanks @pashpashpash.</li>
<li>Gateway/config: allow <code>$include</code> directives to read files from operator-approved <code>OPENCLAW_INCLUDE_ROOTS</code> directories while preserving default config-directory confinement. Thanks @ificator.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Agents/OpenAI: default GPT-5 API-key sessions to the SSE Responses transport unless WebSocket is explicitly selected, restoring replies in fresh Control UI and WebChat beta installs where the auto WebSocket path connected but produced no model events.</li>
<li>Agents/sessions: preserve terminal lifecycle state when final run metadata persists from a stale in-memory snapshot, preventing sessions from staying stuck as running after completed or timed-out turns.</li>
<li>Gateway/CLI/status: make <code>openclaw gateway start</code> repair stale managed service definitions that point at old OpenClaw versions, missing binaries, or temporary installer paths before starting; add concrete service, config, listener-owner, and log collection next steps when gateway probes fail and Bonjour finds no local gateway; avoid repeated plugin tool descriptor config hashing so large runtime configs do not block reply startup and trigger reconnect/timeouts. Refs #49012. (#75944) Thanks @vincentkoc and @joshavant.</li>
<li>Plugins/update/config: stop treating the non-plugin <code>auth</code> command root as a bundled plugin id, keep packaged upgrades and beta external plugin installs on stable runtime aliases and matching prerelease npm specs, detect tracked plugin install records whose package directories disappeared during <code>openclaw update</code>, reinstall them before normal plugin updates, fail the update if install records still point at missing disk payloads, and validate configured web-search providers plus statically suppressed model/provider pairs against the active plugin set at config load. Thanks @vincentkoc.</li>
<li>Codex/app-server: resolve managed binaries from bundled <code>dist</code> chunks and from the <code>@openai/codex</code> package bin when installs do not provide a nearby <code>.bin/codex</code> shim, avoiding false missing-binary startup failures.</li>
<li>Status: show the <code>openai-codex</code> OAuth profile for <code>openai/gpt-*</code> sessions running through the native Codex runtime instead of reporting auth as unknown. (#76197) Thanks @mbelinky.</li>
<li>Status/update: resolve beta update-channel checks from the installed version when config still says <code>stable</code>, show configured channels in <code>openclaw status</code> and config-only <code>openclaw channels status</code> output even when the Gateway is unreachable, and let <code>status --deep</code> reuse live gateway channel credential state instead of warning on command-path-only token misses. Thanks @vincentkoc.</li>
<li>Plugins/externalization: add official npm-first catalogs for externalized channel, provider, and generic plugins; install official external web-search plugins before saving provider config; repair missing configured, selected-search, and env-selected plugin installs from npm by default; keep official install docs, update examples, live Codex checks, diagnostics ClawHub packages, and persisted bundled-plugin relocation on default npm tags; keep Matrix and Mattermost bundled until their npm packages cut over; and keep ACPX, Google Chat, and LINE publishable plugin dist trees out of the core package while ClawHub pack files roll out. Thanks @vincentkoc.</li>
<li>Plugins/ClawHub/source/registry: use the ClawHub artifact resolver response as the install decision before downloading, keep bare plugin package specs on npm for the launch cutover and reserve ClawHub resolution for explicit <code>clawhub:</code> specs until ClawHub pack readiness is deployed, discover source-only plugins such as Codex from <code>extensions/*</code>, install ClawPack artifacts from the explicit npm-pack <code>.tgz</code> resolver path, persist artifact kind, npm integrity, shasum, and tarball metadata for update/diagnostics flows, fall back to version metadata when the artifact resolver route is missing, keep the Docker ClawHub fixture aligned with npm-pack artifact resolution, explain unavailable explicit ClawHub ClawPack artifact downloads with a temporary npm install hint, and hash manifest/package metadata when validating persisted plugin registries so fast same-size rewrites cannot leave stale plugin metadata trusted. Thanks @vincentkoc.</li>
<li>Control UI: add validated <code>gateway.controlUi.chatMessageMaxWidth</code> instead of patched bundled CSS, ignore malformed persisted cron rows before they enter UI state, guard stale cron render paths, and bound the default Sessions tab query to recent activity and fewer rows while keeping filters editable. Fixes #67935, #55047, #54439, and #76050; supersedes #54550 and #54552. (#76051) Thanks @xiew4589-lang and @Neomail2.</li>
<li>Gateway/channels: cap startup fanout at four channel/account handoffs and recover from Bonjour ciao self-probe races, reducing Windows startup stalls with many Telegram accounts. Fixes #75687.</li>
<li>Gateway/sessions: keep <code>sessions.list</code> polling responsive on large session stores by reusing list-safe session cache/indexes and returning a lightweight compaction checkpoint preview instead of heavyweight summaries. Thanks @rolandrscheel.</li>
<li>Control UI/Gateway: keep long-running dashboard WebSocket sessions alive with protocol pings, keep Stop available after reconnect or reload by recovering session-scoped active-run abort state, contain standalone iOS PWA viewports with safe-area-aware document locking, use high-contrast text selection colors, and show inline feedback when local slash-command dispatch is unavailable or fails unexpectedly. Fixes #70991, #60850, and #52105; supersedes #60854. Thanks @alexandre-leng, @kvncrw, @Badschaff, @efe-arv, and @MooreQiao.</li>
<li>CLI/update: treat inherited Gateway service markers as origin hints and only block package replacement when the managed Gateway is still live, so self-updates can stop the service and continue safely. (#75729) Thanks @hxy91819.</li>
<li>Agents/failover: exempt run-level timeouts that fire during tool execution from model fallback, timeout-triggered compaction, and generic timeout payload synthesis, avoiding misleading "LLM request timed out" errors after the primary model has already responded. Fixes #52147. (#75873) Thanks @simonusa.</li>
<li>Docker: copy Bun 1.3.13 from a digest-pinned image and keep CI on the same version. Fixes #74356. Thanks @fede-kamel and @sallyom.</li>
<li>Agents/compaction: keep prior context on consecutive turns against z.ai-style providers (z.ai direct, openrouter z-ai/\*, in-house GLM gateways), avoiding accidental Pi state reset after successful turns. (#76056) Thanks @openperf.</li>
<li>Doctor/plugins: run a one-time 2026.5.2 configured-plugin install repair based on <code>meta.lastTouchedVersion</code>, update stale configured plugin manifests that still declare channels without <code>channelConfigs</code>, install actively used downloadable OpenClaw plugins through the configured external source, preserve unmanaged third-party plugin <code>node_modules</code>, and then mark the config touched for the release.</li>
<li>Sessions/transcripts: use one <code>session.writeLock.acquireTimeoutMs</code> policy for session transcript lock acquisitions and raise the default wait to 60 seconds, avoiding user-visible lock timeouts during legitimate slow prep, cleanup, compaction, and mirror work. Fixes #75894. Thanks @shandutta.</li>
<li>Agents/restart recovery: match cleaned transcript locks by exact transcript lock paths plus the canonical session fallback, so interrupted main sessions using topic-suffixed transcripts resume after gateway restart. Refs #76052. Thanks @anyech.</li>
<li>Agents/runtime: cache the stable system-prompt prefix and reuse prompt-report tool schema stats during dispatch prep, reducing repeated CPU work before streaming starts. Fixes #75999; supersedes #76061. Thanks @zackchiutw and @STLI69.</li>
<li>Telegram/native commands: pass persisted session files into plugin commands for topic-bound sessions, so <code>/codex bind</code> works from Telegram forum topics. Refs #75845 and #76049. Thanks @MatthewSchleder.</li>
<li>Security audit/plugins: ignore plugin install backup, disabled, and dependency debris directories when enumerating installed plugin roots, avoiding false-positive findings for <code>.openclaw-install-backups</code> after plugin updates. Fixes #75456.</li>
<li>Telegram: honor runtime conversation bindings for native slash commands in bound top-level groups, so commands like <code>/status@bot</code> route to the active non-<code>main</code> session instead of falling back to the default route. Fixes #75405; supersedes #75558. Thanks @ziptbm and @yfge.</li>
<li>Gateway/tasks: make task registry maintenance use pass-local backing-session lookups and fresh active child-session indexes, avoiding repeated full task snapshots and session-store clones on large stale registries. Fixes #73517 and #75708; supersedes #74406 and #75709. Thanks @Lightningxxl, @glfruit, and @jared-rebel.</li>
<li>Auth/sessions: JSON-clone auth-profile cache/runtime snapshots and remaining session cleanup previews instead of using <code>structuredClone</code>, preserving mutation isolation while avoiding native-memory growth on large stores. Fixes #45438. Thanks @markus-lassfolk.</li>
<li>Models CLI: restore <code>openclaw models list --provider <id></code> catalog and registry fallback rows for unconfigured providers, so provider-specific verification commands no longer report "No models found." Fixes #75517; supersedes #75615. Thanks @lotsoftick and @koshaji.</li>
<li>Gateway/macOS: write LaunchAgent services with a canonical system PATH and stop preserving old plist PATH entries, so Volta, asdf, fnm, and pnpm shell paths no longer affect gateway child-process Node resolution. Fixes #75233; supersedes #75246. Thanks @nphyde2.</li>
<li>Slack/hooks: preserve bot alert attachment text in message-received hook content when command text is blank. Fixes #76035; refs #76036. Thanks @amsminn.</li>
<li>Sessions/agents: route Gateway session-store writes, CLI cleanup maintenance, and agent-delete session purges through a dedicated in-process writer and borrow the validated mutable cache during the writer slot, avoiding runtime file locks plus repeated <code>sessions.json</code> rereads and JSON clones on hot metadata updates. Refs #68554. Thanks @henkterharmsel.</li>
<li>Memory/markdown: replace CRLF managed blocks in place and collapse duplicate marker blocks without rewriting unmanaged markdown, so Dreaming and Memory Wiki files self-heal from repeated generated sections. Fixes #75491; supersedes #75495, #75810, and #76008. Thanks @asaenokkostya-coder, @ottodeng, @everettjf, and @lrg913427-dot.</li>
<li>Agents/tools: return critical tool-loop circuit-breaker stops as blocked tool results instead of thrown tool failures, so models see the guardrail and stop retrying the same call. Thanks @rayraiser.</li>
<li>Agents/sessions: preserve pre-existing runtime model and context window after heartbeat turns so a per-run heartbeat model override does not bleed into shared-session status. Fixes #75452. Thanks @zhangguiping-xydt.</li>
<li>Model commands: clarify direct and inline <code>/model</code> acknowledgements for non-default selections as session-scoped. Thanks @addu2612.</li>
<li>Doctor/gateway: stop warning that non-existent, unconfigured user-bin directories are required in the Gateway service PATH. Fixes #76017. Thanks @xiphis.</li>
<li>TUI/setup: skip full provider model normalization during context-window warmup and bound Terminal hatch bootstrap provider requests, avoiding cold-start stalls with large model registries and first-run hatching stuck behind the watchdog. (#76241) Thanks @547895019 and @joshavant.</li>
<li>Agents: enable malformed tool-call argument repair for Codex and Azure OpenAI Responses transports while keeping generic OpenAI Responses paths out of the repair gate. Fixes #75154. Thanks @Nimraakram22.</li>
<li>Memory Wiki: accept relative Markdown links that include the <code>.md</code> suffix during broken-wikilink validation, avoiding false positives for native render-mode links. Thanks @Kenneth8128.</li>
<li>OpenAI Codex: show the device-pairing code in the interactive SSH/headless prompt while keeping the short-lived code out of persistent runtime logs. Fixes #74212. Thanks @da22le123.</li>
<li>QA Lab: stop gateway children when the suite parent disappears, so interrupted local QA runs cannot leave hot orphaned gateways behind.</li>
<li>Codex/app-server/plugins: tolerate second connection closes during startup recovery, include retry counts plus stringified restart errors, and allow the official npm Codex plugin to install without the unsafe-install override while keeping <code>/codex</code> command ownership and covering the real npm Docker live path through managed <code>.openclaw/npm</code> dependencies plus uninstall failure proof.</li>
<li>Plugins/CLI: cache plugin CLI registration entries per command program so completion state generation does not repeat the full plugin sweep in one invocation. Thanks @ScientificProgrammer.</li>
<li>Plugins: reuse gateway-bindable plugin loader cache entries for later default-mode loads without serving default-built registries to gateway-bound requests, reducing repeated plugin registration during dispatch. Refs #61756. Thanks @DmitryPogodaev.</li>
<li>Gateway/secrets: include the caught error message in <code>secrets.reload</code> and <code>secrets.resolve</code> warning logs while keeping RPC errors generic, so operators can diagnose reload and permission failures. Thanks @davidangularme.</li>
<li>Providers/OpenRouter/LM Studio/Anthropic: fill DeepSeek V4 <code>reasoning_content</code> replay placeholders for <code>openrouter/deepseek/deepseek-v4-flash</code> and <code>openrouter/deepseek/deepseek-v4-pro</code>, normalize binary LM Studio reasoning metadata from Gemma 4 and other local models, and recover Anthropic-compatible stream text deltas that arrive before their matching content block. Fixes #76018 and #76007. Thanks @cloph-dsp and @vliuyt.</li>
<li>fix(infra): block workspace state-directory env override [AI]. (#75940) Thanks @pgondhi987.</li>
<li>MCP/OpenAI and media: normalize parameter-free MCP tool schemas before OpenAI tool submission, honor explicit short <code>[[tts:text]]...[[/tts:text]]</code> blocks while keeping untagged short auto-TTS suppressed, and accept home-relative <code>MEDIA:~/...</code> attachment paths under the existing file-read policy. Fixes #75362, #73758, and #73796. Thanks @tolkonepiu, @SymbolStar, @yfge, and @fabkury.</li>
<li>Hooks/doctor: warn when <code>hooks.transformsDir</code> points outside the canonical hooks transform directory, so invalid workspace skill paths get a direct recovery hint before the Gateway crash-loops. Fixes #75853. Thanks @midobk.</li>
<li>Proxy/audio: convert standard <code>FormData</code> bodies before proxy-backed undici fetches, so audio transcription and multipart uploads no longer send <code>[object FormData]</code> when <code>HTTP_PROXY</code> or <code>HTTPS_PROXY</code> is configured. Fixes #48554. Thanks @dco5.</li>
<li>Discord/setup/startup/native commands: write resolved guild/channel allowlist selections to the selected guild and channel, persist slash-command deploy hashes across process restarts, treat abort-time Carbon reconnect-exhausted events as expected shutdown during stale-socket restarts, allow explicit ack reactions in tool-only guild channels, and warn when slash dispatch or direct plugin execution produces no visible reply. Fixes #74922 and #58986; carries forward #58216; supersedes #47788, #73949, and #62057. Thanks @samvilian, @BlueBirdBack, @Eldersonar, @Perttulands, and @jb510.</li>
<li>Discord/delivery/media: use session-backed A2A announce target lookup for multi-account <code>sessions_send</code>, keep typing indicators alive during long tool runs and auto-compaction, preserve multipart Content-Type headers for uploads, preserve attachment and sticker filenames, and keep non-ASCII channel names in session labels while preserving ASCII-slug allowlists. Fixes #42652 and #59744; refs #51626 and #44773; supersedes #73975. Thanks @irchelper, @dpalfox, @Lanfei, @Squirbie, @FunJim, @xela92, @rockcent, and @swjeong9.</li>
<li>Discord/threads/PluralKit: canonicalize proxied webhook turns to the original message id for dedupe, inject thread starter context only on the first effective thread turn, and resolve thread <code>ownerId</code>/<code>parentId</code> from Discord API-style snake_case payload fields so bot-owned autoThreads do not require unnecessary mentions. Fixes #41355; supersedes #44447 and #44449. Thanks @acgh213, @p3nchan, and @mgh3326.</li>
<li>Gateway/diagnostics: include a bounded redacted startup error message in stability bundles, so crash-loop reports identify the failing plugin or contract without exposing secrets. Refs #75797. Thanks @ymebosma.</li>
<li>Gateway/pricing: defer optional model pricing catalog refresh until after sidecars and channels reach the ready path, so slow OpenRouter or LiteLLM pricing fetches cannot block Gateway readiness. Fixes #74128; supersedes #73486. Thanks @ctbritt and @alprclbi.</li>
<li>Gateway/pricing: abort in-flight model pricing catalog fetches when Gateway shutdown stops the refresh loop, and avoid post-stop cache writes or refresh timers. Fixes #72208. Thanks @rzcq.</li>
<li>Codex/app-server: make startup retry cleanup ownership-aware so concurrent Codex lanes cannot close another lane's freshly restarted shared app-server client. Thanks @vincentkoc.</li>
<li>Google Meet/Twilio/Voice Call: report missing dial-in details during setup, explain that Twilio needs a phone dial plan for Meet URLs, start the phone leg before Meet PIN DTMF, delay intro speech until after post-connect dialing, log each stage, and accept provider call IDs for gateway speak/continue while reporting ended-call state from history.</li>
<li>Control UI/Talk: allow the OpenAI Realtime WebRTC offer endpoint through the Control UI CSP, configure browser sessions with explicit VAD/transcription input settings, and surface OpenAI realtime error/lifecycle events instead of leaving Talk stuck as live with no diagnostic. Fixes #73427.</li>
<li>Plugins: clarify config-selected duplicate plugin override diagnostics and document manifest schema updates for bundled-plugin forks. Fixes #8582. Thanks @sachah.</li>
<li>CLI backends/Claude: make live-session JSONL turn caps bounded and configurable via <code>reliability.outputLimits</code>, raising the default guard for tool-heavy Claude CLI turns while preserving memory limits. Fixes #75838. Thanks @hcordoba840.</li>
<li>Telegram/DMs/network/commands: keep incidental <code>message_thread_id</code> reply-with-quote metadata on flat DM sessions unless topic isolation is configured, raise outbound text and typing Bot API guards to 60 seconds with safe timeout overrides and typing fallback retries, and register/clear command menus in default and group-chat scopes so <code>/status</code> and plugin commands stay available in forum topics. Fixes #75975, #76013, and #74032; updates #6457. Thanks @ProjectEvolutionEVE, @iaki1206, @dae-sun, and @WouldenShyp.</li>
<li>Providers/OpenAI: resolve <code>keychain:<service>:<account></code> <code>OPENAI_API_KEY</code> refs before creating OpenAI Realtime browser sessions or voice bridges, with a bounded cached Keychain lookup. Fixes #72120. Thanks @ctbritt.</li>
<li>Discord/gateway: reconnect when the gateway socket closes while waiting for the shared IDENTIFY concurrency window, instead of silently skipping IDENTIFY and leaving the bot online but unresponsive. Fixes #74617. Thanks @zeeskdr-ai.</li>
<li>Voice Call: add <code>sessionScope: "per-call"</code> for fresh per-call agent memory while preserving the default per-phone caller history. Fixes #45280. Thanks @pondcountry.</li>
<li>Music generation: raise too-small tool timeouts to the provider-safe 10-second floor and collapse cascading abort fallback errors into a clearer root-cause summary. Thanks @shakkernerd.</li>
<li>Memory-core/dreaming: include the primary runtime workspace in multi-agent dreaming sweeps without mixing main-agent session transcripts into configured subagent workspaces. Fixes #70014. Thanks @ttomiczek.</li>
<li>Control UI: add tab/RPC timing attribution and decouple slow Overview/Cron secondary refreshes so Sessions navigation gets immediate visible feedback. Refs #64004. Thanks @WaMaSeDu.</li>
<li>Memory: retry transient SQLite index file swaps during atomic reindex on Windows, so brief <code>EBUSY</code>, <code>EPERM</code>, or <code>EACCES</code> locks do not fail memory rebuilds. Fixes #64187. Thanks @kunpeng-ai-lab.</li>
<li>Telegram/startup/models: use the existing <code>getMe</code> request guard and higher <code>timeoutSeconds</code> configs for slow Bot API paths, and make model picker confirmations say selections are session-scoped. Fixes #75783 and #75965. Thanks @tankotan and @sd1114820.</li>
<li>Control UI/slash commands: keep fallback command metadata on a browser-safe registry path, so provider thinking runtime imports cannot blank the Web UI with <code>process is not defined</code>. Fixes #75987. Thanks @novkien.</li>
<li>Heartbeat/Discord: keep async exec completion events out of the generic <code>System (untrusted)</code> prompt block and let the dedicated exec heartbeat prompt handle them, so Discord no longer receives raw exec failure tails as separate system-style messages. Fixes #66366. Thanks @Promee-ThaBossHoss.</li>
<li>Heartbeat/scheduler: make heartbeat phase scheduling active-hours-aware so the scheduler seeks forward to the first in-window phase slot instead of arming timers for quiet-hours slots and relying solely on the runtime guard. Non-UTC <code>activeHours.timezone</code> values (e.g. <code>Asia/Shanghai</code>) now correctly influence when the next heartbeat timer fires, avoiding wasted quiet-hours ticks and long dormant gaps after gateway restarts. Fixes #75487. Thanks @amknight.</li>
<li>Channels: strip plain-text MiniMax and XML tool-call scaffolding from shared user-facing reply sanitization, so messaging channels do not deliver raw model tool syntax when a provider emits it as text instead of structured tool calls. Fixes #62820. Thanks @canh0chua.</li>
<li>Infer/media: report missing image-understanding and audio-transcription provider configuration for <code>image describe</code>, <code>image describe-many</code>, and <code>audio transcribe</code> instead of blaming the input path when no provider is available. Fixes #73569 and supersedes #73593, #74288, and #74495. Thanks @bittoby, @tmimmanuel, @Linux2010, and @vyctorbrzezowski.</li>
<li>CLI/infer: reject local <code>codex/*</code> one-shot model probes before simple-completion dispatch and point operators at the Codex app-server runtime path instead of ending with an empty-output error.</li>
<li>Docs/health: clarify that session listing surfaces stored conversation rows rather than Discord/channel socket liveness, and point connectivity checks at channel status and health probes. Fixes #70420. Thanks @ashersoutherncities-art and @martingarramon.</li>
<li>WhatsApp/Cron: keep DM pairing-store approvals out of implicit cron and heartbeat recipient fallback, so scheduled automation only uses explicit targets, active configured recipients, or configured <code>allowFrom</code> entries. Fixes #62339. Thanks @kelvinisly-collab.</li>
<li>Google Meet: keep the agent-facing <code>google_meet</code> tool visible on non-macOS hosts but block local Chrome realtime actions with guidance, so Linux agents can still use transcribe, Twilio, chrome-node, and artifact flows without choosing the macOS-only BlackHole path. Refs #75950. Thanks @actual-software-inc.</li>
<li>macOS/settings: keep opening General from rewriting <code>openclaw.json</code> during Tailscale settings hydration, preserving <code>gateway</code>, <code>auth</code>, <code>meta</code>, and <code>wizard</code> until the user changes a setting. Fixes #59545. Thanks @Tengdw.</li>
<li>Discord: prioritize interaction callbacks ahead of stale background REST work without polling active REST buckets, validate oversized gateway payloads and member-intent requests before send, and forward explicit component payloads from message actions. (#75363)</li>
<li>Active Memory: use the configured recall timeout as the blocking prompt-build hook budget by default and move cold-start setup grace behind explicit <code>setupGraceTimeoutMs</code> config, so the plugin no longer silently extends 15000 ms configs to 45000 ms on the main lane. Fixes #75843. Thanks @vishutdhar.</li>
<li>Plugins/web-provider: reuse the active gateway plugin registry for runtime web provider resolution after deriving the same candidate plugin ids as the loader path, avoiding a redundant <code>loadOpenClawPlugins</code> call on every request while preserving origin and scope filters. Fixes #75513. Thanks @jochen.</li>
<li>Crestodian/CLI: exit non-zero when interactive Crestodian is invoked without a TTY, so scripts and CI no longer treat the setup error as success. Fixes #73646 and supersedes #73928 and #74059. Thanks @bittoby, @luyao618, and @Linux2010.</li>
<li>Cron: keep implicit/default isolated cron announce deliveries out of the main session awareness queue, so isolated jobs do not accumulate in the main conversation. Fixes #61426. Thanks @Lihannon.</li>
<li>Subagents: avoid duplicate parent-visible replies when a parent uses <code>sessions_send</code> on its own persistent native subagent session, while preserving announce delivery for async sends. Fixes #73550. Thanks @sylviazhang2006-design.</li>
<li>Web search/Brave: add opt-in <code>brave.http</code> diagnostics for Brave request URLs/query params, response status/timing, and cache hit/miss/write events without logging API keys or response bodies. Fixes #55196. Thanks @mecampbellsoup.</li>
<li>Web search/Brave: add <code>plugins.entries.brave.config.webSearch.baseUrl</code> for Brave-compatible proxies, including endpoint-aware cache keys for both web and LLM Context modes. Fixes #19075. Thanks @jkoprax and @vishnukool.</li>
<li>Web search/config: validate explicit <code>tools.web.search.provider</code> values against bundled and installed plugin manifests, while warning for stale third-party plugin config. Fixes #53092. Thanks @TinyTb.</li>
<li>Web search/SearXNG: retry empty non-general category searches once with the general category, so unsupported category engines do not return empty results when general search has matches. Fixes #73552. Thanks @Loukky.</li>
<li>CLI/message: skip gateway-stop hooks for read-only <code>message read</code> and bound stop-hook shutdown for other message actions, so one-shot Discord reads cannot hang behind plugin lifecycle cleanup.</li>
<li>Plugins/web-provider: cache repeated bundled web search and web fetch provider registry loads by default while preserving explicit cache opt-outs. Supersedes #75992. Thanks @DmitryPogodaev.</li>
<li>Agents/sandbox: preserve existing workspace file modes when sandbox edits atomically replace files, so 0644 files do not collapse to 0600 after Write/Edit/apply_patch. Fixes #44077. Thanks @patosullivan.</li>
<li>Control UI/WebChat: route typed <code>/new</code> through the New Chat dashboard-session creation flow instead of <code>chat.send</code>, while keeping <code>/reset</code> as the explicit current-session reset. Fixes #69599. Thanks @WolvenRA.</li>
<li>Agents/models: keep legacy CLI runtime model refs such as <code>claude-cli/*</code> in the configured allowlist after canonical runtime migration, so cron <code>payload.model</code> overrides keep working. Fixes #75753. Thanks @RyanSandoval.</li>
<li>Codex/app-server: restart the shared Codex app-server client once when it closes during startup thread resume, preserving the existing thread binding instead of retrying <code>thread/start</code> on a closed client. Thanks @vincentkoc.</li>
<li>Gateway/watch: keep colored subsystem log prefixes in the managed tmux pane even when the parent shell exports <code>NO_COLOR</code>, while preserving explicit <code>FORCE_COLOR=0</code> opt-out. Thanks @vincentkoc.</li>
<li>Agents/compaction: submit a non-empty runtime-event marker for pre-compaction memory flush turns, so strict Anthropic providers no longer reject the silent flush as an empty user message. Fixes #75305. Thanks @sableassistant3777-source.</li>
<li>Plugin SDK: re-export <code>isPrivateIpAddress</code> from <code>plugin-sdk/ssrf-runtime</code>, restoring source-checkout builds for SearXNG and Firecrawl private-network guards. Thanks @vincentkoc.</li>
<li>Discord/message actions: advertise <code>upload-file</code> and route it through Discord's send runtime with agent-scoped media reads, so agents can discover and send file attachments. Fixes #60652 and supersedes #60808, #61087, and #61100. Thanks @claw-io, @efe-arv, @joelnishanth, and @sjhddh.</li>
<li>Sessions: suppress exact inter-session control replies such as <code>NO_REPLY</code> and keep agent-to-agent announce bookkeeping out of visible transcripts. Fixes #53145. Thanks @TarahAssistant.</li>
<li>CLI/directory: report unsupported directory operations for installed channel plugins instead of prompting to reinstall the plugin when it lacks a directory adapter. Fixes #75770. Thanks @lawong888.</li>
<li>Web search/SearXNG/Firecrawl/Kimi: show the SearXNG JSON API <code>search.formats</code> prerequisite, pass through <code>img_src</code> image URLs, fail explicitly when Kimi returns ungrounded answers, keep public provider requests on strict SSRF guards, reject private/loopback/metadata/non-HTTP(S) hosted Firecrawl scrape targets, and allow explicit self-hosted private Firecrawl endpoints. Fixes #52573, #74357, and #63877; supersedes #65592, #61416, #74360, #48133, #59666, #63941, and #74013. Thanks @evanpaul14, @sghael, @wangwllu, @fede-kamel, @kn1ghtc, @jhthompson12, @jzakirov, @Mlightsnow, and @shad0wca7.</li>
<li>CLI/models: report gateway model fallback attempts in <code>infer model run --json</code> and avoid double-prefixing provider-qualified defaults such as <code>openrouter/auto</code> in <code>models status</code>. Partially fixes #69527. Thanks @alexifra.</li>
<li>Providers/OpenRouter: strip trailing assistant prefill turns from verified OpenRouter Anthropic model requests when reasoning is enabled, so Claude 4.6 routes no longer fail with Anthropic's prefill rejection through the OpenAI-compatible adapter. Fixes #75395. Thanks @sbmilburn.</li>
<li>Voice Call: add per-number inbound routing for dialed-number greetings, response agents/models/prompts, and TTS voice overrides. Fixes #56604. Thanks @healthstatus.</li>
<li>Feishu: preserve Feishu/Lark HTTP error bodies for message sends, media sends, and chat member lookups, so HTTP 400 failures include vendor code, message, log id, and troubleshooter details. Fixes #73860. Thanks @desksk.</li>
<li>Agents/transcripts: avoid reopening large Pi transcript files through the synchronous session manager for maintenance rewrites, persisted tool-result truncation, manual compaction boundary hardening, and queued compaction rotation. Thanks @mariozechner.</li>
<li>Web search/Exa/MiniMax: accept Exa <code>webSearch.baseUrl</code> overrides with endpoint-partitioned caches, include MiniMax Search in setup, and let <code>MINIMAX_API_KEY</code> participate in MiniMax Search auto-detection. Fixes #54928; supersedes #54939 and #65828. Thanks @mrpl327, @lyfuci, and @Jah-yee.</li>
<li>Plugins/ClawHub: preserve official source-linked trust through archive installs, so OpenClaw can install trusted ClawHub plugin packages that trigger the built-in dangerous-pattern scanner. Thanks @vincentkoc.</li>
<li>Plugins/ClawHub: install package runtime dependencies for archive-backed plugin installs, so ClawHub packages such as WhatsApp load declared dependencies after download. Thanks @vincentkoc.</li>
<li>Plugins/tools: cache repeated plugin tool factory results only for matching request context, reducing per-turn tool prep without leaking sandbox, session, browser, delivery, or runtime config state. Fixes #75956. Thanks @Linux2010.</li>
<li>Providers/LM Studio: allow <code>models.providers.lmstudio.params.preload: false</code> to skip OpenClaw's native model-load call so LM Studio JIT loading, idle TTL, and auto-evict can own model lifecycle. Fixes #75921. Thanks @garyd9.</li>
<li>Agents/transcripts: keep chat history, restart recovery, fork token checks, and stale-token compaction checks on bounded async transcript reads or cached async indexes instead of reparsing large session files. Thanks @mariozechner.</li>
<li>Telegram: inherit the process DNS result order for Bot API transport and downgrade recovered sticky IPv4 fallback promotions to debug logs, while keeping pinned-IP escalation warnings visible. Fixes #75904. Thanks @highfly-hi and @neeravmakwana.</li>
<li>Sessions: keep durable external conversation pointers, including group and thread-scoped chat sessions, out of age, count, and disk-budget maintenance eviction while still allowing synthetic runtime entries to age out. Fixes #58088. Thanks @drinkflav.</li>
<li>Web search/Providers MiniMax: allow <code>MINIMAX_OAUTH_TOKEN</code> to satisfy MiniMax Search credentials and derive Coding Plan usage polling from the configured MiniMax base URL, so OAuth-authorized and global setups use the right endpoint. Fixes #65768 and #65054. Thanks @kikibrian, @zhouhe-xydt, @sixone74, and @Yanhu007.</li>
<li>Control UI/WebChat: skip assistant-media transcript supplements when stale media refs resolve to no playable media, so text-only final replies are not stored a second time as gateway-injected assistant messages. Fixes #73956. Thanks @HemantSudarshan.</li>
<li>Sessions: reject <code>sessions_send</code> targets that resolve to thread-scoped chat sessions, so inter-agent coordination cannot be injected into active human-facing Slack or Discord threads. Fixes #52496. Thanks @barry-p5cc.</li>
<li>Subagents: honor <code>sessions_spawn</code> with <code>expectsCompletionMessage: false</code> by skipping parent completion handoff delivery while still running child cleanup. Fixes #75848. Thanks @alfredjbclaw.</li>
<li>Media/completions: treat media-only message-tool sends as delivered async completion output, avoiding duplicate raw <code>MEDIA:</code> fallback posts after video or music generation finishes.</li>
<li>Gateway/logging: keep deferred channel startup logs on the subsystem logger, so Slack, Discord, Telegram, and voice-call startup messages keep timestamped prefixes. Thanks @vincentkoc.</li>
<li>Codex/app-server: recover JSON-RPC frames split by raw command-output newlines and include a redacted preview when malformed app-server messages still reach the console. Thanks @vincentkoc.</li>
<li>Replies/typing: keep typing alive for queued follow-up messages that are genuinely waiting behind an active run, instead of making chat surfaces look idle while work is queued. Fixes #65685. Thanks @papag00se.</li>
<li>ACP/Discord: suppress completion announce delivery for inline thread-bound ACP session runs, so Discord thread-bound ACP replies are not delivered twice. Fixes #60780. Thanks @solavrc.</li>
<li>Discord/threads: ignore webhook-authored copies in already-bound Discord session threads even when the webhook id differs, preventing PluralKit proxy copies from creating duplicate turn pressure. Fixes #52005. Thanks @acgh213.</li>
<li>Discord/threads: return the created thread as partial success when the follow-up initial message fails, so agents do not retry thread creation and create empty duplicate threads. Fixes #48450. Thanks @dahifi.</li>
<li>Discord/components: consume every button or select in a non-reusable component message after the first authorized click, so single-use panels cannot fire sibling callbacks. Fixes #54227. Thanks @fujiwarakasei.</li>
<li>macOS/config: preserve existing <code>gateway.auth</code> and unrelated config keys during app fallback writes, so dashboard or Talk settings changes cannot strand Control UI clients by dropping persisted auth. Fixes #75631. Thanks @Fuma2013.</li>
<li>Control UI/TUI: keep reconnecting chat sends bound to the same backing session id and let TUI relaunches resume the last selected session, avoiding silent fresh sessions after refresh, reconnect, or terminal restart. Fixes #63195, #68162, and #73546. Thanks @bond260312-cmyk, @zhong18804784882, and @mtuwei.</li>
<li>Plugins/tools: let plugin manifests declare static tool availability so reply startup skips unavailable plugin tool runtimes instead of importing factories that only return <code>null</code>. Thanks @shakkernerd.</li>
<li>Discord/reactions: skip reaction listener registration when DMs and group DMs are disabled and every configured guild has <code>reactionNotifications: "off"</code>, avoiding needless reaction-event queue work. Fixes #47516. Thanks @x4v13r1120.</li>
<li>CLI sessions: preserve explicit manual-attach reuse bindings so trusted CLI sessions are not invalidated on the first turn when auth, prompt, or MCP fingerprints drift. Fixes #75849. Thanks @alfredjbclaw.</li>
<li>Telegram/streaming: keep partial preview streaming enabled for plain reply-to replies, disabling drafts only for real native quote excerpts that require Telegram quote parameters. Fixes #73505. Thanks @choury.</li>
<li>Config: log the "newer OpenClaw" version warning once per process instead of once per config snapshot read. (#75927) Thanks @romneyda.</li>
<li>Telegram/message actions: treat benign delete-message 400s as no-op warnings instead of runtime errors, so stale or already-removed messages do not create noisy delete failures. Fixes #73726. Thanks @Avicennasis.</li>
<li>Telegram: split long default markdown sends and media follow-up text into safe HTML chunks, so outbound messages over Telegram's limit no longer fail as one oversized Bot API request. Fixes #75868. Thanks @zhengsx.</li>
<li>Gateway/chat history: merge Claude CLI transcript imports for Anthropic-routed sessions that still have a Claude CLI binding, so local chat history does not hide CLI JSONL turns. Fixes #75850. Thanks @alfredjbclaw.</li>
<li>Media: trim serialized JSON suffixes after local <code>MEDIA:</code> directive file extensions, so generated-image metadata cannot pollute the parsed media path and cause false <code>ENOENT</code> delivery failures. Fixes #75182. Thanks @TnzGit and @hclsys.</li>
<li>Plugins/runtime: hot-reload Gateway plugin runtime surfaces after plugin enable/disable changes while keeping source-changing plugin install, update, and uninstall operations restart-backed so loaded module code is not reused. Fixes #72097.</li>
<li>Cron: make scheduler reload schedule comparison tolerate malformed persisted jobs, so one bad cron entry no longer aborts the whole tick. Fixes #75886. Thanks @samfox-ai.</li>
<li>Doctor/channels: warn after migrations when default Telegram or Discord accounts have no configured token and their env fallback (<code>TELEGRAM_BOT_TOKEN</code> or <code>DISCORD_BOT_TOKEN</code>) is unavailable, with secret-safe migration docs for checking state-dir <code>.env</code>. Fixes #74298. Thanks @lolaopenclaw.</li>
<li>Gateway/diagnostics: keep idle liveness samples in telemetry instead of visible warning logs unless diagnostic work is active, waiting, or queued. Thanks @vincentkoc.</li>
<li>Channels/cron: reject provider-prefixed targets for the wrong channel and let prefixed announce targets such as <code>telegram:123</code> select their channel when delivery falls back to <code>last</code>, so Telegram IDs cannot be coerced into WhatsApp phone numbers. Fixes #56839. Thanks @bencoremans.</li>
<li>Control UI/chat: keep live replies visible when a raw session alias such as <code>main</code> sends the chat turn but Gateway emits events under the canonical session key for the same run. Fixes #73716. Thanks @teebes.</li>
<li>CLI/models: reject <code>--agent</code> on <code>openclaw models set</code> and <code>set-image</code> instead of silently writing agent-scoped requests to global model defaults. Fixes #68391. Thanks @derrickabellard.</li>
<li>CLI: stop treating the legacy singular <code>openclaw tool ...</code> token as a plugin id under restrictive <code>plugins.allow</code>, so it falls through as a normal unknown/reserved command instead of suggesting a stale allowlist entry. Fixes #64732. Thanks @efe-arv, @SweetSophia, and @hashtag1974.</li>
<li>Media: write inbound media buffers through same-directory temp files before rename, so failed disk writes do not leave zero-byte artifacts for later voice transcription. Fixes #55966. Thanks @OpenCodeEngineer.</li>
<li>TTS/Telegram: keep trusted local audio generated by the TTS tool queued for voice-note delivery even when the run-level built-in tool list omits the raw <code>tts</code> name. Fixes #74752. Thanks @Loveworld3033 and @andyliu.</li>
<li>TTS: require explicit user or config audio intent for the agent speech tool so dashboard chats stay text unless audio is requested. Fixes #69777. Thanks @alexandre-leng.</li>
<li>Plugins/config: keep bundled source-checkout plugins from being runtime-gated by install-only <code>minHostVersion</code> metadata, accept prerelease host floors, trim plugin-service startup failures to one log line, and avoid broad channel-runtime loading during base config parsing. Thanks @vincentkoc.</li>
<li>Heartbeat: strip legacy <code>[TOOL_CALL]...[/TOOL_CALL]</code> and <code>[TOOL_RESULT]...[/TOOL_RESULT]</code> pseudo-call blocks from heartbeat replies before channel delivery. Fixes #54138. Thanks @Deniable9570.</li>
<li>macOS/Voice Wake: send wake-word and Push-to-Talk transcripts through the selected macOS session target instead of always falling back to main WebChat. Fixes #51040. Thanks @carl-jeffrolc.</li>
<li>Providers/xAI: give Grok <code>web_search</code> a 60s default timeout, harden malformed xAI Responses parsing, and return structured timeout errors instead of aborting the tool call. Fixes #58063 and #58733. Thanks @dnishimura, @marvcasasola-svg, and @Nanako0129.</li>
<li>Providers/configure: preserve the existing default model when adding or reauthing a provider whose plugin returns a default-model config patch. Fixes #50268. Thanks @rixcorp-oc.</li>
<li>Slack/DMs/routing: honor <code>dmHistoryLimit</code> for fresh 1:1 DMs, keep top-level DMs on stable DM sessions even when <code>replyToMode</code> targets thread replies, send text/block-only proactive DMs directly with <code>chat.postMessage(channel=<user id>)</code>, match Slack target route syntax such as <code>channel:C...</code>, <code>user:U...</code>, or <code><@U...></code>, and match public-channel allowlists against bare runtime channel IDs. Fixes #64427, #58832, #62042, #41608, and #41264; supersedes #56530. Thanks @brantley-creator, @daye-jjeong, @MarkMolina, @Winnsolutionsadmin, @babutree, and @Realworld404.</li>
<li>Slack/delivery/capabilities: preserve missing-scope details in outbound errors, read granted scopes from <code>auth.test</code> metadata before legacy APIs, retry Slack writes only for wrapped DNS request failures such as <code>EAI_AGAIN</code>, and prefer the account bound to the outbound target peer in multi-workspace sends. Fixes #62391, #44625, and #68789; supersedes #66807. Thanks @alexey-pelykh, @Qquanwei, @martingarramon, @sonnyb9, and @rijhsinghani.</li>
<li>Slack/message actions/tools: send media before follow-up Block Kit messages for file sends, forward agent-scoped media roots through the bundled upload-file path, resolve <code><!subteam^...></code> user-group mentions before waking mention-gated channels, and let <code>read</code> fetch an exact Slack message timestamp or thread reply. Fixes #51458, #64625, #73827, and #53943. Thanks @HirokiKobayashi-R, @benpchandler, @CG-Intelligence-Agent-Jack, and @zomars.</li>
<li>PDF/Gemini: send native PDF analysis API keys in the <code>x-goog-api-key</code> header instead of the request URL, keeping secrets out of proxy and access logs. Supersedes #60600. Thanks @garagon.</li>
<li>Web search/Gemini/DuckDuckGo/Brave/fetch: route abort signals into Gemini provider fetches, late-bind managed agent <code>web_search</code> calls to the current runtime config snapshot, reuse Google provider API key/base URL as lower-priority Gemini search fallbacks, pass Gemini freshness/date filters through grounding, include DuckDuckGo in setup, honor Gemini/Grok/x_search <code>baseUrl</code> overrides, point Brave metadata at canonical docs, support Brave LLM Context freshness/date ranges, resolve external <code>webFetchProviders</code> for non-sandboxed fetches, and point missing-key errors to <code>web_fetch</code> or browser where appropriate. Fixes #72995, #75420, #66498, #65862, #65870, and #74915; supersedes #57496, #65940, #61972, #65892, and #51005. Thanks @RoseKongPS, @richardmqq, @Aoiujz, @ismael-81, @Jah-yee, @Lanfei, @Magicray1217, @remusao, @ultrahighsuper, @mingmingtsao, and @zhaoyang97.</li>
<li>Slack/directory: make <code>openclaw directory peers/groups list --channel slack</code> prefer token-backed live readers and return the connected Slack account from <code>directory self</code>, so valid Slack tokens no longer produce empty directory CLI results. Fixes #50776. Thanks @pjaillon.</li>
<li>Slack: keep assistant typing status, temporary typing reactions, and status reactions active for group/channel turns that use message-tool-only visible replies, while still suppressing automatic source replies. Fixes #75877. Thanks @teosborne.</li>
<li>Slack: recover full inbound DM text from top-level rich-text blocks when Slack sends a shortened message preview, so long direct messages still reach the agent intact. Fixes #55358. Thanks @tonyjwinter.</li>
<li>Replies: strip legacy <code>[TOOL_CALL]{tool => ..., args => ...}[/TOOL_CALL]</code> pseudo-call text from user-facing replies and flag it in tool-call diagnostics instead of showing raw tool syntax in channels. Fixes #63610. Thanks @canh0chua.</li>
<li>WhatsApp: close long-lived web sockets through Baileys <code>end(error)</code> before falling back to raw websocket close, so listener teardown runs Baileys cleanup instead of leaving zombie sockets. Fixes #52442. Thanks @essendigitalgroup-cyber.</li>
<li>Twitch/plugins: emit a flat JSON Schema for Twitch channel config so single-account and multi-account configs validate before runtime load, and add source-checkout diagnostics for missing pnpm workspace dependencies. Thanks @vincentkoc.</li>
<li>Gateway/sessions: move hot transcript reads and mirror appends onto async bounded IO with serialized parent-linked writes, keeping large session histories from stalling Gateway requests and channel replies. Fixes #75656. Thanks @DerFlash.</li>
<li>macOS/Talk Mode: downmix multi-channel microphone buffers before handing them to Apple Speech across Push-to-Talk, Talk Mode, Voice Wake, and the wake-word tester, so pro audio interfaces no longer produce empty transcripts. Fixes #42533. Thanks @jbuecker.</li>
<li>macOS/Talk Mode: subscribe native WebChat to active-session transcript updates and render external spoken user turns in the chat thread instead of only showing assistant replies. Fixes #75155. Thanks @SledderBling.</li>
<li>macOS/Voice Wake: accept trigger-only phrases in the built-in Voice Wake test, matching the settings UI and runtime trigger-only path instead of requiring extra command text after the wake word. Fixes #64986. Thanks @zoiks65.</li>
<li>Cron/TTS: run cron announce payloads through the normal TTS directive transform before outbound delivery, so scheduled <code>[[tts]]</code> replies generate voice payloads instead of leaking raw tags. Fixes #52125. Thanks @kenchen3000.</li>
<li>WhatsApp: save downloadable quoted image media from reply context as inbound media, so agents can inspect an image that a user replied to instead of only seeing <code><media:image></code>. Fixes #59174. Thanks @gaffner.</li>
<li>Sessions/store: stop persisting the runtime-only <code>skillsSnapshot.resolvedSkills</code> array inside each session entry, so <code>sessions.json</code> no longer carries a copy of every parsed <code>SKILL.md</code> body for every active session; <code>ensureSkillSnapshot</code> rehydrates the array from disk on cold resume so the embedded runner, the Claude CLI skills plugin, and the Claude live-session fingerprint all see populated skills, and legacy stores self-heal on the next save. Refs #11950, #6650, #15000. Thanks @amoghasgekar.</li>
<li>Doctor/WhatsApp: warn when Linux crontabs still run the legacy <code>ensure-whatsapp.sh</code> health check, which can misreport <code>Gateway inactive</code> when cron lacks the systemd user-bus environment. Fixes #60204. Thanks @mySebbe.</li>
<li>Slack/setup: print the generated app manifest as plain JSON instead of embedding it inside the framed setup note, so it can be copied into Slack without deleting border characters. Fixes #65751. Thanks @theDanielJLewis.</li>
<li>Channels/WhatsApp: route CLI logout through the live Gateway and stop runtime-backed listeners before channel removal, so removing a WhatsApp account does not leave the old socket replying until restart. Fixes #67746. Thanks @123Mismail.</li>
<li>Voice Call/Twilio: honor TTS directive text and provider voice/model overrides during telephony synthesis, so <code>[[tts:...]]</code> tags are not spoken literally and voiceId overrides reach OpenAI/ElevenLabs calls. Fixes #58114. Thanks @legonhilltech-jpg.</li>
<li>Agents/session-locks: reclaim untracked current-process session locks with matching starttime during acquisition and startup cleanup, so Gateway restarts recover from self-owned orphan <code>.jsonl.lock</code> files. Fixes #75805; refs #49603. Thanks @cdznho.</li>
<li>Agents/subagents: initialize built-in context engines before native <code>sessions_spawn</code> resolves spawn preparation, so cliBackend-only cold starts no longer fail with an unregistered <code>legacy</code> context engine. Fixes #73095. (#73904) Thanks @brokemac79.</li>
<li>Plugins/Bonjour: ship the ciao runtime dependency with packaged OpenClaw so fresh OCM envs can start default mDNS discovery without a missing-module failure. Thanks @shakkernerd.</li>
<li>Agents/tools: scope reply plugin-tool discovery to manifest-declared tool owners and already-active matching tool entries, avoiding broad plugin runtime loading for narrow or core-only tool allowlists. Thanks @shakkernerd.</li>
<li>Agents/replies: defer implicit image model discovery and keep OAuth auth-store adoption on persisted profiles during reply startup, cutting OCM MarCodex warm prep to sub-second in live checks. Thanks @shakkernerd.</li>
<li>Plugins/tools: enforce <code>contracts.tools</code> as the manifest ownership contract for plugin tool registration, rejecting undeclared runtime tool names and adding bundled plugin drift coverage. Thanks @shakkernerd.</li>
<li>Agents/Codex: stop prompting message-tool-only source turns to finish with <code>NO_REPLY</code>, so quiet turns are represented by not calling the visible message tool instead of conflicting final-text instructions. Thanks @pashpashpash.</li>
<li>Gateway/config: report failed backup restores as failed in logs and config observe audit records instead of marking them valid. (#70515) Thanks @davidangularme.</li>
<li>Compaction: use the active session model fallback chain for implicit summarization failures without persisting fallback model selection, so Azure content-filter 400s can recover. Fixes #64960. (#74470) Thanks @jalehman and @OpenCodeEngineer.</li>
<li>Gateway/config: allow <code>gateway config.patch</code> to update documented subagent thinking defaults. Fixes #75764. (#75802) Thanks @kAIborg24.</li>
<li>Plugins/CLI: keep git plugin install paths credential-free, preserve existing git checkouts until replacement succeeds, honor duplicate npm install mode, and remove managed git repos on uninstall. Thanks @vincentkoc.</li>
<li>Plugins/CLI: redact authenticated git URLs from git install command failure details, so failed clone or checkout output cannot leak credentials during plugin installs. Thanks @vincentkoc.</li>
<li>Channels/status reactions: remove stale non-terminal lifecycle reactions when a run reaches done or error, so Discord does not leave a permanent thinking emoji after completion. Fixes #75458. Thanks @davelutztx.</li>
<li>Discord/doctor: migrate unsupported per-channel <code>agentId</code> entries under guild channel config into top-level <code>bindings[]</code> routes, so <code>openclaw doctor --fix</code> preserves the intended agent route instead of stripping it as an unknown key. Fixes #62455. Thanks @lobster-biscuit.</li>
<li>Discord/DMs: set inbound direct-message <code>ctx.To</code> to the semantic <code>user:<id></code> target while keeping delivery routed through the DM channel, so mirror and recovery paths do not treat DMs as channel conversations. Fixes #68126. Thanks @illuminate0623.</li>
<li>Discord/DMs: keep no-guild inbound messages on direct-message routing when Discord channel lookup is temporarily unavailable, preventing degraded DMs from forking into channel sessions. Fixes #59817. Thanks @DooPeePey.</li>
<li>Discord: retry outbound API calls on HTTP 5xx, request-timeout, and transient transport failures instead of only Discord rate limits, reducing dropped cron and agent replies during short Discord or network outages. Fixes #52396. Thanks @sunshineo.</li>
<li>Discord: include Components v2 Text Display content from referenced replies and forwarded snapshots, so component-only messages still appear in reply context. Fixes #56228. Thanks @HollandDrive.</li>
<li>Discord: add configurable gateway READY timeouts for startup and runtime reconnects, so staggered multi-account setups can avoid false restart loops. Fixes #72273. Thanks @sergionsantos.</li>
<li>Discord: preserve native slash-command description localizations through command reconcile, so localized Discord descriptions no longer get overwritten by English defaults. Fixes #56580. Thanks @mhseo93.</li>
<li>Discord: add configured outbound mention aliases so known <code>@Name</code> references can be rewritten to real Discord user mentions instead of relying only on the transient directory cache. Fixes #67587. Thanks @McoreD.</li>
<li>Discord: avoid startup REST amplification by skipping native command deploy retries after Discord rate limits and deriving the bot id from parseable bot tokens instead of requiring a <code>/users/@me</code> lookup. Fixes #75341. Thanks @PrinceOfEgypt.</li>
<li>Plugins/hooks: derive hook <code>ctx.channelId</code> from the conversation target instead of the provider name, so Discord and other channel plugins can keep per-channel state isolated. Fixes #59881. Thanks @bradfreels.</li>
<li>Gateway/config: log config health-state write failures instead of silently hiding config observe-recovery write errors. Thanks @sallyom.</li>
<li>Diagnostics: reset stuck-session timers on reply, tool, status, block, and ACP progress events, and back off repeated <code>session.stuck</code> diagnostics while a session remains unchanged. Supersedes #72010. Thanks @rubencu.</li>
<li>Gateway/agents: avoid rebuilding core tools for plugin-only allowlists and keep the full plugin registry cache warm across scoped plugin loads, reducing per-turn latency spikes. Fixes #75882, #75907, #75906, #75887, and #75851. (#75922) Thanks @obviyus.</li>
<li>Agents/failover: classify bare <code>status: internal server error</code> provider messages as retryable server errors so model fallback can rotate instead of stopping. (#73844) Thanks @thesomewhatyou.</li>
<li>Gateway/startup: return the shared retryable startup-sidecars error for startup-gated control-plane RPCs such as sessions.create, sessions.send, sessions.abort, agent.wait, and tools.effective, so clients can retry early sidecar races. (#76012) Thanks @scoootscooob.</li>
<li>Providers/Google: fix Gemini 2.5 Flash-Lite <code>reasoning: "minimal"</code> rejections by raising its thinking-budget floor to 512 while preserving the existing Gemini 2.5 Pro and Flash minimal presets. (#70629) Thanks @ericberic.</li>
<li>Agents/status: resolve <code>session_status(sessionKey="current")</code> for sparse channel-plugin sessions after literal current lookups miss, so Scope, Slack, Discord, and other plugin-driven agents avoid retrying through <code>Unknown sessionKey: current</code>. Fixes #74141. (#72306) Thanks @bittoby.</li>
<li>Cron: retry recurring wake-now main-session jobs through temporary heartbeat busy skips before recording success, so queued cron events no longer appear as ok ghost runs while the main lane is still busy. Fixes #75964. (#76083) Thanks @kshetrajna12 and @xuruiray.</li>
<li>Providers/Google: keep Gemini thinking-signature-only stream chunks active during reasoning, so Gemini 3.1 Pro Preview replies no longer hit idle timeouts before visible text. Fixes #76071. (#76080) Thanks @marcoschierhorn and @zhangguiping-xydt.</li>
<li>CLI/skills: show per-agent model and command visibility in <code>openclaw skills check --agent</code>, and let doctor report or disable unavailable skills allowed for the default agent. (#75983) Thanks @mbelinky.</li>
<li>Agents/runtime/tools: keep reply startup on Gateway metadata, manifest catalog rows, auth-store state, and plugin loader cache-key compatibility checks so scoped runtime registries, model allowlists, thinking metadata, media/PDF/generation tools, Comfy workflows, OpenAI Codex OAuth image generation, and image/video/music tool registration avoid broad provider/runtime loads while preserving explicit config and auth-backed providers. Thanks @shakkernerd.</li>
<li>Discord: document canonical mention formatting in agent prompt hints and channel docs so outbound replies use <code><@USER_ID></code>, <code><#CHANNEL_ID></code>, and <code><@&ROLE_ID></code> instead of legacy nickname mentions. (#75173)</li>
<li>Heartbeat scheduler: gate exec-event/notification/spawn/retry wakes through a centralized cooldown so backgrounded <code>process.start</code> exit notifications can no longer self-feed runaway heartbeat runs (configured <code>every: "30m"</code> was firing every ~10s in production, pegging the gateway event loop with <code>eventLoopDelayMaxMs >6s</code> spikes that stalled control-UI asset serving and TUI handshakes). Documented wake-now paths (<code>manual</code>, <code>wake</code>, task completion, blocked-task follow-up, <code>/hooks/wake mode=now</code>, and cron <code>--wake now</code>) remain immediate; retryable busy skips no longer poison the cooldown for the next retry; per-agent flood guard caps any unexpected feedback loop at 5 runs/60s. (#64016, refs #17797 and #75436) Thanks @hexsprite.</li>
<li>fix: block workspace CLOUDSDK_PYTHON override and always set trusted interpreter for gcloud. (#74492) Thanks @pgondhi987.</li>
<li>Providers/Z.AI: move the bundled GLM catalog and auth env metadata into the plugin manifest, so <code>models list --all --provider zai</code> shows the full known catalog without duplicated runtime seed data. Thanks @shakkernerd.</li>
<li>Providers/Qianfan and Providers/Stepfun: declare setup auth metadata (<code>api-key</code> method, <code>QIANFAN_API_KEY</code>, <code>STEPFUN_API_KEY</code>) in the plugin manifest so onboarding and <code>models setup</code> surface the expected env var without falling back to legacy <code>providerAuthEnvVars</code> runtime seed data. Thanks @shakkernerd.</li>
<li>fix(infra): block ambient Homebrew env vars from brew resolution. (#74463) Thanks @pgondhi987.</li>
<li>Onboarding/configure: avoid staging every default plugin runtime dependency after config writes, so skipped setup flows only prepare config-selected plugin deps instead of pulling broad feature-plugin packages. Thanks @vincentkoc.</li>
<li>Thinking/providers: resolve bundled provider thinking profiles through lightweight provider policy artifacts when startup-lazy providers are not active, so OpenAI Codex GPT-5.x keeps xhigh available in Gateway session validation. Fixes #74796. Thanks @maxschachere.</li>
<li>Security/Windows: ignore workspace <code>.env</code> system-path variables and resolve stale-process <code>taskkill.exe</code> from the validated Windows install root, preventing repository-local env files from redirecting cleanup helpers. Thanks @pgondhi987.</li>
<li>CLI/plugins: refresh persisted plugin registry policy in place for <code>plugins enable</code> and <code>plugins disable</code>, so routine toggles no longer rebuild and hash every plugin source when the target is already indexed. Thanks @vincentkoc.</li>
<li>Windows/install: run npm from a writable installer temp directory and pin the Bedrock runtime dependency below a Windows ARM Node 24 npm resolver failure, so global OpenClaw installs no longer fail before onboarding. Thanks @mariozechner.</li>
<li>CLI/plugins: scope install and enable slot selection to the selected plugin manifest/runtime fallback, so plugin installs no longer load every plugin runtime or broad status snapshot just to update memory/context slots. Thanks @vincentkoc.</li>
<li>Plugins/TTS: keep bundled speech-provider discovery available on cold package Gateway paths and add bundled plugin matrix runtime probes for health, readiness, RPC, TTS discovery, and post-ready runtime-deps watchdog coverage. Refs #75283. Thanks @vincentkoc.</li>
<li>Google Meet/Twilio: show delegated voice call ID, DTMF, and intro-greeting state in <code>googlemeet doctor</code>, and avoid claiming DTMF was sent when no Meet PIN sequence was configured. Refs #72478. Thanks @DougButdorf.</li>
<li>Plugins/tools: prefer built bundled plugin code during tool discovery and skip channel runtime hydration while preserving companion provider registrations, reducing per-run plugin-tool prep cost without dropping executable plugin tools. Fixes #75290. Thanks @thanos-openclaw.</li>
<li>Plugins/loader: scope plugin-tool registry reuse to the enabled plugin plan and stored Gateway method keys, so embedded runner tool lookup can reuse compatible startup registries without hiding enabled non-startup plugin tools. Fixes #75520. Thanks @whtoo.</li>
<li>Voice Call/Twilio: send notify-mode initial TwiML directly in the outbound create-call request while keeping conversation and pre-connect DTMF calls webhook-driven, so one-shot notify calls do not depend on a first-answer webhook fetch. Supersedes #72758. Thanks @tyshepps.</li>
<li>Discord/Slack: defer status-reaction cleanup until run finalization so queued, thinking, tool, and terminal reactions no longer flicker during normal progress updates. (#75582)</li>
<li>Discord/voice: leave voice off for text-only configs unless explicitly configured, rerun configured voice auto-join after gateway RESUMED events, ignore already-destroyed stale voice connections during reconnect cleanup, lengthen the default voice join Ready wait with configurable timeouts, merge configured media-understanding providers such as Deepgram into partial active registries, apply per-channel <code>systemPrompt</code> overrides to voice transcript turns, and run voice-channel turns under a voice-output policy that hides the agent <code>tts</code> tool. Fixes #73753, #40665, #63098, #65687, #47095, and #61536; refs #74044, #39825, and #65039. Thanks @sanchezm86, @SecureCloudProjO, @liz709, @darealgege, @kzicherman, @ayochim, @OneMintJulep, @qearlyao, and @aounakram.</li>
<li>Plugins/CLI: reuse the cold manifest registry while building plugin status and inspect reports, so large configured plugin sets no longer rediscover the bundled/plugin registry once per inspect row. Thanks @vincentkoc.</li>
<li>Gateway/health: refresh cached health RPC snapshots when channel runtime state diverges, so Discord and other channel status reads no longer report stale running or connected values until the cache TTL expires. (#75423)</li>
<li>Gateway/sessions: keep session-store reads from running stale prune and entry-count cap maintenance during startup, so oversized stores no longer block chat history readiness after updates while writes and <code>sessions cleanup --enforce</code> still preserve the cleanup safeguards. Fixes #70050. Thanks @tangda18.</li>
<li>Security/audit: keep plain <code>security audit</code> on the cold config/filesystem path and reserve plugin runtime security collectors for <code>--deep</code>, so large plugin installs cannot execute every plugin runtime during routine audits. Thanks @vincentkoc.</li>
<li>WhatsApp: stage <code>qrcode</code> through root mirrored runtime dependencies so packaged QR pairing can render from staged plugin-runtime-deps installs. Fixes #75394. Thanks @FelipeX2001.</li>
<li>Interactive channel payloads: send Discord component-only interaction replies, Slack block-only slash replies, Telegram button/select fallback labels, and LINE quick-reply fallback option text instead of accepting empty renderable payloads. Thanks @vincentkoc.</li>
<li>Auto-reply/docking: require <code>/dock-*</code> route switches to start from direct chats, so group or channel participants cannot reroute a shared session's future replies into a linked DM. Thanks @vincentkoc.</li>
<li>Discord: keep text-DM main-session route updates pinned to the configured DM owner, matching component interactions so another direct-message sender cannot redirect future main-session replies. Thanks @vincentkoc.</li>
<li>Mattermost/Matrix: keep direct-message main-session route updates pinned to the configured DM owner so paired or temporarily allowed senders cannot redirect future shared-session replies. Thanks @vincentkoc.</li>
<li>Discord: keep SecretRef-backed bot tokens discoverable for message actions without resolving the token during schema generation, and resolve scoped channel SecretRefs before outbound agent message sends even when the tool is built from a config snapshot. Fixes #75324. Thanks @slideshow-dingo and @Conan-Scott.</li>
<li>Updates: run package post-install doctor repair with the managed Gateway service profile and state paths when a daemon is installed, so shell/profile mismatches no longer repair the caller state while the restarted Gateway keeps stale config. Thanks @vincentkoc.</li>
<li>Models/DeepInfra: declare DeepInfra manifest catalog discovery and derive its runtime fallback catalog from the manifest, restoring provider-filtered <code>models list --all --provider deepinfra</code> rows without duplicated static model data. Thanks @shakkernerd.</li>
<li>CLI/update: verify managed gateway restarts against the installed service port instead of the caller shell port, so package updates do not report a healthy daemon as failed when profiles use different gateway ports. Thanks @vincentkoc.</li>
<li>Gateway/agent: reject strict <code>openclaw agent --deliver</code> requests with missing delivery targets before starting the agent run, so users do not wait for a completed turn that cannot send anywhere. Thanks @vincentkoc.</li>
<li>Setup/import: honor non-interactive <code>--import-from</code> onboarding flags by running the migration import path instead of silently completing normal setup without importing anything. Thanks @vincentkoc.</li>
<li>Doctor/plugins: keep plain <code>doctor --non-interactive</code> from installing bundled plugin runtime dependencies, so headless health checks report missing deps while <code>doctor --fix</code> remains the explicit repair path. Thanks @vincentkoc.</li>
<li>Doctor/gateway: require an interactive confirmation before installing or rewriting the Gateway service, so <code>doctor --fix --non-interactive</code> can repair plugin/config drift without replacing the operator's launchd/systemd service from a temporary environment. Thanks @vincentkoc.</li>
<li>Plugins/runtime-deps: include packaged OpenClaw identity in bundled plugin loader cache keys, so same-path package upgrades stop reusing stale versioned runtime-deps mirrors. Fixes #75045. Thanks @sahilsatralkar.</li>
<li>Plugin SDK: restore reply-prefix and reply-pipeline helpers on the deprecated root/compat SDK surface so external plugins still using <code>openclaw/plugin-sdk</code> do not fail message dispatch after update. Fixes #75171. Thanks @zhangxiliang.</li>
<li>Plugins/runtime-deps: prune inactive same-package versioned runtime-deps roots after bundled dependency repair, so upgrades do not leave old <code>openclaw-<version>-<hash></code> package caches behind after doctor runs. Thanks @vincentkoc.</li>
<li>Plugins/runtime-deps: prune legacy version-scoped plugin runtime-deps roots during bundled dependency repair and cover the path in Package Acceptance's upgrade-survivor matrix, so upgrades from 2026.4.x no longer leave stale per-plugin runtime trees after doctor runs. Thanks @vincentkoc.</li>
<li>Plugins/runtime-deps: keep Gateway startup plugin imports and runtime plugin fallback loads verify-only after startup/config repair planning, so packaged installs no longer spawn package-manager repair from hot paths after readiness. Refs #75283 and #75069. Thanks @brokemac79 and @xiaohuaxi.</li>
<li>Plugins/runtime-deps: treat package.json runtime-deps manifests as supersets when generated materialization metadata is absent, so bundled plugin activation stops restaging already-installed dependency subsets on every activation. Fixes #75429. (#75431) Thanks @loyur.</li>
<li>iMessage: add stdin write callback and error listener to IMessageRpcClient so async EPIPE from a closed child process rejects the pending request instead of crashing the gateway with uncaughtException. Fixes #75438.</li>
<li>MCP/stdio: settle MCP stdio transport send() from the write callback instead of resolving immediately on buffer acceptance, so async write errors reject the promise instead of being lost. Refs #75438.</li>
<li>Process/exec: add stdin error listener in runCommandWithTimeout so EPIPE from a prematurely-exited child is swallowed instead of escaping to uncaughtException. Refs #75438.</li>
<li>Voice Call/realtime: add default-off fast memory/session context for <code>openclaw_agent_consult</code>, giving live calls a bounded answer-or-miss path before the full agent consult. Fixes #71849. Thanks @amzzzzzzz.</li>
<li>Google Meet: interrupt Realtime provider output when local barge-in clears playback, so command-pair audio stops model speech instead of only restarting Chrome playback. Fixes #73850. (#73834) Thanks @shhtheonlyperson.</li>
<li>Gateway/config: cap oversized plugin-owned schemas in the full <code>config.schema</code> response so large installed plugin sets cannot balloon Gateway RSS or crash schema clients. Thanks @vincentkoc.</li>
<li>Plugins/update: skip ClawHub and marketplace plugin updates when the bundled version is newer than the recorded installed version, so <code>openclaw update</code> no longer overwrites working bundled plugins with older external packages. Fixes #75447. Thanks @amknight.</li>
<li>Gateway/sessions: use bounded tail reads for sessions-list transcript usage fallbacks and cap bulk title/last-message hydration, keeping large session stores responsive when rows request derived previews. Thanks @vincentkoc.</li>
<li>Gateway/sessions: yield during bulk transcript title/preview hydration and copy compaction checkpoints asynchronously, keeping the Gateway event loop responsive for large session stores and large transcripts. Refs #75330 and #75414. Thanks @amknight.</li>
<li>Gateway/sessions: stream bounded transcript reads for session detail, history, artifacts, compaction, and send/subscribe sequence paths so small Gateway requests no longer materialize large transcripts or OOM on oversized session logs. Thanks @vincentkoc.</li>
<li>Gateway/chat: bound chat-history transcript reads to the requested display window so large session logs no longer OOM the Gateway when clients ask for a small history page. Thanks @vincentkoc.</li>
<li>BlueBubbles: detect audio attachments by Apple UTIs (<code>public.audio</code>, <code>public.mpeg-4-audio</code>, <code>com.apple.m4a-audio</code>, <code>com.apple.coreaudio-format</code>) in addition to <code>audio/*</code> MIME, so iMessage voice notes whose webhook payload only carries the UTI are now classified as audio in the inbound <code><media:audio></code> placeholder instead of falling through to the generic <code><media:attachment></code> tag. Thanks @omarshahine.</li>
<li>Voice Call/Twilio: honor stored pre-connect TwiML before realtime webhook shortcuts and reject DTMF sequences outside conversation mode, so Meet PIN entry cannot be skipped or silently dropped. Thanks @donkeykong91 and @PfanP.</li>
<li>Docs/sandboxing: clarify that sandbox setup scripts (<code>sandbox-setup.sh</code>, <code>sandbox-common-setup.sh</code>, <code>sandbox-browser-setup.sh</code>) are only available from a source checkout, and add inline <code>docker build</code> commands for npm-installed users so sandbox image setup works without cloning the repo. Fixes #75485. Thanks @amknight.</li>
<li>Google Meet/Voice Call: play Twilio Meet DTMF before opening the realtime media stream and carry the intro as the initial Voice Call message, so the greeting is generated after Meet admits the phone participant instead of racing a live-call TwiML update. Thanks @donkeykong91 and @PfanP.</li>
<li>Google Meet/Voice Call: make Twilio setup preflight honor explicit <code>--transport twilio</code> and fail local/private Voice Call webhook URLs, including IPv6 loopback and unique-local forms, before joins. Thanks @donkeykong91 and @PfanP.</li>
<li>Voice Call/Twilio: retry transient 21220 live-call TwiML updates and catch answered-path initial-greeting failures, so a fast answered callback no longer crashes the Gateway or drops the Twilio greeting/listen transition. (#74606) Thanks @Sivan22.</li>
<li>CLI/startup: preserve <code>OPENCLAW_HIDE_BANNER</code> banner suppression for route-first startup callers that rely on the default process environment while keeping read-only status/channel paths from repairing bundled plugin runtime dependencies. Refs #75183.</li>
<li>Voice Call/Twilio: register accepted media streams immediately but wait for realtime transcription readiness before speaking the initial greeting, so reconnect grace handling stays live while OpenAI STT startup is no longer starved by TTS. Fixes #75197. (#75257) Thanks @donkeykong91 and @PfanP.</li>
<li>Voice Call CLI: run gateway-delegated <code>voicecall continue</code> through operation-id polling and protocol-shaped errors, so long conversational turns keep their transcript result without blocking a single Gateway RPC. (#75459) Thanks @serrurco and @DougButdorf.</li>
<li>Voice Call CLI: delegate operational <code>voicecall</code> commands to the running Gateway runtime and skip webhook startup during CLI-only plugin loading, preventing webhook port conflicts and <code>setup --json</code> hangs. Fixes #72345. Thanks @serrurco and @DougButdorf.</li>
<li>Agents/pi-embedded-runner: extract the <code>abortable</code> provider-call wrapper from <code>runEmbeddedAttempt</code> to module scope so its promise handlers no longer close over the run lexical context, releasing transcripts, tool buffers, and subscription callbacks when a provider call hangs past abort. (#74182) Thanks @cjboy007.</li>
<li>Docker: restore <code>python3</code> in the gateway runtime image after the slim-runtime switch. Fixes #75041.</li>
<li>Agents/session-repair: fix resumed sessions failing with repeated 400 errors on Anthropic and strict OpenAI-compatible providers (Qwen, mlx-vlm) after an interrupted conversation or blank user input. Fixes #75271 and #75313. Thanks @amknight.</li>
<li>CLI/Voice Call: scope <code>voicecall</code> command activation to the Voice Call plugin so setup and smoke checks no longer broad-load unrelated plugin runtimes or hang after printing JSON. Thanks @vincentkoc.</li>
<li>Doctor/plugins: warn when restrictive <code>plugins.allow</code> is paired with wildcard or plugin-owned tool allowlists, making the exclusive plugin allowlist behavior visible before users hit empty callable-tool runs. Refs #58009 and #64982. Thanks @KR-Python and @BKF-Gitty.</li>
<li>Google Meet/Voice Call: keep Twilio Meet joins in conversation mode and reuse the realtime intro prompt when no voice-call-specific intro is configured, so answered phone bridge calls speak instead of joining silently. Refs #72478. Thanks @DougButdorf.</li>
<li>Auto-reply/group chats: keep the <code>message</code> tool available for message-tool-only visible replies and apply group-scoped tool policy before deciding fallback delivery, so Discord/Slack-style rooms reply visibly in the correct channel after upgrades. Fixes #74842; refs #75207. Thanks @davelutztx and @aa-on-ai.</li>
<li>Agents/commitments: keep inferred follow-ups internal when heartbeat target is none, strip raw source text from stored commitments, disable tools during due-commitment heartbeat turns, bound hidden extraction queue growth, expire stale commitments, and add QA/Docker safety coverage. Thanks @vignesh07.</li>
<li>Telegram/agents: keep typing indicators and optional generation tools off the reply critical path, so fresh Telegram replies no longer stall while provider catalogs and media models load. (#75360) Thanks @obviyus.</li>
<li>Agents/commitments: run hidden follow-up extraction on the configured agent/default model instead of falling back to direct OpenAI, so OpenAI Codex OAuth-only gateways no longer spam background API-key failures. Fixes #75334. Thanks @sene1337.</li>
<li>Agents/media: keep async music generation completions on the requester-session wake path even when direct-send completion is enabled, so finished audio stays agent-mediated while video can still opt into direct channel delivery. (#75335) Thanks @vincentkoc.</li>
<li>Security/config-audit: redact CLI argv and execArgv secrets before persisting config audit records, covering write, observe, and recovery paths. Fixes #60826. Thanks @koshaji.</li>
<li>Gateway/models: keep default and configured model-list views responsive when provider catalog discovery stalls, without hiding real catalog load failures, while <code>--all</code> still waits for the exact full catalog. Fixes #75297; refs #74404. Thanks @lisandromachado and @najef1979-code.</li>
<li>Plugins/runtime-deps: accept already materialized package-level runtime-deps supersets as converged, so later lazy plugin activation no longer prunes and relaunches <code>pnpm install</code> after gateway startup pre-staging, reducing event-loop pressure from repeated runtime-deps repair on packaged installs. Fixes #75283; refs #75297 and #72338. Thanks @brokemac79, @lisandromachado, and @midhunmonachan.</li>
<li>Plugins/runtime-deps: remove OpenClaw-owned legacy runtime-deps symlinks before replacing staged bundled plugin dependencies, so updates can recover from older symlinked installs instead of failing the symlink safety guard. Thanks @goldmar.</li>
<li>Discord: retry queued REST 429s against learned bucket/global cooldowns and reacquire fresh voice upload URLs after CDN upload rate limits, so outbound sends recover without reusing stale single-use upload URLs. Thanks @discord.</li>
<li>TTS/providers: keep bundled speech-provider compat fallback available when plugins are globally disabled, so cold gateway and CLI startup can still resolve fallback speech providers instead of leaving explicit TTS provider selection with no registered providers. Refs #75265. Thanks @sliekens.</li>
<li>Discord: collapse repeated native slash-command deploy rate-limit startup logs into one non-fatal warning while keeping per-request REST timing in verbose output. Thanks @discord.</li>
<li>Discord: report native slash-command deploy aborts as REST timeouts with method, path, timeout budget, and observed duration, so startup logs explain slow Discord API calls instead of showing a generic aborted operation. Thanks @discord.</li>
<li>Security/logging: redact payment credential field names such as card number, CVC/CVV, shared payment token, and payment credential across default log and tool-payload redaction patterns so wallet-style MCP tools do not expose raw payment credentials in UI events or transcripts. Thanks @stainlu.</li>
<li>Providers/OpenAI Codex: preserve existing wrapped Codex streams during OpenAI attribution so PI OAuth bearer injection reaches ChatGPT/Codex Responses, and strip native Codex-only unsupported payload fields without touching custom compatible endpoints. (#75111) Thanks @keshavbotagent.</li>
<li>Plugins/runtime-deps: materialize newly required bundled plugin packages after local <code>openclaw onboard</code> and <code>openclaw configure</code> config writes, while keeping remote setup read-only, so first Gateway startup no longer discovers missing channel/provider deps after setup claimed success. Fixes #75309; refs #75069. Thanks @scottgl9 and @xiaohuaxi.</li>
<li>Plugins/runtime-deps: expire stale legacy install locks whose live PID cannot be tied to the current process incarnation, so Docker PID reuse no longer leaves bundled dependency repair stuck behind old <code>.openclaw-runtime-deps.lock</code> directories. Fixes #74948; refs #74950 and #74346. Thanks @dchekmarev.</li>
<li>Plugins/runtime-deps: recover interrupted bundled runtime-dependency installs whose package sentinels exist but generated materialization is incomplete, forcing npm/pnpm repair in Gateway startup, doctor, and lazy plugin loads instead of leaving channels crash-looping on missing packages. Fixes #75309; refs #75310, #75296, and #75304. Thanks @scottgl9.</li>
<li>Plugins/runtime-deps: treat no-main and export-map package sentinels without reachable entry files as incomplete, so Gateway startup, doctor, and lazy plugin loads repair interrupted bundled dependency installs instead of accepting package.json-only partial installs. Fixes #75309; refs #75183. Thanks @shakkernerd.</li>
<li>Plugins/runtime-deps: keep runtime inspection and channel maintenance commands from downloading bundled plugin dependencies, route explicit repairs through <code>openclaw plugins deps --repair</code>, and still allow Gateway/DO paths to repair missing deps before import. Refs #75069. Thanks @xiaohuaxi.</li>
<li>Updates: force non-deferred, no-cooldown update restarts after package-manager updates requested through the live Gateway control plane and fail release validation on post-swap stale chunk import crashes, so Telegram/Discord imports do not stay pointed at removed dist files. Fixes #75206. Thanks @xonaman and @faux123.</li>
<li>Agents/tool-result guard: use the resolved runtime context token budget for non-context-engine tool-result overflow checks, so long tool-heavy sessions no longer compact early when <code>contextTokens</code> is larger than native <code>contextWindow</code>. Fixes #74917. Thanks @kAIborg24.</li>
<li>Gateway/systemd: exit with sysexits 78 for supervised lock and <code>EADDRINUSE</code> conflicts so <code>RestartPreventExitStatus=78</code> stops <code>Restart=always</code> restart loops instead of repeatedly reloading plugins against an occupied port. Fixes #75115. Thanks @yhyatt.</li>
<li>Agents/runtime: skip blank visible user prompts at the embedded-runner boundary before provider submission while still allowing internal runtime-only turns and media-only prompts, so Telegram/group sessions no longer leak raw empty-input provider errors when replay history exists. Fixes #74137. Thanks @yelog, @Gracker, and @nhaener.</li>
<li>Agents/Codex: isolate local Codex app-server <code>CODEX_HOME</code> and <code>HOME</code> per agent and add a deliberate Codex migration path with selectable skill copies, so personal Codex CLI skills, plugins, config, and hooks no longer leak into OpenClaw agents unless the operator migrates them into the workspace. Thanks @pashpashpash.</li>
<li>Security/Nextcloud Talk: make webhook signature validation use the padded timing-safe compare path even when the supplied signature length is wrong, keep normalized header lookup behavior, and extend regression coverage for tampered bodies, wrong secrets, array-backed headers, and truncated signatures. Carries forward earlier contributor work from #50516 by teddytennant. (#58097) Thanks @gavyngong.</li>
<li>Plugins/runtime-deps: replace stale symlinked mirror target roots before writing runtime-mirror temp files and skip rewriting already materialized hardlinks, so cross-version container upgrades no longer crash-loop on read-only image-layer paths while warm mirrors do less churn. Fixes #75108; refs #75069. Thanks @coletebou and @xiaohuaxi.</li>
<li>Auto-reply/group chats: fall back to automatic source delivery when a channel precomputes message-tool-only replies but the <code>message</code> tool is unavailable, so Discord/Slack-style group turns do not silently complete without a visible reply. Fixes #74868. Thanks @kagura-agent.</li>
<li>Browser/gateway: share one browser control runtime across the HTTP control server and <code>browser.request</code>, and refresh browser profile config from the source snapshot, so CLI status/start honors configured <code>browser.executablePath</code>, <code>headless</code>, and <code>noSandbox</code> instead of falling back to stale auto-detection. Fixes #75087; repairs #73617. Thanks @civiltox and @martingarramon.</li>
<li>Agents/subagents: bound automatic orphan recovery with persisted recovery attempts and a wedged-session tombstone, and teach task maintenance/doctor to reconcile those sessions so restart loops no longer require manual <code>sessions.json</code> surgery. Fixes #74864. Thanks @solosage1.</li>
<li>Plugins/runtime-deps: keep bundled provider policy config loading from staging plugin runtime dependencies, so config reads no longer fail on locked-down <code>/var/lib/openclaw/plugin-runtime-deps</code> directories. Fixes #74971. Thanks @eurojojo.</li>
<li>Memory/runtime-deps: retain the native <code>node-llama-cpp</code> runtime only when local memory search is configured, so packaged installs can repair local embeddings without relying on unreachable global npm installs. Fixes #74777. Thanks @LLagoon3.</li>
<li>Gateway/startup: skip pre-bind web-fetch provider discovery for credential-free <code>tools.web.fetch</code> config, so Docker/Kubernetes gateways bind even when optional fetch limits are present. Fixes #74896. Thanks @KoykL.</li>
<li>Signal: match group allowlists against inbound Signal group ids as well as sender ids, and process explicitly configured Signal groups without requiring mentions unless <code>requireMention</code> is set. Fixes #53308. Thanks @minupla and @juan-flores077.</li>
<li>Signal: bound <code>signal-cli</code> installer release and archive downloads with explicit timeouts, declared and streamed size checks, and partial-file cleanup. Fixes #54153. Thanks @jinduwang1001-max and @juan-flores077.</li>
<li>Slack: require bot-authored room messages with <code>allowBots=true</code> to come from an explicitly channel-allowlisted bot or from a room where an explicit Slack owner is present, so broad bot relays cannot run unattended. Fixes #59284. Thanks @andrewhong-translucent.</li>
<li>Signal: derive <code>getAttachment</code> HTTP response caps from <code>channels.signal.mediaMaxMb</code> with base64 headroom, so inbound photos and videos no longer drop behind the 1 MiB RPC default. Fixes #73564. Thanks @heyhudson.</li>
<li>Signal: keep the long-lived receive SSE monitor open while idle instead of applying the 10s RPC/check deadline, so <code>signal-cli</code> 0.14.3 event streams no longer reconnect before inbound messages arrive. Fixes #74741. Thanks @fgabelmannjr and @k7n4n5t3w4rt.</li>
<li>CLI/progress: suppress nested progress spinners and line clears while TUI input owns raw stdin, so Crestodian <code>/status</code> no longer disturbs the active input row. (#75003) Thanks @velvet-shark.</li>
<li>Models/OpenAI Codex: restore <code>openai-codex/gpt-5.4-mini</code> for ChatGPT/Codex OAuth PI runs after live OAuth proof, and align the manifest, forward-compat metadata, docs, and regression tests so stale cron and heartbeat configs resolve again. Fixes #74451. Thanks @0xCyda, @hclsys, and @Marvae.</li>
<li>Plugins/runtime-deps: always write a dependency map in generated runtime-deps install manifests, so npm does not crash or prune staged bundled-plugin packages when the plan is empty. Fixes #74949. Thanks @hclsys.</li>
<li>Telegram: use durable message edits for streaming previews instead of native draft state, so generated replies no longer flicker through draft-to-message transitions that look like duplicates. (#75073) Thanks @obviyus.</li>
<li>Telegram: echo preflighted DM voice-note transcripts back to the originating chat, including Telegram DM topic thread metadata, instead of only echoing later media-understanding transcripts. Fixes #75084. Thanks @M-Lietz.</li>
<li>Telegram: clamp low long-polling client timeouts so configured <code>timeoutSeconds</code> values below the <code>getUpdates</code> poll window no longer force a fresh HTTPS connection every few seconds. Fixes #75114. Thanks @hpinho77.</li>
<li>Web search: describe <code>web_search</code> as using the configured provider instead of hard-coding Brave when DuckDuckGo or another provider is active. Fixes #75088. Thanks @sun-rongyang.</li>
<li>Infra/tmp: tolerate concurrent temp-dir permission repairs by rechecking directories that another process already tightened, so parallel ACP subprocess startup no longer throws <code>Unsafe fallback OpenClaw temp dir</code>. Fixes #66867. Thanks @Kane808-AI and @jarvisz8.</li>
<li>Agents/compaction: add an opt-in <code>agents.defaults.compaction.midTurnPrecheck</code> mid-turn precheck that detects tool-loop context pressure and triggers compaction before the next tool call instead of waiting for end-of-turn. (#73499) Thanks @marchpure and @haoxingjun.</li>
<li>Gateway/approvals: let loopback token/password-backed native approval clients resolve exec approvals without attaching stale paired Gateway identities, while remote and unauthenticated approval clients keep normal device identity behavior. (#74472)</li>
<li>Gateway/config: include rejected validation paths in foreground and service last-known-good recovery logs plus main-agent notices, so unsupported direct edits explain which key caused restore instead of looking like silent reversion. Fixes #75060. Thanks @amknight.</li>
<li>Plugins/runtime-deps: hash the OS-canonical <code>packageRoot</code> via <code>fs.realpathSync.native</code> (with <code>path.resolve</code> fallback) when computing the bundled runtime-deps stage key, so loader and channel <code>bundled-root</code> callers no longer derive divergent stage directories under <code>~/.openclaw/plugin-runtime-deps/openclaw-<version>-<hash>/</code> and bundled channels stop failing with <code>ENOENT</code> on shared dist chunks under Windows npm symlinks, junctions, or PM2 multi-instance worker layouts. Fixes #74963. (#75048) Thanks @openperf and @vincentkoc.</li>
<li>fix(logging): add redaction patterns for Tencent Cloud, Alibaba Cloud, HuggingFace and Replicate API keys (#58162). Thanks @gavyngong</li>
<li>Pairing: surface unexpected allowlist filesystem stat errors instead of treating the allowlist as missing, so permission and I/O failures are visible during pairing authorization checks. (#63324) Thanks @franciscomaestre.</li>
<li>macOS app: reserve layout space for exec approval command details so the allow dialog no longer overlaps the command, context, and action buttons. (#75470) Thanks @ngutman.</li>
<li>Agents/failover: carry <code>sessionId</code>, <code>lane</code>, <code>provider</code>, <code>model</code>, and <code>profileId</code> attribution through <code>FailoverError</code> and <code>describeFailoverError</code>/<code>coerceToFailoverError</code> so structured error logs (e.g. <code>gateway.err.log</code> ingestion) can attribute exhausted-fallback wrapper errors to the originating session and last-attempted provider instead of dropping the metadata after the per-profile errors. Fixes #42713. (#73506) Thanks @wenxu007.</li>
<li>Context Engine: treat assembled prompt as the default authority for preemptive overflow prechecks so engines that return a windowed, self-contained context no longer trigger false hard-fail compactions on huge raw history. Engines whose assembled view can hide overflow risk can opt back into the legacy behavior with <code>AssembleResult.promptAuthority: "preassembly_may_overflow"</code>. (#74255) Thanks @100yenadmin.</li>
<li>Mattermost: refresh current native slash command registrations before accepting callbacks so stale tokens from deleted or regenerated commands stop being accepted without a gateway restart while failed validations stay briefly cached and lookup starts are rate-limited per command, gate each callback against the resolved command's own startup token so a token leaked for one slash command cannot poison another command's failure cache, redact slash validation lookup errors, and add a body read timeout to the multi-account routing path so slow callback senders cannot tie up the dispatcher. Thanks @feynman-hou and @eleqtrizit.</li>
<li>Security/dotenv: block <code>COMSPEC</code> in workspace <code>.env</code> so a malicious repo cannot redirect Windows <code>cmd.exe</code> resolution, and lock in case-insensitive workspace-<code>.env</code> regression coverage for the full Windows shell trust-root family (<code>COMSPEC</code>, <code>PROGRAMFILES</code>, <code>PROGRAMW6432</code>, <code>SYSTEMROOT</code>, <code>WINDIR</code>). (#74460) Thanks @mmaps.</li>
<li>Gateway/install: drop stale version-manager and package-manager PATH entries preserved from old service files during <code>gateway install --force</code> and doctor repair, so the repair path no longer recreates <code>gateway-path-nonminimal</code> warnings. Fixes #75220. (#75440) Thanks @leonaIee, @renaudcerrato, and @aaajiao.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.5.2/OpenClaw-2026.5.2.zip" length="51078259" type="application/octet-stream" sparkle:edSignature="NwoecacHxJOYpltNmB/y7LV5I8ZIh5pENWSydbOM1vsfgSrcb7pRP+Zm2nih1IAq7hh1tOmQ0XWnsohic7U4DA=="/>
</item>
<item>
<title>2026.4.29</title>
<pubDate>Thu, 30 Apr 2026 21:47:22 +0000</pubDate>
@@ -657,240 +1057,5 @@
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.27/OpenClaw-2026.4.27.zip" length="50595360" type="application/octet-stream" sparkle:edSignature="X8DQNQNWVcvtpYLkhZcsKNpnA78ycyzgGlZaG0XBY1GIph3oZNUIpAszGGocJVqTK7+F89Au5ZPb60mOqJQ6DQ=="/>
</item>
<item>
<title>2026.4.26</title>
<pubDate>Tue, 28 Apr 2026 02:40:27 +0000</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>2026042690</sparkle:version>
<sparkle:shortVersionString>2026.4.26</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.4.26</h2>
<h3>Changes</h3>
<ul>
<li>Channels/QQBot: add full group chat support (history tracking, @-mention gating, activation modes, per-group config, FIFO message queue with deliver debounce), C2C <code>stream_messages</code> streaming with a <code>StreamingController</code> lifecycle manager, unified <code>sendMedia</code> with chunked upload for large files, and refactor the engine into pipeline stages, focused outbound submodules, builtin slash-command modules, and explicit DI ports via <code>createEngineAdapters()</code>. (#70624) Thanks @cxyhhhhh.</li>
<li>Channels/Yuanbao: register the Tencent Yuanbao external channel plugin (<code>openclaw-plugin-yuanbao</code>) in the official channel catalog, contract suites, and community plugin docs, with a new <code>docs/channels/yuanbao.md</code> quick-start guide for WebSocket bot DMs and group chats. (#72756) Thanks @loongfay.</li>
<li>Control UI/Talk: add a generic browser realtime transport contract, Google Live browser Talk sessions with constrained ephemeral tokens, and a Gateway relay for backend-only realtime voice plugins. Thanks @VACInc.</li>
<li>CLI/models: route provider-filtered model listing through an explicit source plan so user config, installed manifest rows, Provider Index previews, and scoped runtime fallbacks keep a stable authority order without adding another catalog cache. Thanks @shakkernerd.</li>
<li>Providers: add Cerebras as a bundled plugin with onboarding, static model catalog, docs, and manifest-owned endpoint metadata.</li>
<li>Memory/OpenAI-compatible: add optional <code>memorySearch.inputType</code>, <code>queryInputType</code>, and <code>documentInputType</code> config for asymmetric embedding endpoints, including direct query embeddings and provider batch indexing. Carries forward #63313 and #60727. Thanks @HOYALIM and @prospect1314521.</li>
<li>Ollama/memory: add model-specific retrieval query prefixes for <code>nomic-embed-text</code>, <code>qwen3-embedding</code>, and <code>mxbai-embed-large</code> memory-search queries while leaving document batches unchanged. Carries forward #45013. Thanks @laolin5564.</li>
<li>Plugins/providers: move pre-runtime model-id normalization, endpoint host metadata, OpenAI-compatible request-family hints, model-catalog aliases/suppressions, OpenAI stale Spark suppression, and reusable startup metadata snapshots into plugin manifests so core no longer carries bundled-provider routing tables or repeated manifest rebuilds. Thanks @shakkernerd.</li>
<li>Plugins/config: deprecate direct plugin config load/write helpers in favor of passed runtime snapshots plus transactional mutation helpers with explicit restart follow-up policy, scanner guardrails, runtime warnings, and revision-based cache invalidation.</li>
<li>Plugins/install: allow <code>OPENCLAW_PLUGIN_STAGE_DIR</code> to contain layered runtime-dependency roots, resolving read-only preinstalled deps before installing missing deps into the final writable root. Fixes #72396. Thanks @liorb-mountapps.</li>
<li>Control UI: add a raw config pending-changes diff panel that parses JSON5, redacts sensitive values until reveal, and avoids fake raw-edit callbacks when opening the panel. Refs #39831; supersedes #48621 and #46654. Thanks @JiajunBernoulli and @BunsDev.</li>
<li>Control UI: polish the quick settings dashboard grid so common cards align across desktop, tablet, and mobile layouts without wasting horizontal space. Thanks @BunsDev.</li>
<li>Matrix/E2EE: add <code>openclaw matrix encryption setup</code> to enable Matrix encryption, bootstrap recovery, and print verification status from one setup flow. Thanks @gumadeiras.</li>
<li>Agents/compaction: add an opt-in <code>agents.defaults.compaction.maxActiveTranscriptBytes</code> preflight trigger that runs normal local compaction when the active JSONL grows too large, requiring transcript rotation so successful compaction moves future turns onto a smaller successor file instead of raw byte-splitting history. Thanks @vincentkoc.</li>
<li>CLI/migration: add <code>openclaw migrate</code> with plan, dry-run, JSON, pre-migration backup, onboarding detection, archive-only reports, a Claude Code/Desktop importer, and a Hermes importer for configuration, memory/plugin hints, model providers, MCP servers, skills, commands, and supported credentials. Thanks @vincentkoc and @NousResearch.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Agents/LSP: terminate bundled stdio LSP process trees during runtime disposal and Gateway shutdown, so nested children such as <code>tsserver</code> do not survive stop or restart. Fixes #72357. Thanks @ai-hpc and @bittoby.</li>
<li>Gateway/device tokens: stop echoing rotated bearer tokens from shared/admin <code>device.token.rotate</code> responses while preserving the same-device token handoff needed by token-only clients before reconnect. (#66773) Thanks @MoerAI.</li>
<li>Control UI/Talk: keep Google Live browser sessions on the WebSocket transport instead of falling back to WebRTC, validate browser Google Live WebSocket endpoints, cap Gateway relay sessions per browser connection, and remove stale browser-native voice buttons that did not use the configured Talk/TTS provider. Thanks @BunsDev.</li>
<li>Gateway/startup: reuse config snapshot plugin manifests for startup auto-enable, config validation, and plugin bootstrap planning, including authored source config and disabled setup-probe handling, so restrictive allowlists avoid duplicate manifest/config passes during boot. Thanks @shakkernerd.</li>
<li>Agents/subagents: enforce <code>subagents.allowAgents</code> for explicit same-agent <code>sessions_spawn(agentId=...)</code> calls instead of auto-allowing requester self-targets. Fixes #72827. Thanks @oiGaDio.</li>
<li>ACP/sessions_spawn: let explicit <code>sessions_spawn(runtime="acp")</code> bootstrap turns run while <code>acp.dispatch.enabled=false</code> still blocks automatic ACP thread dispatch. Fixes #63591. Thanks @moeedahmed.</li>
<li>CLI/update: install npm global updates into a verified temporary prefix before swapping the package tree into place, preventing mixed old/new installs and stale packaged files from breaking <code>openclaw update</code> verification. Thanks @shakkernerd.</li>
<li>Gateway: skip CLI startup self-respawn for foreground gateway runs so low-memory Linux/Node 24 hosts start through the same path as direct <code>dist/index.js</code> without hanging before logs. Fixes #72720. Thanks @sign-2025.</li>
<li>Google Meet: route local Chrome joins through OpenClaw browser control, grant Meet media permissions, pin local Chrome audio defaults to <code>BlackHole 2ch</code>, and use the configured OpenClaw browser profile so joined agents no longer show <code>Permission needed</code> or use raw/default Chrome state. Thanks @DougButdorf and @oromeis.</li>
<li>Plugins/discovery: follow symlinked plugin directories in global and workspace plugin roots while keeping broken links ignored and existing package safety checks in place. Fixes #36754; carries forward #72695 and #63206. Thanks @Quackstro, @ming1523, and @xsfX20.</li>
<li>Plugins/install: skip test files and directories during install security scans while still force-scanning declared runtime entrypoints, so packaged test mocks no longer block plugin installs. Fixes #66840; carries forward #67050. Thanks @saurabhjain1592 and @Magicray1217.</li>
<li>Plugins/install: allow exact package-manager peer links back to the trusted OpenClaw host package during install security scans while continuing to block spoofed or nested escaping <code>node_modules</code> symlinks. Carries forward #70819. Thanks @fgabelmannjr.</li>
<li>Plugins/install: resolve plugin install destinations from the active profile state dir across CLI, ClawHub, marketplace, local path, and channel setup installs, so <code>openclaw --profile <name> plugins install ...</code> no longer writes into the default profile. Fixes #69960; carries forward #69971. Thanks @FrancisLyman and @Sanjays2402.</li>
<li>Plugins/registry: suppress duplicate-plugin startup warnings when a tracked npm-installed plugin intentionally overrides the bundled plugin with the same id. Carries forward #48673. Thanks @abdushsk.</li>
<li>Plugins/startup: reuse canonical realpath lookups throughout each plugin discovery pass, including package and manifest boundary checks, so Windows npm-global startups no longer repeat expensive path resolution for the same plugin roots. Fixes #65733. Thanks @welfo-beo.</li>
<li>Gateway/proxy: pass <code>ALL_PROXY</code> / <code>all_proxy</code> into the global Undici env-proxy dispatcher and provider proxy-fetch helper while keeping SSRF trusted-proxy auto-upgrade on <code>HTTP_PROXY</code> / <code>HTTPS_PROXY</code> only, so gateway/provider calls honor all-proxy setups without weakening guarded fetches. Fixes #43821; carries forward #43919. Thanks @RickyTong1.</li>
<li>Reply/link understanding: keep media and link preprocessing on stable runtime entrypoints and continue with raw message content if optional enrichment fails, so URL-bearing messages are no longer dropped after stale runtime chunk upgrades. Fixes #68466. Thanks @songshikang0111.</li>
<li>Discord: persist routed model-picker overrides when the hidden <code>/model</code> dispatch succeeds but the bound thread session store is still stale, including LM Studio suffixed model ids. Carries forward #61473. Thanks @Nanako0129.</li>
<li>Nodes/CLI: add <code>openclaw nodes remove --node <id|name|ip></code> and <code>node.pair.remove</code> so stale gateway-owned node pairing records can be cleaned without hand-editing state files.</li>
<li>Gateway: include the connecting client and fresh presence version in the initial <code>hello-ok</code> snapshot, so clients no longer need a follow-up event before seeing themselves online.</li>
<li>Docker: install the CA certificate bundle in the slim runtime image so HTTPS calls from containerized gateways no longer fail TLS setup after the <code>bookworm-slim</code> base switch. Fixes #72787. Thanks @ryuhaneul.</li>
<li>Providers/OpenRouter: remove retired Hunter Alpha and Healer Alpha static catalog rows and disable proxy reasoning injection for stale Hunter Alpha configs, so replies are not hidden when OpenRouter returns answer text in reasoning fields. Fixes #43942. Thanks @EvanDataForge.</li>
<li>Providers/reasoning: let Groq and LM Studio declare provider-native reasoning effort values, so Qwen thinking models receive <code>none</code>/<code>default</code> or <code>off</code>/<code>on</code> instead of OpenAI-only <code>low</code>/<code>medium</code> values. Fixes #32638. Thanks @Aqu1bp, @mgoulart, @Norpps, and @BSTail.</li>
<li>Local models: default custom providers with only <code>baseUrl</code> to the Chat Completions adapter and trust loopback model requests automatically, so local OpenAI-compatible proxies receive <code>/v1/chat/completions</code> without timing out. Fixes #40024. Thanks @parachuteshe.</li>
<li>Channels/message tool: surface Discord, Slack, and Mattermost <code>user:</code>/<code>channel:</code> target syntax in the shared message target schema and Discord ambiguity errors, so DM sends by numeric id stop burning retries before finding <code>user:<id></code>. Fixes #72401. Thanks @garyd9, @hclsys, and @praveen9354.</li>
<li>Agents/tools: scope tool-loop detection history to the active run when available, so scheduled heartbeat cycles no longer inherit stale repeated-call counts from previous runs. Fixes #40144. Thanks @mattbrown319.</li>
<li>Agents/subagents: preserve requester delivery for completion announces across different channel accounts, keep same-channel thread completions routed to the child thread, and fail closed instead of guessing a child binding when requester conversation signal is missing. Thanks @sfuminya and @suyua9.</li>
<li>Agents/status: persist the post-compaction token estimate from auto-compaction when providers omit usage metadata, so <code>/status</code> and session lists keep showing fresh context usage after compaction. Fixes #67667; carries forward #72822. Thanks @Jimmy-xuzimo and @skylight-9.</li>
<li>Control UI: show loading, reload, and retry states when a lazy dashboard panel cannot load after an upgrade, so the Logs tab no longer appears blank on stale browser bundles. Fixes #72450. Thanks @sobergou.</li>
<li>Gateway/plugins: start the Gateway in degraded mode when a single plugin entry has invalid schema config, and let <code>openclaw doctor --fix</code> quarantine that plugin config instead of crash-looping every channel. Fixes #62976 and #70371. Thanks @Doraemon-Claw and @pksidekyk.</li>
<li>Agents/plugins: skip malformed plugin tools with missing schema objects and report plugin diagnostics, so one broken tool no longer crashes Anthropic agent runs. Fixes #69423. Thanks @jmnickels.</li>
<li>Agents/reasoning: recover fully wrapped unclosed <code><think></code> replies that would otherwise sanitize to empty text while keeping strict stripping for closed reasoning blocks and unclosed tails after visible text. Fixes #37696; supersedes #51915. Thanks @druide67 and @okuyam2y.</li>
<li>Control UI/Gateway: bind WebChat handshakes to their active socket and reject post-close server registrations, so aborted connects no longer leave zombie clients or misleading duplicate WebSocket connection logs. Fixes #72753. Thanks @LumenFromTheFuture.</li>
<li>Agents/fallback: split ambiguous provider failures into <code>empty_response</code>, <code>no_error_details</code>, and <code>unclassified</code>, and add flat fallback-step fields to structured fallback logs so primary-model failures stay visible when later fallbacks also fail. Fixes #71922; refs #71744. Thanks @andyk-ms and @nikolaykazakovvs-ux.</li>
<li>Plugins/Windows: normalize Windows absolute paths before handing bundled plugin modules to Jiti, so Feishu/Lark message sending no longer fails with unsupported <code>c:</code> ESM loader URLs. Fixes #72783. Thanks @jackychen-png.</li>
<li>CLI/doctor: run bundled plugin runtime-dependency repairs through the async npm installer with spinner/line progress and heartbeat updates, so long <code>openclaw doctor --fix</code> installs no longer look hung in TTY or piped output. Fixes #72775. Thanks @dfpalhano.</li>
<li>Feishu/Windows: normalize bundled channel sidecar loads before Jiti evaluates them, so Feishu outbound sends no longer fail with raw <code>C:</code> ESM loader errors on Windows. Fixes #72783. Thanks @jackychen-png.</li>
<li>Agents/tools: ignore volatile <code>exec</code> runtime metadata when comparing tool-loop outcomes, so enabled loop detection can stop repeated identical shell-command results instead of resetting on duration, PID, session, or cwd changes. Fixes #34574; supersedes #41502. Thanks @gucasbrg and @Zcg2021.</li>
<li>Agents/fallback: classify internal live-session model switch conflicts as unknown fallback failures instead of provider overloads, preventing local vLLM endpoints from receiving misleading overloaded cooldowns. Refs #63229. Thanks @clawdia-lobster.</li>
<li>Discord: let thread sessions inherit the parent channel's session-level <code>/model</code> override as a model-only fallback without enabling parent transcript inheritance. Fixes #72755. Thanks @solavrc.</li>
<li>Gateway/plugins: skip stale configured channels whose matching plugin is no longer discoverable, point cleanup at <code>openclaw doctor --fix</code>, and keep unrelated channel typos fatal so one missing channel plugin no longer crash-loops the Gateway. Fixes #53311. Thanks @futhgar.</li>
<li>Control UI: keep session-specific assistant identity loads authoritative after WebSocket connect, so non-main agent chat sessions do not show the main agent name in the header after bootstrap refreshes. Fixes #72776. Thanks @rockytian-top.</li>
<li>Agents/Qwen: preserve exact custom <code>modelstudio</code> provider configs with foreign <code>api</code> owners so explicit OpenAI-compatible Model Studio endpoints no longer get normalized into the bundled Qwen plugin path. Fixes #64483. Thanks @FiredMosquito831.</li>
<li>MCP/bundle-mcp: normalize CLI-native <code>type: "http"</code> MCP server entries to OpenClaw <code>transport: "streamable-http"</code> on save, repair existing configs with doctor, and keep embedded Pi from falling back to legacy SSE GET-first startup for those servers. Fixes #72757. Thanks @Studioscale.</li>
<li>OpenCode: expose Anthropic Opus/Sonnet 4.x thinking levels for proxied Claude models, so <code>/think xhigh</code>, <code>/think adaptive</code>, and <code>/think max</code> validate consistently with the direct Anthropic provider. Fixes #72729. Thanks @haishmg and @aaajiao.</li>
<li>Media-understanding/audio: migrate deprecated <code>{input}</code> placeholders in legacy <code>audio.transcription.command</code> configs to <code>{{MediaPath}}</code>, so custom audio transcribers no longer receive the literal placeholder after doctor repair. Fixes #72760. Thanks @krisfanue3-hash.</li>
<li>Ollama/WSL2: warn when GPU-backed WSL2 installs combine CUDA visibility with an autostarting <code>ollama.service</code> using <code>Restart=always</code>, and document the systemd, <code>.wslconfig</code>, and keep-alive mitigation for crash loops. Carries forward #61022; fixes #61185. Thanks @yhyatt.</li>
<li>Ollama/onboarding: de-dupe suggested bare local models against installed <code>:latest</code> tags and skip redundant pulls, so setup shows the installed model once and no longer says it is downloading an already available model. Fixes #68952. Thanks @tleyden.</li>
<li>Memory-core/doctor: keep <code>doctor.memory.status</code> on the cached path by default and only run live embedding pings for explicit deep probes, preventing slow local embedding backends from blocking Gateway status checks. Fixes #71568. Thanks @apex-system.</li>
<li>Memory/QMD: group same-source collections into one QMD search invocation when the installed QMD supports multiple <code>-c</code> filters, while keeping older QMD builds on the per-collection fallback. Fixes #72484; supersedes #72485 and #69583. Thanks @BsnizND and @zeroaltitude.</li>
<li>Memory/QMD: accept QMD status vector-count variants such as <code>Vectors = 42</code>, <code>Vectors:42</code>, and <code>Vectors: 42 embedded</code>, so <code>memory status --deep</code> no longer reports embeddings unavailable for healthy QMD wrappers. Fixes #63652; carries forward #63678. Thanks @apoapostolov and @WarrenJones.</li>
<li>Memory/QMD: skip QMD vector status probes and embedding maintenance in lexical <code>searchMode: "search"</code>, so BM25-only QMD setups on ARM do not trigger llama.cpp/Vulkan builds during status checks or embed cycles. Fixes #59234 and #67113. Thanks @PrinceOfEgypt, @Vksh07, @Snipe76, @NomLom, @t4r3e2q1-commits, and @dmak.</li>
<li>Memory/QMD: report the live watcher dirty state in memory status, so changed QMD-backed memory files show as dirty until the queued sync finishes. Fixes #60244. Thanks @xinzf.</li>
<li>Compaction: skip oversized pre-compaction checkpoint snapshots and prune duplicate long user turns from compaction input and rotated successor transcripts, preventing retry storms from being preserved across checkpoint cycles. Fixes #72780. Thanks @SweetSophia.</li>
<li>Control UI/Cron: render cron job prompts and run summaries as sanitized markdown in the dashboard, with full-width block content, safer link clicks, and no duplicate error text when a failed run has no summary. Supersedes #48504. Thanks @garethdaine.</li>
<li>Control UI/Gateway: preserve WebChat client version labels across localhost, 127.0.0.1, and IPv6 loopback aliases on the same port, avoiding misleading <code>vcontrol-ui</code> connection logs while investigating duplicate-message reports. Refs #72753 and #72742. Thanks @LumenFromTheFuture and @allesgutefy.</li>
<li>Agents/reasoning: treat orphan closing reasoning tags with following answer text as a privacy boundary across delivery, history, streaming, and Control UI sanitizers so malformed local-model output cannot leak chain-of-thought text. Fixes #67092. Thanks @AnildoSilva.</li>
<li>Memory-core: run one-shot memory CLI commands through transient builtin and QMD managers so <code>memory index</code>, <code>memory status --index</code>, and <code>memory search</code> no longer start long-lived file watchers that can hit macOS <code>EMFILE</code> limits. Fixes #59101; carries forward #49851. Thanks @mbear469210-coder and @maoyuanxue.</li>
<li>Agents/ACP: ship the Claude ACP adapter with OpenClaw and require Claude result messages before idle can complete a prompt, preventing parent agents from waking early on long-running <code>sessions_spawn(runtime: "acp", agentId: "claude")</code> children. Fixes #72080. Thanks @siavash-saki and @iannwu.</li>
<li>CLI/tasks: route <code>tasks --json</code>, <code>tasks list --json</code>, and <code>tasks audit --json</code> through a lean JSON path so read-only task inspection no longer loads unrelated plugin/runtime command graphs. Fixes #66238. Thanks @ChuckChambers.</li>
<li>Memory-core: re-resolve the active runtime config whenever <code>memory_search</code> or <code>memory_get</code> executes, so provider changes made by <code>config.patch</code> stop leaving stale embedding backends behind in existing tool instances. Fixes #61098. Thanks @BradGroux and @Linux2010.</li>
<li>WebChat: keep bare <code>/new</code> and <code>/reset</code> startup instructions out of visible chat history while preserving <code>/reset <note></code> as user-visible transcript text. Fixes #72369. Thanks @collynes and @haishmg.</li>
<li>Tasks/memory: checkpoint and truncate SQLite WAL sidecars on a timer and before close for task, Task Flow, proxy capture, and builtin memory databases, bounding long-running gateway <code>*.sqlite-wal</code> growth. Fixes #72774. Thanks @dfpalhano.</li>
<li>CLI/doctor: remove dangling channel config, heartbeat targets, and channel model overrides when stale plugin repair removes a missing channel plugin, preventing Gateway boot loops after failed plugin reinstalls. Fixes #65293. Thanks @yidecode.</li>
<li>Control UI/Gateway: cache, coalesce, stale-refresh, and invalidate effective tool inventory on channel registry changes while reusing the gateway-bound plugin registry and avoiding model/auth discovery, so chat runs no longer stall Control UI requests on repeated plugin/model setup. Fixes #72365; supersedes #72558. Thanks @Gabiii2398 and @1yihui.</li>
<li>Channels/setup: treat bundled channel plugins as already bundled during <code>channels add</code> and onboarding, enabling them without writing redundant <code>plugins.load.paths</code> entries or path install records. Fixes #72740. Thanks @iCodePoet.</li>
<li>WhatsApp: honor gateway <code>HTTPS_PROXY</code> / <code>HTTP_PROXY</code> env vars for QR-login WebSocket connections, while respecting <code>NO_PROXY</code>, so proxied networks no longer fall back to direct <code>mmg.whatsapp.net</code> connections that time out with 408. Fixes #72547; supersedes #72692. Thanks @mebusw and @SymbolStar.</li>
<li>Bonjour: default mDNS advertisements to the system hostname when it is DNS-safe, avoiding <code>openclaw.local</code> probing conflicts and Gateway restart loops on hosts such as <code>Lobster</code> or <code>ubuntu</code>. Fixes #72355 and #72689; supersedes #72694. Thanks @mscheuerlein-bot, @gcusms, @moyuwuhen601, @pavan987, @zml-0912, @hhq365, and @SymbolStar.</li>
<li>Agents/OpenAI-compatible: retry replay-safe empty <code>stop</code> turns once for <code>openai-completions</code> endpoints, so transient empty local backend responses no longer surface as “Agent couldn't generate a response” when a continuation succeeds, and restore <code>openclaw agent --model</code> for one-shot CLI runs. Fixes #72751. Thanks @moooV252.</li>
<li>Git hooks: skip ignored staged paths when formatting and restaging pre-commit files, so merge commits no longer abort when <code>.gitignore</code> newly ignores staged merged content. Fixes #72744. Thanks @100yenadmin.</li>
<li>Memory-core/dreaming: add a supported <code>dreaming.model</code> knob for Dream Diary narrative subagents, wired through phase config and the existing plugin subagent model-override trust gate. Refs #65963. Thanks @esqandil and @mjamiv.</li>
<li>Agents/Anthropic: remove trailing assistant prefill payloads when extended thinking is enabled, so Opus 4.7/Sonnet 4.6 requests do not fail Anthropic's user-final-turn validation. Fixes #72739. Thanks @superandylin.</li>
<li>Agents/vLLM/Qwen: add plugin-owned Qwen thinking controls for vLLM chat-template kwargs and DashScope-style top-level <code>enable_thinking</code> flags, including preserved thinking for agent loops. Fixes #72329. Thanks @stavrostzagadouris.</li>
<li>Memory-core/dreaming: treat request-scoped narrative fallback as expected, skip session cleanup when no subagent run was created, and remove duplicate phase-level cleanup so fallback no longer emits warning noise. Fixes #67152. Thanks @jsompis.</li>
<li>Agents/exec: apply configured <code>tools.exec.timeoutSec</code> to background, <code>yieldMs</code>, and node <code>system.run</code> commands when no per-call timeout is set, preventing auto-backgrounded and remote node commands from running indefinitely. Fixes #67600; supersedes #67603. Thanks @dlmpx and @kagura-agent.</li>
<li>Config/doctor: stop masking unknown-key validation diagnostics such as <code>agents.defaults.llm</code>, and have <code>openclaw doctor --fix</code> remove the retired <code>agents.defaults.llm</code> timeout block. Thanks @aidiffuser.</li>
<li>CLI/startup: keep the built pre-dispatch CLI graph free of package-level imports and extend packaged CLI smoke coverage to onboard and doctor help paths, preventing missing runtime dependencies such as tslog from killing onboarding before repair code can run. Fixes #63024. Thanks @hu19940121.</li>
<li>CLI/plugins: preserve unversioned ClawHub install specs so <code>plugins update</code> can follow newer ClawHub releases instead of pinning to the initially resolved version. Fixes #63010; supersedes #58426. Thanks @kangsen1234 and @robinspt.</li>
<li>Memory-core/subagents: tag plugin-created subagent sessions with their plugin owner so dreaming narrative cleanup can delete its own ephemeral sessions without granting broad admin session deletion. Fixes #72712. Thanks @BSG2000.</li>
<li>Gateway/models: move local-provider pricing opt-outs, OpenRouter/LiteLLM aliases, and proxy passthrough pricing lookup into plugin manifest metadata so core no longer carries extension-specific pricing tables.</li>
<li>CLI/update: honor <code>OPENCLAW_NO_AUTO_UPDATE=1</code> as a gateway startup kill-switch for configured background package auto-updates, so operators can hold a deliberate downgrade during incident recovery without editing config first. Fixes #72715. Thanks @Xivi08.</li>
<li>Agents/Claude CLI: force live-session launches to include <code>--output-format stream-json</code> whenever OpenClaw adds <code>--input-format stream-json</code>, so new Claude CLI sessions no longer fail immediately while reusable sessions keep working. Fixes #72206. Thanks @kwangwonkoh and @Xivi08.</li>
<li>CLI/plugins: accept ClawHub plugin API wildcard ranges such as <code>*</code> without rejecting compatible plugin installs, while still requiring a valid runtime API version. Fixes #56446; supersedes #56466. Thanks @darconada and @claygeo.</li>
<li>CLI/plugins: add an explicit <code>npm:<package></code> install prefix that skips ClawHub lookup for known npm packages while keeping bare package specs ClawHub-first. Fixes #55805; supersedes #54377. Thanks @Zeoy2020 and @vagusX.</li>
<li>CLI/plugins: let config-gated bundled plugins install without persisting invalid placeholder config entries, so install/uninstall sweeps can cover plugins such as memory-lancedb before the user configures credentials. Thanks @vincentkoc.</li>
<li>CLI/plugins: reject malformed ClawHub plugin specs with trailing <code>@</code> before registry lookup, so empty-version typos report as invalid specs instead of package-not-found errors. Fixes #56579; supersedes #56582. Thanks @Kansodata.</li>
<li>Agents/sessions: acquire the session write lock only after cold bootstrap, plugin, and tool setup so fallback runs are not blocked by stalled pre-model startup work.</li>
<li>Browser/plugins: auto-start the bundled browser plugin when root <code>browser</code> config is present, including restrictive plugin allowlists, and ignore stale persisted plugin registries whose package paths no longer exist.</li>
<li>Browser: circuit-break repeated managed Chrome launch failures per profile so browser requests stop spawning Chromium indefinitely when CDP cannot start. Fixes #64271. Thanks @TheophilusChinomona.</li>
<li>Gateway/models: skip external OpenRouter and LiteLLM pricing refreshes for local/self-hosted model endpoints so startup does not wait on remote pricing catalogs for local-only Ollama, vLLM, and compatible providers.</li>
<li>CLI/plugins: stop security-blocked plugin installs from retrying as hook packs, so normal plugin packages report the scanner failure without a misleading "not a valid hook pack" follow-up. Fixes #61175; supersedes #64102. Thanks @KonsultDigital and @ziyincody.</li>
<li>Agents/Anthropic: strip stale trailing assistant prefill turns from outbound replay so context-engine short circuits cannot send unsupported assistant-prefill payloads to provider APIs. Fixes #72556. Thanks @Veda-openclaw.</li>
<li>Agents/Google: strip stale trailing assistant/model prefill turns from Gemini outbound replay so Google Generative AI requests end with a user turn or function response. Follow-up to #72556. Thanks @Veda-openclaw.</li>
<li>Control UI/Dreaming: require explicit confirmation before applying restart-impacting Dreaming mode changes, with restart warning copy and loading feedback. Fixes #63804. (#63807) Thanks @bbddbb1.</li>
<li>CLI/agent: mark Gateway-to-embedded fallback runs with <code>meta.transport: "embedded"</code> and <code>meta.fallbackFrom: "gateway"</code> in JSON output, and make the terminal diagnostic explicit so scripts and operators can distinguish fallback runs from Gateway runs. Fixes #71416. Thanks @amknight.</li>
<li>Agents/tools: normalize <code>null</code> or missing tool-call arguments to <code>{}</code> for parameterless object schemas before Pi validation, so empty-argument tools run instead of failing argument validation. Fixes #72587. Thanks @amknight.</li>
<li>Agents/subagents: clear active embedded-run state before terminal lifecycle events so post-completion cleanup no longer treats finished child runs as still active and skips archive or announcement bookkeeping. (#70187) Thanks @amknight.</li>
<li>CLI/update: keep the automatic post-update completion refresh on the core-command tree so it no longer stages bundled plugin runtime deps before the Gateway restart path, avoiding <code>.24</code> update hangs and 1006 disconnect cascades. Fixes #72665. Thanks @sakalaboator and @He-Pin.</li>
<li>Control UI: make explicit Reload Config actions discard stale local config edits while passive refreshes and failed-save recovery keep pending drafts intact. Fixes #40352; carries forward #40443. Thanks @realmikechong-dotcom.</li>
<li>Agents/Bedrock: stop heartbeat runs from persisting blank user transcript turns and repair existing blank user text messages before replay, preventing AWS Bedrock <code>ContentBlock</code> blank-text validation failures. Fixes #72640 and #72622. Thanks @goldzulu.</li>
<li>Agents/LM Studio: promote standalone bracketed local-model tool requests into registered tool calls and hide unsupported bracket blocks from visible replies, so MemPalace MCP lookups do not print raw <code>[tool]</code> JSON scaffolding in chat. Fixes #66178. Thanks @detroit357.</li>
<li>Local models: warn when an assistant reply looks like a tool call but the provider emitted plain text instead of a structured tool invocation, making fake/non-executed tool calls visible in logs. Fixes #51332. Thanks @emilclaw.</li>
<li>Local models: accept persisted non-secret local auth markers for private-LAN custom OpenAI-compatible providers, so LAN Ollama configs no longer fail with missing auth when <code>ollama-local</code> is saved as the key. Fixes #49736. Thanks @charles-zh.</li>
<li>TUI/local models: treat visible gateway client labels such as <code>openclaw-tui</code> as the current requester session for session-aware tools, so Ollama tool calls no longer fail by resolving the UI label as a session id. Fixes #66391. Thanks @kickingzebra.</li>
<li>Local models: route self-hosted OpenAI-compatible model discovery through the guarded fetch path pinned to the configured host, covering vLLM and SGLang setup without reopening local/LAN SSRF probes. Supersedes #46359. Thanks @cdxiaodong.</li>
<li>Local models: classify terminated, reset, closed, timeout, and aborted model-call failures and attach a process memory snapshot to the diagnostic event, making LM Studio/Ollama RAM-pressure failures easier to prove from stability bundles. Refs #65551. Thanks @BigWiLLi111.</li>
<li>Local models: pass configured provider request timeouts through OpenAI SDK transports and the model idle watchdog so long-running local or custom OpenAI-compatible streams use one timeout knob instead of hitting the SDK's 10-minute default or the 120s idle default. Fixes #63663. Thanks @aidiffuser.</li>
<li>LM Studio: trust configured LM Studio loopback, LAN, and tailnet endpoints for guarded model requests by default, preserving explicit private-network opt-outs. Refs #60994. Thanks @tnowakow.</li>
<li>Docker/setup: route Docker onboarding defaults for host-side LM Studio and Ollama through <code>host.docker.internal</code> and add the Linux host-gateway mapping to the bundled Compose file, so containerized gateways can reach local providers without using container loopback. Fixes #68684; supersedes #68702. Thanks @safrano9999 and @skolez.</li>
<li>Agents/LM Studio: strip prior-turn Gemma 4 reasoning from OpenAI-compatible replay while preserving active tool-call continuation reasoning. Fixes #68704. Thanks @chip-snomo and @Kailigithub.</li>
<li>LM Studio: allow interactive onboarding to leave the API key blank for unauthenticated local servers, using local synthetic auth while clearing stale LM Studio auth profiles. Fixes #66937. Thanks @olamedia.</li>
<li>Plugins/startup/registry: reuse a Gateway <code>PluginLookUpTable</code> and one manifest registry pass across startup plugin IDs, plugin loading, deferred channel reloads, model pricing, read-only channel defaults, capability/provider/media resolution, manifest contracts, extractors, web fallback discovery, owner maps, and cold provider-discovery caches, with new startup-trace timing/count metrics for installed-index, manifest, startup-plan, and owner-map work. Thanks @shakkernerd and @mcaxtr.</li>
<li>Mattermost: keep direct-message replies top-level by suppressing reply roots for DM delivery while preserving channel and group thread roots, and derive inbound chat kind from the trusted channel lookup instead of the websocket event channel type. Carries forward #60115, #55186, #72305, and #72659; refs #59758, #59981, #59791, and #57565. Thanks @vincentkoc, @jwchmodx, and @hnykda.</li>
<li>Docker: pre-create <code>/home/node/.openclaw</code> with node ownership and private permissions so first-run Docker Compose named volumes no longer fail startup with EACCES. (#48072, #63959; fixes #61279) Thanks @timoxue and @jeanibarz.</li>
<li>CLI/Gateway: treat local restart probe policy closes for connect, exact <code>device required</code>, pairing, and auth failures as Gateway reachability proof without accepting empty, broad standalone token/password/scope/role, or pair-substring 1008 close reasons. Fixes #48771; carries forward #48801; related #63491. Thanks @MarsDoge and @genoooool.</li>
<li>Feishu: send outgoing interactive reply payloads as native cards with clickable buttons while preserving text, media, and document-comment fallbacks. Fixes #13175 and #58298; carries forward #47891. Thanks @Horacehxw.</li>
<li>Process/Windows: decode command stdout and stderr from raw bytes with console-codepage awareness, while preserving valid UTF-8 output and multibyte characters split across chunks. Fixes #50519. Thanks @iready, @kevinten10, @zhangyongjie1997, @knightplat-blip, @heiqishi666, and @slepybear.</li>
<li>Bonjour/Windows: hide the bundled mDNS advertiser's Windows ARP shell probe so Gateway startup no longer flashes command-prompt windows. Fixes #70238. Thanks @alexandre-leng, @PratikRai0101, @infinitypacific, and @tomerpeled.</li>
<li>Agents/bootstrap: dedupe hook-injected bootstrap context files by workspace-relative path and store normalized resolved paths so duplicate relative and absolute hook paths no longer depend on the process cwd. (#59344; fixes #59319; related #56721, #56725, and #57587) Thanks @koen666.</li>
<li>Agents/bootstrap: refresh cached workspace bootstrap snapshots on long-lived main-session turns when <code>AGENTS.md</code>, <code>SOUL.md</code>, <code>MEMORY.md</code>, or <code>TOOLS.md</code> change on disk, while preserving unchanged snapshot identity through the workspace file cache. (#64871; related #43901, #26497, #28594, #30896) Thanks @aimqwest and @mikejuyoon.</li>
<li>macOS Gateway: detect installed-but-unloaded LaunchAgent split-brain states during status, doctor, and restart, and re-bootstrap launchd supervision before falling back to unmanaged listener restarts. Fixes #67335, #53475, and #71060; refs #58890, #60885, and #70801. Thanks @ze1tgeist88, @dafacto, and @vishutdhar.</li>
<li>Plugins/install: treat mirrored core logger dependencies as staged bundled runtime deps so packaged Gateway starts do not crash when the external plugin-runtime-deps root is missing <code>tslog</code>. Fixes #72228; supersedes #72493. Thanks @deepujain.</li>
<li>Build/plugins: preserve active bundled runtime-dependency staging temp directories owned by live build processes so overlapping postbuild runs no longer delete each other's staged deps mid-prune. Supersedes #72220. Thanks @VACInc.</li>
<li>Plugins/install: hide bundled runtime-dependency npm child windows on Windows across Gateway startup, postinstall, and packaged staging paths so Telegram/Anthropic dependency repair no longer flashes shell windows. Fixes #72315. Thanks @athuljayaram and @joshfeng.</li>
<li>Agents/Windows: normalize lazy agent runtime imports before Node ESM loading so Windows drive-letter <code>subagent-registry</code> runtime paths no longer fail every agent task with <code>ERR_UNSUPPORTED_ESM_URL_SCHEME</code>. Fixes #72636; carries forward #72716. Thanks @Andyz-CData and @xialonglee.</li>
<li>Plugins/Windows: normalize lazy plugin service override imports before Node ESM loading so drive-letter browser-control module paths no longer fail with <code>ERR_UNSUPPORTED_ESM_URL_SCHEME</code>. Fixes #72573; supersedes #72599 and #72582. Thanks @llzzww316, @feineryonah-byte, and @WuKongAI-CMU.</li>
<li>Browser/plugins: load <code>playwright-core</code> through the browser runtime shim so packaged installs can run Playwright actions from staged plugin runtime deps after doctor/startup repair. Fixes #72168; supersedes #72238. Thanks @zdg1110 and @yetval.</li>
<li>Plugins/install: stage bundled plugin runtime dependencies before Gateway startup, drain update restarts, and materialize plugin-owned root chunks in external mirrors so staged deps resolve under native ESM. Fixes #72058; supersedes #72084. Thanks @amnesia106 and @drvoss.</li>
<li>TTS/SecretRef: resolve <code>messages.tts.providers.*.apiKey</code> from the active runtime snapshot so SecretRef-backed MiniMax and other TTS provider keys work in runtime reply/audio paths. Fixes #68690. Thanks @joshavant.</li>
<li>Gateway/install: surface systemd user-bus recovery hints during Linux service activation and retry via the target user scope when <code>systemctl --user</code> reports no-medium bus failures, without letting stale <code>SUDO_USER</code> override <code>sudo -u</code> installs. Fixes #39673; refs #44417 and #63561. Thanks @Arbor4, @myrsu, @mssteuer, and @boyuaner.</li>
<li>CLI/nodes: make unfiltered <code>openclaw nodes list</code> prefer the effective paired-node view used by <code>nodes status</code> while preserving pending rows, pairing-scope fallback, terminal-safe table rendering, and paired JSON metadata. Fixes #46871; carries forward #65772 through the ProjectClownfish #72619 repair. Thanks @skainguyen1412.</li>
<li>CLI/startup: read generated startup metadata from the bundled <code>dist</code> layout before falling back to live help rendering, so root/browser help and channel-option bootstrap stay on the fast path. Thanks @vincentkoc.</li>
<li>Feishu/Lark: stop treating broadcast-only <code>@all</code>/<code>@_all</code> messages as bot mentions while preserving direct bot mentions, including messages that also include <code>@all</code>. Fixes #37706. Thanks @JosepLee.</li>
<li>CLI/help: treat positional <code>help</code> invocations like <code>openclaw channels help</code> as help paths for startup gating, avoiding model/auth warmup while preserving positional arguments such as <code>openclaw docs help</code>. Thanks @gumadeiras.</li>
<li>Web search: route plugin-scoped web_search SecretRefs through the active runtime config snapshot so provider execution receives resolved credentials across app/runtime paths, including <code>plugins.entries.brave.config.webSearch.apiKey</code>. Fixes #68690. Thanks @VACInc.</li>
<li>Voice Call: allow SecretRef-backed Twilio auth tokens and call-specific OpenAI/ElevenLabs TTS API keys through the plugin config surface. Fixes #68690. Thanks @joshavant.</li>
<li>Google Meet/Voice Call: clean stale chrome-node realtime bridges before rejoining, expose bridge inspection, tolerate transient node input pull failures, default Chrome command-pair audio to 24 kHz PCM16 while preserving legacy 8 kHz G.711 mu-law pairs, handle Gemini Live interruptions/VAD and function-response names correctly, route stateful <code>google_meet</code> tools through the gateway runtime, support <code>realtime.agentId</code>, and send non-blocking consult continuations before long tool-backed answers finish. Fixes #72371, #72525, #72523, #72440, and #72425; (#72372, #72524, #72381, #72441, #72189, #72426) Thanks @BsnizND and @VACInc.</li>
<li>Discord/media: keep incidental Markdown image badges in final replies as text unless a channel opts into Markdown-image media extraction, while preserving Telegram Markdown-image media replies and explicit <code>MEDIA:</code> attachments. Fixes #72642. Thanks @solavrc and @Bartok9.</li>
<li>Matrix/E2EE: stabilize recovery and broken-device QA flows while avoiding Matrix device-cleanup sync races that could leave shutdown-time crypto work running. Thanks @gumadeiras.</li>
<li>Cron: apply <code>cron.maxConcurrentRuns</code> to the nested isolated-agent lane, start isolated execution timeouts only after the runner enters that lane, keep legacy flat <code>jobs.json</code> rows loadable, invalidate stale pending runtime slots after schedule edits, and preserve due slots for formatting-only rewrites. Fixes #72707, #27996, #71607, and #41783; carries forward #71651. Thanks @kagura-agent, @xialonglee, @fagnersouza666, @ayanesakura, and @Hurray0.</li>
<li>Cron/delivery: classify isolated successes, quiet <code>NO_REPLY</code> turns, model/provider failures, execution denials, <code>--no-deliver</code> traces, skipped-job alerts, and verified delivery outcomes correctly so cron history, retries, and failure counters reflect what actually happened. Fixes #72732, #50170, #43604, #68452, #60846, #72210, and #67172; follow-up to #54188; carries forward #43631, #68453, #72219, and #67186. Thanks @zNatix, @pixeldyn, @ChickenEggRoll, @SPFAdvisors, @anyech, @slideshow-dingo, @hatemclawbot-collab, @xydigit-sj, @oc-gh-dr, @hclsys, and @1yihui.</li>
<li>Cron/routing: preserve direct Telegram thread/account IDs, explicit Discord <code>user:</code>/<code>channel:</code> delivery targets, and <code>session:<id></code> failure-destination routing so reminders, cron announcements, and failure alerts keep the intended recipient kind across direct and group chats. Fixes #44270; refs #62777; carries forward #44325, #44351, #44412, #72657, #68535, and #62798. Thanks @RunMintOn, @arkyu2077, @0xsline, @vincentkoc, @slideshow-dingo, @likewen-tech, and @neeravmakwana.</li>
<li>Subagents: keep the delegated task only in the subagent system prompt and send a short initial kickoff message, avoiding duplicate task tokens while preserving multiline task formatting. Fixes #72019; carries forward #72053. Thanks @Wizongod and @ly85206559.</li>
<li>Onboarding/GitHub Copilot: add manifest-owned <code>--github-copilot-token</code> support for non-interactive setup, including env fallback, tokenRef storage in ref mode, saved-profile reuse, and current Copilot default-model wiring. Refs #50002 and supersedes #50003. Thanks @scottgl9.</li>
<li>Gateway/install: add a validated <code>--wrapper</code>/<code>OPENCLAW_WRAPPER</code> service install path that persists executable LaunchAgent/systemd wrappers across forced reinstalls, updates, and doctor repairs instead of falling back to raw node/bun <code>ProgramArguments</code>. Fixes #69400. (#72445) Thanks @willtmc.</li>
<li>Plugins: fail plugin registration when loader-owned acceptance gates reject missing hook names or memory-only capability registration from non-memory plugins, surfacing the issue through plugin status and doctor instead of silently dropping the registration. Fixes #72459. Thanks @amknight.</li>
<li>macOS Gateway: write launchd services with a state-dir <code>WorkingDirectory</code>, use a durable state-dir temp path instead of freezing macOS session <code>TMPDIR</code>, create that temp directory before bootstrap, and label abort-shaped launchd exits as <code>SIGABRT/abort</code> in status output. Fixes #53679 and #70223; refs #71848. Thanks @dlturock, @stammi922, and @palladius.</li>
<li>Control UI/update: make <code>Update now</code> require a real gateway process replacement, report skipped/error update outcomes with stable reasons, and verify the running gateway version after restart so global installs cannot silently keep old code in memory. Fixes #62492; addresses #64892 and #63562. Thanks @IAMSamuelRodda.</li>
<li>Exec approvals: accept runtime-owned <code>source: "allow-always"</code> and <code>commandText</code> allowlist metadata in gateway and node approval-set payloads so Control UI round-trips no longer fail with <code>unexpected property 'source'</code>. Fixes #60000; carries forward #60064. Thanks @sd1471123, @sharkqwy, and @luoyanglang.</li>
<li>Exec/node: skip approval-plan preparation for full-trust <code>host=node</code> runs so interpreter and script commands no longer fail with <code>SYSTEM_RUN_DENIED: approval cannot safely bind</code> when effective policy is <code>security=full</code> and <code>ask=off</code>. Fixes #48457 and duplicate #69251. Thanks @ajtran303, @jaserNo1, @Blakeshannon, @lesliefag, and @AvIsBeastMC.</li>
<li>Exec/node: synthesize a local approval plan when a paired node advertises <code>system.run</code> without <code>system.run.prepare</code>, unblocking approval-required <code>host=node</code> exec on current macOS companion nodes while preserving remote prepare for node hosts that support it. Fixes #37591 and duplicate #66839; carries forward #69725. Thanks @soloclz.</li>
<li>Memory/QMD: prefer QMD's <code>--mask</code> collection pattern flag so root memory indexing stays scoped to <code>MEMORY.md</code> instead of widening to every markdown file in the workspace. Fixes #65480; supersedes #65481 and #66259. Thanks @ccage-simp, @Bortlesboat, @seank-com, and @crazyscience.</li>
<li>Memory/doctor: treat the specific <code>gateway timeout after ...</code> gateway memory probe result as inconclusive instead of reporting embeddings not ready, while preserving warnings for explicit failures. Fixes #44426; carries forward #46576 with the Greptile review feedback applied. Thanks Cengiz (@ghost).</li>
<li>Gateway/startup: defer QMD, core request handlers, setup wizard, CLI outbound senders, plugin HTTP routes, chat/session projection, node session runtime validation, embedded-run activity reads, MCP loopback server imports, channel runtime helpers, HTTP/canvas/plugin auth helpers, isolated cron imports, and hook dispatch parsing until their request or shutdown paths, while making plain <code>gateway status</code> use a parse-only config snapshot so no-plugin boots and status reads avoid broad runtime fanout. Thanks @vincentkoc.</li>
<li>Lobster/Gateway: memoize repeated Ajv schema compilation before loading the embedded Lobster runtime so scheduled workflows and <code>llm.invoke</code> loops stop growing gateway heap on content-identical schemas. Fixes #71148. Thanks @cmi525, @vsolaz, and @vincentkoc.</li>
<li>Codex harness: normalize cached input tokens before session/context accounting so prompt cache reads are not double-counted in <code>/status</code>, <code>session_status</code>, or persisted <code>sessionEntry.totalTokens</code>. Fixes #69298. Thanks @richardmqq.</li>
<li>Hooks/session-memory: use the host local timezone for memory filenames, fallback timestamp slugs, and markdown headers instead of UTC dates. Fixes #46703. (#46721) Thanks @Astro-Han.</li>
<li>Gateway health: preserve live runtime-backed channel/account state in <code>gateway.health</code> snapshots and cached refreshes while keeping raw probe payloads on sensitive/admin paths only. (#39921, #42586, #46527, #52770, #42543) Thanks @FAL1989, @rstar327, @0xble, and @ajayr.</li>
<li>Feishu: extract quoted/replied interactive-card text across schema 1.0, schema 2.0, i18n, template-variable, and post-format fallback shapes without carrying broad generated/config churn from related parser experiments. (#38776, #60383, #42218, #45936) Thanks @lishuaigit, @lskun, @just2gooo, and @Br1an67.</li>
<li>Telegram/agents: hide raw failed write/edit warning messages in Telegram when the assistant already explicitly acknowledges the failed action, while keeping warnings when the reply claims success or omits the failure; #39406 remains the broader configurable delivery-policy follow-up. Fixes #51065; covers #39631. Thanks @Bartok9 and @Bortlesboat.</li>
<li>Exec approvals: accept a symlinked <code>OPENCLAW_HOME</code> as the trusted approvals root while still rejecting symlinked <code>.openclaw</code> path components below it. (#64663) Thanks @FunJim.</li>
<li>Logging: add top-level <code>hostname</code>, flattened <code>message</code>, and available <code>agent_id</code>, <code>session_id</code>, and <code>channel</code> fields to file-log JSONL records for multi-agent filtering without removing existing structured log arguments. Fixes #51075. Thanks @stevengonsalvez.</li>
<li>ACP: route server logs to stderr before Gateway config/bootstrap work so ACP stdout remains JSON-RPC only for IDE integrations. Fixes #49060. Thanks @Hollychou924.</li>
<li>Logging: propagate internal request trace scopes through Gateway HTTP requests and WebSocket frames so file logs, diagnostic events, agent run traces, model-call traces, OTEL spans, and trusted provider <code>traceparent</code> headers share a correlatable <code>traceId</code> without logging raw request or model content. Fixes #40353. Thanks @liangruochong44-ui.</li>
<li>Diagnostics/OTEL: capture privacy-safe model-call request payload bytes, streamed response bytes, first-response latency, and total duration in diagnostic events, plugin hooks, stability snapshots, and OTEL model-call spans/metrics without logging raw model content. Fixes #33832. Thanks @wwh830.</li>
<li>Logging: write validated diagnostic trace context as top-level <code>traceId</code>, <code>spanId</code>, <code>parentSpanId</code>, and <code>traceFlags</code> fields in file-log JSONL records so traced requests and model calls are easier to correlate in log processors. Refs #40353. Thanks @liangruochong44-ui.</li>
<li>Logging/sessions: apply configured redaction patterns to persisted session transcript text and accept escaped character classes in safe custom redaction regexes, so transcript JSONL no longer keeps matching sensitive text in the clear. Fixes #42982. Thanks @panpan0000.</li>
<li>Agents/sessions: let <code>sessions_spawn runtime="subagent"</code> ignore ACP-only <code>streamTo</code> and <code>resumeSessionId</code> fields while keeping ACP passthrough and documenting <code>streamTo</code> as ACP-only. Fixes #43556 and #63120; covers #56326, #61724, #64714, and #67248; carries forward #68397, #65282, #58686, #56342, and #40102. Thanks @skernelx, @damselem, @Br1an67, @Mintalix, @IsaacAPerez, @vvitovec, @Sanjays2402, @shenkq97, and @1034378361.</li>
<li>Providers/Ollama: honor <code>/api/show</code> capabilities, custom Modelfile <code>PARAMETER num_ctx</code>, configured provider/model context defaults, whitelisted native params such as <code>temperature</code>, <code>top_p</code>, and <code>think</code>, and native thinking effort levels so local models get accurate tools, context, and thinking behavior without forcing full-context VRAM use. Fixes #64710, duplicate #65343, #68344, #44550, #52206, #49684, #68662, #48010, #71584, and #44786; supersedes #69464; carries forward #44955. Thanks @yuan-b, @netherby, @xilopaint, @Diyforfun2026, @neeravmakwana, @taitruong, @armi0024, @LokiCode404, @zhouZcong, @dshenster-byte, @tangzhi, @pandego, @maweibin, @Adam-Researchh, @EmpireCreator, @g0st1n, and @voltwake.</li>
<li>Image tool/media: honor <code>tools.media.image.timeoutSeconds</code> and matching per-model image timeouts in explicit image analysis, including the MiniMax VLM fallback path, so slow local vision models are not capped by hardcoded 30s/60s aborts. Fixes #67889; supersedes #67929. Thanks @AllenT22 and @alchip.</li>
<li>Providers/Ollama: strip custom provider prefixes before native chat/embedding requests, skip ambient localhost discovery unless config/auth opts in, handle custom remote <code>api: "ollama"</code> providers, accept OpenAI SDK-style <code>baseURL</code>, scope synthetic local auth and embedding bearer headers to declared host boundaries, resolve custom-named local providers for subagents, add provider-scoped model request timeouts, preserve explicit input modalities, and document <code>params.keep_alive</code> plus local/LAN/cloud/multi-host/web-search/embedding/thinking setup recipes. Fixes #72353, #56939, #62533, #43945, #64541, #68796, and #39690; supersedes #57116, #62549, #69261, #69857, #65143, and #66511; refs #43945; carries forward #43224 and #39785. Thanks @maximus-dss, @hclsys, @IanxDev, @tsukhani, @issacthekaylon, @Julien-BKK, @Linux2010, @hyspacex, @maxramsay, @Meli73, @LittleJakub, @Juankcba, @uninhibite-scholar, @yfge, @Skrblik, and @Mriris.</li>
<li>Providers/Ollama: move memory embeddings to <code>/api/embed</code> with batched <code>input</code>, route local web search through Ollama's signed daemon proxy while keeping cloud auth scoped, treat Ollama memory embeddings as key-optional in doctor, and keep model usage visible by estimating native transcript usage when <code>/api/chat</code> omits counters. Fixes #39983, #69132, and #46584; carries forward #39112. Thanks @sskkcc, @LiudengZhang, @yoon1012, @hyspacex, @fengly78, and @TylonHH.</li>
<li>Agents/Ollama: parse stringified native tool-call arguments, retry native empty/thinking-only turns, accept already-prefixed LLM task model overrides, apply provider-owned replay normalization for Cloud models, validate explicit <code>--thinking max</code>, show resolved thinking defaults in Control UI, and include configured provider models in <code>models list --provider</code>. Fixes #69735, #50052, #71697, #71584, #72407, and #65207; supersedes #69910; carries forward #66552 and #61223. Thanks @rongshuzhao, @yfge, @L3G, @ralphy-maplebots, @Hollychou924, @ismael-81, @g0st1n, @NotecAG, and @drzeast-png.</li>
<li>Providers/PDF/Ollama: add bounded network timeouts for Ollama model pulls and native Anthropic/Gemini PDF analysis requests so unresponsive provider endpoints no longer hang sessions indefinitely. Fixes #54142; supersedes #54144 and #54145. Thanks @jinduwang1001-max and @arkyu2077.</li>
<li>Docker/QA: add observability coverage to the normal Docker aggregate so QA-lab OTEL and Prometheus diagnostics run inside Docker. Thanks @vincentkoc.</li>
<li>Auto-reply: poison inbound message dedupe after replay-unsafe provider/runtime failures so retries stay safe before visible progress but cannot duplicate messages after block output, tool side effects, or session progress. Fixes #69303; keeps #58549 and #64606 as duplicate validation. Thanks @martingarramon, @NikolaFC, and @zeroth-blip.</li>
<li>Agents/model fallback: keep auto-persisted fallback model overrides selected across turns until <code>/new</code> or reset clears them, avoiding repeated probes of a known-bad primary while <code>/status</code> shows the selected and active models. Thanks @kibedu.</li>
<li>Agents/model fallback: jump directly to a known later live-session model redirect instead of walking unrelated fallback candidates, while preserving the already-landed live-session/fallback loop guard. Fixes #57471; related loop family already closed via #58496. Thanks @yuxiaoyang2007-prog.</li>
<li>Gateway/Bonjour: keep @homebridge/ciao cancellation handlers registered across advertiser restarts so late probing cancellations cannot crash Linux and other mDNS-churned gateways.</li>
<li>Plugins/startup: load the default <code>memory-core</code> slot during Gateway startup when permitted so active-memory recall can call <code>memory_search</code> and <code>memory_get</code> without requiring an explicit <code>plugins.slots.memory</code> entry, while preserving <code>plugins.slots.memory: "none"</code>.</li>
<li>Plugins/CLI: prefer native require for compiled bundled plugin JavaScript before jiti so read-only config, status, device, and node commands avoid unnecessary transform overhead on slow hosts. Fixes #62842. Thanks @Effet.</li>
<li>Plugins/compat/CLI: inventory doctor-side deprecation migrations separately from runtime plugin compatibility, add dated records for legacy extension-api, memory registration, provider hook/type aliases, runtime aliases, channel SDK helpers, and approval/test utility shims, refresh the persisted registry after managed plugin removals, make plugin install/uninstall writes conflict-aware, clear stale denylists, and fail tracked plugin/hook updates or unloadable package installs instead of leaving stale state. Thanks @vincentkoc.</li>
<li>WebChat/Control UI: support non-video file attachments in chat uploads while preserving the existing image attachment path and MIME-sniff fallback for generic image uploads. (#70947) Thanks @IAMSamuelRodda.</li>
<li>Skills/memory: restore Chokidar v5 hot reloads by watching concrete skill and memory roots with filters, including SKILL.md removals and deleted skill folders without broad workspace recursion. Fixes #27404, #33585, and #41606. Thanks @shelvenzhou, @08820048, and @rocke2020.</li>
<li>Gateway/chat: keep duplicate attachment-backed <code>chat.send</code> retries with the same idempotency key on the documented in-flight path so aborts still target the real active run. Fixes #70139. Thanks @Feelw00.</li>
<li>Gateway/session rows: report the same config-resolved thinking default that runtime sessions use, including global and per-agent defaults, so Control UI and TUI default labels stay aligned. (#71779, #70981, #71033, #70302) Thanks @chen-zhang-cs-code, @SymbolStar, and @cholaolu-boop.</li>
<li>Plugins: share package entrypoint resolution between install and discovery, reject mismatched <code>runtimeExtensions</code>, and cache bundled runtime-dependency manifest reads during scans.</li>
<li>WhatsApp/Web: keep quiet but healthy linked-device sessions connected by basing the watchdog on WhatsApp Web transport activity, while retaining a longer app-silence cap so frame activity cannot mask a stuck session forever. Fixes #70678; carries forward the focused #71466 approach and keeps #63939 as related configurable-timeout follow-up. Thanks @vincentkoc and @oromeis.</li>
<li>Discord/gateway: count failed health-monitor restart attempts toward cooldown and hourly caps, and evict stale account lifecycle state during channel reloads so repeated Discord gateway recovery cannot loop on old status. Fixes #38596. (#40413) Thanks @jellyAI-dev and @vashquez.</li>
<li>Cron/context engine: run isolated cron jobs under run-scoped context-engine session keys so prior runs of the same job are not inherited unless the job is explicitly session-bound. (#72292) Thanks @jalehman.</li>
<li>Control UI: localize command palette labels, categories, skill shortcuts, footer hints, and connect-command copy labels while preserving localized command palette search matching. (#61130, #61119) Thanks @rubensfox20.</li>
<li>Plugins/memory-lancedb: request float embedding responses from OpenAI-compatible servers so local providers that default SDK requests to base64 no longer return dimension-mismatched LanceDB vectors while preserving configured dimensions. Fixes #45982. (#59048, #46069, #45986) Thanks @deep-introspection, @xiaokhkh, @caicongyang, and @thiswind.</li>
<li>Plugins/memory-lancedb: advance auto-capture cursors per session only after messages are processed or intentionally skipped, retry failed messages, survive compacted histories, and clear cursor state on session end. Fixes #71349; carries forward #42083. Thanks @as775116191.</li>
<li>Plugins/memory-core: respect configured memory-search embedding concurrency during non-batch indexing so local Ollama embedding backends can serialize indexing instead of flooding the server. Fixes #66822. (#66931) Thanks @oliviareid-svg and @LyraInTheFlesh.</li>
<li>Docker/update smoke: keep the package-derived update-channel fixture on package-shipped files and make its UI build stub create the asset the updater verifies. Thanks @vincentkoc.</li>
<li>Gateway/models: repair legacy <code>models.providers.*.api = "openai"</code> config values to <code>openai-completions</code>, and skip providers with future stale API enum values during startup instead of bricking the gateway. Fixes #72477. (#72542) Thanks @JooyoungChoi14 and @obviyus.</li>
<li>Gateway/skills: redact <code>apiKey</code> and secret-named <code>env</code> values from the <code>skills.update</code> RPC response to prevent leaking credentials into WebSocket traffic, client logs, or session transcripts. Config is still written to disk in full; only the response payload is redacted. (#69998) Thanks @Ziy1-Tan.</li>
<li>Plugins/CLI: let flag-driven <code>openclaw channels add</code> install the selected channel plugin from its default source without opening an interactive prompt, fixing published npm Telegram setup in stdin-closed automation.</li>
<li>Onboarding/setup: keep first-run config reads, plugin compatibility notices, OpenAI Codex auth, post-auth default-model policy lookup, skip-auth, provider-scoped model pickers, and post-model sanity checks on cold manifest/setup metadata unless the user chooses to browse all models, avoiding full plugin/provider runtime loads between prompts. Thanks @shakkernerd.</li>
<li>Gateway/Bonjour: suppress known @homebridge/ciao cancellation and network assertion failures through scoped process handlers so malformed mDNS packets or restricted VPS networking disable/restart Bonjour instead of crashing the gateway. Fixes #67578. Thanks @zenassist26-create.</li>
<li>Discord: keep late clicks on already-resolved exec approval buttons quiet when elevated mode auto-resolved the request, while still surfacing real approval submission failures. Fixes #66906. Thanks @rlerikse.</li>
<li>Telegram: send a fresh final message for long-lived preview-streamed replies so the visible Telegram timestamp reflects completion time instead of the preview creation time. Thanks @rubencu.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.4.26/OpenClaw-2026.4.26.zip" length="48222029" type="application/octet-stream" sparkle:edSignature="6wgFZUyyU09Y6nvD9T1Ufq7Plo0Wzfg+L9r80DCaNMMuwebcKWAsMVSP3RvhRhTxVMax8toUDYg3gb/vOiE5BA=="/>
</item>
</channel>
</rss>

View File

@@ -65,8 +65,8 @@ android {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026043000
versionName = "2026.4.30"
versionCode = 2026050300
versionName = "2026.5.3"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")

View File

@@ -1,5 +1,13 @@
# OpenClaw iOS Changelog
## 2026.5.3 - 2026-05-03
Maintenance update for the current OpenClaw development release.
## 2026.5.2 - 2026-05-02
Maintenance update for the current OpenClaw development release.
## 2026.4.30 - 2026-04-30
Maintenance update for the current OpenClaw development release.

View File

@@ -2,8 +2,8 @@
// Source of truth: apps/ios/version.json
// Generated by scripts/ios-sync-versioning.ts.
OPENCLAW_IOS_VERSION = 2026.4.30
OPENCLAW_MARKETING_VERSION = 2026.4.30
OPENCLAW_IOS_VERSION = 2026.5.3
OPENCLAW_MARKETING_VERSION = 2026.5.3
OPENCLAW_BUILD_VERSION = 1
#include? "../build/Version.xcconfig"

View File

@@ -116,4 +116,4 @@ WatchExtension/Sources/WatchInboxView.swift
../shared/OpenClawKit/Sources/OpenClawKit/StoragePaths.swift
../shared/OpenClawKit/Sources/OpenClawKit/SystemCommands.swift
../shared/OpenClawKit/Sources/OpenClawKit/TalkDirective.swift
../../Swabble/Sources/SwabbleKit/WakeWordGate.swift
../swabble/Sources/SwabbleKit/WakeWordGate.swift

View File

@@ -14,7 +14,7 @@ packages:
OpenClawKit:
path: ../shared/OpenClawKit
Swabble:
path: ../../Swabble
path: ../swabble
schemes:
OpenClaw:
@@ -71,7 +71,7 @@ targets:
exit 1
fi
swiftformat --lint --config "$SRCROOT/../../.swiftformat" \
--unexclude "$SRCROOT/Sources,$SRCROOT/ShareExtension,$SRCROOT/ActivityWidget,$SRCROOT/WatchExtension,$SRCROOT/../shared/OpenClawKit,$SRCROOT/../../Swabble" \
--unexclude "$SRCROOT/Sources,$SRCROOT/ShareExtension,$SRCROOT/ActivityWidget,$SRCROOT/WatchExtension,$SRCROOT/../shared/OpenClawKit,$SRCROOT/../swabble" \
--filelist "$SRCROOT/SwiftSources.input.xcfilelist"
- name: SwiftLint
basedOnDependencyAnalysis: false

View File

@@ -1,3 +1,3 @@
{
"version": "2026.4.30"
"version": "2026.5.3"
}

View File

@@ -21,7 +21,7 @@ let package = Package(
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.9.0"),
.package(url: "https://github.com/steipete/Peekaboo.git", exact: "3.0.0-beta4"),
.package(path: "../shared/OpenClawKit"),
.package(path: "../../Swabble"),
.package(path: "../swabble"),
],
targets: [
.target(

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

Before

Width:  |  Height:  |  Size: 990 KiB

After

Width:  |  Height:  |  Size: 990 KiB

View File

@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.4.30</string>
<string>2026.5.3</string>
<key>CFBundleVersion</key>
<string>2026043000</string>
<string>2026050300</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -1464,6 +1464,36 @@ public struct SessionsListParams: Codable, Sendable {
}
}
public struct SessionsCleanupParams: Codable, Sendable {
public let agent: String?
public let allagents: Bool?
public let enforce: Bool?
public let activekey: String?
public let fixmissing: Bool?
public init(
agent: String?,
allagents: Bool?,
enforce: Bool?,
activekey: String?,
fixmissing: Bool?)
{
self.agent = agent
self.allagents = allagents
self.enforce = enforce
self.activekey = activekey
self.fixmissing = fixmissing
}
private enum CodingKeys: String, CodingKey {
case agent
case allagents = "allAgents"
case enforce
case activekey = "activeKey"
case fixmissing = "fixMissing"
}
}
public struct SessionsPreviewParams: Codable, Sendable {
public let keys: [String]
public let limit: Int?
@@ -1486,6 +1516,28 @@ public struct SessionsPreviewParams: Codable, Sendable {
}
}
public struct SessionsDescribeParams: Codable, Sendable {
public let key: String
public let includederivedtitles: Bool?
public let includelastmessage: Bool?
public init(
key: String,
includederivedtitles: Bool?,
includelastmessage: Bool?)
{
self.key = key
self.includederivedtitles = includederivedtitles
self.includelastmessage = includelastmessage
}
private enum CodingKeys: String, CodingKey {
case key
case includederivedtitles = "includeDerivedTitles"
case includelastmessage = "includeLastMessage"
}
}
public struct SessionsResolveParams: Codable, Sendable {
public let key: String?
public let sessionid: String?
@@ -2752,6 +2804,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
public let channels: [String: AnyCodable]
public let channelaccounts: [String: AnyCodable]
public let channeldefaultaccountid: [String: AnyCodable]
public let eventloop: [String: AnyCodable]?
public init(
ts: Int,
@@ -2762,7 +2815,8 @@ public struct ChannelsStatusResult: Codable, Sendable {
channelmeta: [[String: AnyCodable]]?,
channels: [String: AnyCodable],
channelaccounts: [String: AnyCodable],
channeldefaultaccountid: [String: AnyCodable])
channeldefaultaccountid: [String: AnyCodable],
eventloop: [String: AnyCodable]?)
{
self.ts = ts
self.channelorder = channelorder
@@ -2773,6 +2827,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
self.channels = channels
self.channelaccounts = channelaccounts
self.channeldefaultaccountid = channeldefaultaccountid
self.eventloop = eventloop
}
private enum CodingKeys: String, CodingKey {
@@ -2785,6 +2840,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
case channels
case channelaccounts = "channelAccounts"
case channeldefaultaccountid = "channelDefaultAccountId"
case eventloop = "eventLoop"
}
}
@@ -4272,6 +4328,7 @@ public struct CronRunLogEntry: Codable, Sendable {
public let deliveryerror: String?
public let sessionid: String?
public let sessionkey: String?
public let runid: String?
public let runatms: Int?
public let durationms: Int?
public let nextrunatms: Int?
@@ -4292,6 +4349,7 @@ public struct CronRunLogEntry: Codable, Sendable {
deliveryerror: String?,
sessionid: String?,
sessionkey: String?,
runid: String?,
runatms: Int?,
durationms: Int?,
nextrunatms: Int?,
@@ -4311,6 +4369,7 @@ public struct CronRunLogEntry: Codable, Sendable {
self.deliveryerror = deliveryerror
self.sessionid = sessionid
self.sessionkey = sessionkey
self.runid = runid
self.runatms = runatms
self.durationms = durationms
self.nextrunatms = nextrunatms
@@ -4332,6 +4391,7 @@ public struct CronRunLogEntry: Codable, Sendable {
case deliveryerror = "deliveryError"
case sessionid = "sessionId"
case sessionkey = "sessionKey"
case runid = "runId"
case runatms = "runAtMs"
case durationms = "durationMs"
case nextrunatms = "nextRunAtMs"
@@ -5116,6 +5176,7 @@ public struct UpdateRunParams: Codable, Sendable {
public let sessionkey: String?
public let deliverycontext: [String: AnyCodable]?
public let note: String?
public let continuationmessage: String?
public let restartdelayms: Int?
public let timeoutms: Int?
@@ -5123,12 +5184,14 @@ public struct UpdateRunParams: Codable, Sendable {
sessionkey: String?,
deliverycontext: [String: AnyCodable]?,
note: String?,
continuationmessage: String?,
restartdelayms: Int?,
timeoutms: Int?)
{
self.sessionkey = sessionkey
self.deliverycontext = deliverycontext
self.note = note
self.continuationmessage = continuationmessage
self.restartdelayms = restartdelayms
self.timeoutms = timeoutms
}
@@ -5137,6 +5200,7 @@ public struct UpdateRunParams: Codable, Sendable {
case sessionkey = "sessionKey"
case deliverycontext = "deliveryContext"
case note
case continuationmessage = "continuationMessage"
case restartdelayms = "restartDelayMs"
case timeoutms = "timeoutMs"
}

View File

@@ -1464,6 +1464,36 @@ public struct SessionsListParams: Codable, Sendable {
}
}
public struct SessionsCleanupParams: Codable, Sendable {
public let agent: String?
public let allagents: Bool?
public let enforce: Bool?
public let activekey: String?
public let fixmissing: Bool?
public init(
agent: String?,
allagents: Bool?,
enforce: Bool?,
activekey: String?,
fixmissing: Bool?)
{
self.agent = agent
self.allagents = allagents
self.enforce = enforce
self.activekey = activekey
self.fixmissing = fixmissing
}
private enum CodingKeys: String, CodingKey {
case agent
case allagents = "allAgents"
case enforce
case activekey = "activeKey"
case fixmissing = "fixMissing"
}
}
public struct SessionsPreviewParams: Codable, Sendable {
public let keys: [String]
public let limit: Int?
@@ -1486,6 +1516,28 @@ public struct SessionsPreviewParams: Codable, Sendable {
}
}
public struct SessionsDescribeParams: Codable, Sendable {
public let key: String
public let includederivedtitles: Bool?
public let includelastmessage: Bool?
public init(
key: String,
includederivedtitles: Bool?,
includelastmessage: Bool?)
{
self.key = key
self.includederivedtitles = includederivedtitles
self.includelastmessage = includelastmessage
}
private enum CodingKeys: String, CodingKey {
case key
case includederivedtitles = "includeDerivedTitles"
case includelastmessage = "includeLastMessage"
}
}
public struct SessionsResolveParams: Codable, Sendable {
public let key: String?
public let sessionid: String?
@@ -2752,6 +2804,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
public let channels: [String: AnyCodable]
public let channelaccounts: [String: AnyCodable]
public let channeldefaultaccountid: [String: AnyCodable]
public let eventloop: [String: AnyCodable]?
public init(
ts: Int,
@@ -2762,7 +2815,8 @@ public struct ChannelsStatusResult: Codable, Sendable {
channelmeta: [[String: AnyCodable]]?,
channels: [String: AnyCodable],
channelaccounts: [String: AnyCodable],
channeldefaultaccountid: [String: AnyCodable])
channeldefaultaccountid: [String: AnyCodable],
eventloop: [String: AnyCodable]?)
{
self.ts = ts
self.channelorder = channelorder
@@ -2773,6 +2827,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
self.channels = channels
self.channelaccounts = channelaccounts
self.channeldefaultaccountid = channeldefaultaccountid
self.eventloop = eventloop
}
private enum CodingKeys: String, CodingKey {
@@ -2785,6 +2840,7 @@ public struct ChannelsStatusResult: Codable, Sendable {
case channels
case channelaccounts = "channelAccounts"
case channeldefaultaccountid = "channelDefaultAccountId"
case eventloop = "eventLoop"
}
}
@@ -4272,6 +4328,7 @@ public struct CronRunLogEntry: Codable, Sendable {
public let deliveryerror: String?
public let sessionid: String?
public let sessionkey: String?
public let runid: String?
public let runatms: Int?
public let durationms: Int?
public let nextrunatms: Int?
@@ -4292,6 +4349,7 @@ public struct CronRunLogEntry: Codable, Sendable {
deliveryerror: String?,
sessionid: String?,
sessionkey: String?,
runid: String?,
runatms: Int?,
durationms: Int?,
nextrunatms: Int?,
@@ -4311,6 +4369,7 @@ public struct CronRunLogEntry: Codable, Sendable {
self.deliveryerror = deliveryerror
self.sessionid = sessionid
self.sessionkey = sessionkey
self.runid = runid
self.runatms = runatms
self.durationms = durationms
self.nextrunatms = nextrunatms
@@ -4332,6 +4391,7 @@ public struct CronRunLogEntry: Codable, Sendable {
case deliveryerror = "deliveryError"
case sessionid = "sessionId"
case sessionkey = "sessionKey"
case runid = "runId"
case runatms = "runAtMs"
case durationms = "durationMs"
case nextrunatms = "nextRunAtMs"
@@ -5116,6 +5176,7 @@ public struct UpdateRunParams: Codable, Sendable {
public let sessionkey: String?
public let deliverycontext: [String: AnyCodable]?
public let note: String?
public let continuationmessage: String?
public let restartdelayms: Int?
public let timeoutms: Int?
@@ -5123,12 +5184,14 @@ public struct UpdateRunParams: Codable, Sendable {
sessionkey: String?,
deliverycontext: [String: AnyCodable]?,
note: String?,
continuationmessage: String?,
restartdelayms: Int?,
timeoutms: Int?)
{
self.sessionkey = sessionkey
self.deliverycontext = deliverycontext
self.note = note
self.continuationmessage = continuationmessage
self.restartdelayms = restartdelayms
self.timeoutms = timeoutms
}
@@ -5137,6 +5200,7 @@ public struct UpdateRunParams: Codable, Sendable {
case sessionkey = "sessionKey"
case deliverycontext = "deliveryContext"
case note
case continuationmessage = "continuationMessage"
case restartdelayms = "restartDelayMs"
case timeoutms = "timeoutMs"
}

View File

@@ -58,7 +58,7 @@ private enum TalkConfigContractFixtureLoader {
private static func findFixtureURL(startingAt fileURL: URL) throws -> URL {
var directory = fileURL.deletingLastPathComponent()
while directory.path != "/" {
let candidate = directory.appendingPathComponent("test-fixtures/talk-config-contract.json")
let candidate = directory.appendingPathComponent("test/fixtures/talk-config-contract.json")
if FileManager.default.fileExists(atPath: candidate.path) {
return candidate
}

Some files were not shown because too many files have changed in this diff Show More